webpack基础(三)--多页面打包

3,995 阅读2分钟

一、多页应用(MPA)

单页应用SPA:只有一个html文档,通过js感知url的变化,js动态的将当前页面内容清除掉,然后将下一个页面的内容挂载到页面上,这就是单页应用,每次跳转了解不需要请求新的html文档;

多页应用MPA:每一次页面跳转,服务器都会返回一个新的html文档,这种类型的网站就是多页网站,也叫多页应用。

二、基本思路

每一个页面对应一个entry和一个html-webpack-plugin,代码示例如下:


module.exports = {
    entry:{
        index:'./src/index/index.js',
        search:'./src/search/index.js'
    }
}

缺点:每次新增或删除页面都需要修改webpack配置,页面过多时,会写非常多的html-webpack-plugin配置,造成webpack配置文件冗长,不利于维护。

三、通用方案

每次打包时动态获取entry,根据entry信息自动设置html-webpack-plugin数量。

页面内容全部放在src文件夹下面,并且每一个页面单独一个文件夹,htmljs文件全部命名为index,使用glob模块的glob.sync动态获取src文件夹下面的各个子文件夹中的index.js文件作为每个页面的入口文件。

获取所有的入口文件路径:

const entryFiles = glob.sync(path.join(__dirname,'./src/*/index.js'))

遍历入口文件集合创建html-webpack-plugin设置:

const entry = {};//入口对象
const htmlWebpackPlugins = [];//html-webpack-plugin设置集合
Object.keys(entryFiles).map(index => {
    const entryFil = entryFiles[index];
    //获取文件夹名称
    const match = entryFil.match(/src\/(.*)\/index\.js/);
    const pathname = match && match[1];
    //设置入口对象
    entry[pathname] = entryFil;
    //设置html-webpack-plugin设置
    htmlWebpackPlugins.push(
        new HtmlWebpackPlugin({
            template:path.join(__dirname,`src/${pathname}/index.html`),
            filename:`${pathname}.html`,
            chunks:[pathname],
            inject:true,
            minify:{
                html5:true,
                collapseWhitespace:true,
                preserveLineBreaks:false,
                minifyJS:true,
                minifyCSS:true,
                removeComments:false
            }
        })
    )
})

修改webpack配置:

module.exports = {
    entry:entry,
    ...
    plugins:[
        ...
    ].concat(htmlWebpackPlugins)
}

四、完整代码

const path = require('path');
const glob = require('glob');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const setMpa = () => {
    const entry = {};//入口对象
    const htmlWebpackPlugins = [];//html-webpack-plugin配置
    //获取入口文件
    const entryFiles = glob.sync(path.join(__dirname,'./src/*/index.js'));
    
    Object.keys(entryFiles).map(index => {
        const entryFil = entryFiles[index];
        //获取文件夹名称
        const match = entryFil.match(/src\/(.*)\/index\.js/);
        const pathname = match && match[1];
        //配置入口文件对象
        entry[pathname] = entryFil;
        //配置html-webpack-plugin
        htmlWebpackPlugins.push(
            new HtmlWebpackPlugin({
                template:path.join(__dirname,`src/${pathname}/index.html`),
                filename:`${pathname}.html`,
                chunks:[pathname],
                inject:true,
                minify:{
                    html5:true,
                    collapseWhitespace:true,
                    preserveLineBreaks:false,
                    minifyJS:true,
                    minifyCSS:true,
                    removeComments:false
                }
            })
        )
    });
    
    return {
        entry,
        htmlWebpackPlugins
    }
};

const { entry, htmlWebpackPlugins } = setMpa();
module.exports = {
    entry:entry,
    output:{
        path:path.join(__dirname,'dist'),
        filename:'[name]_[chunkhash:5].js'
    },
    mode:'production',
    module:{
        rules:[
            ...
        ]
    },
    plugins:[
        new CleanWebpackPlugin(),
    ].concat(htmlWebpackPlugins)
}

系列链接: