lanbos'blog

webpack多页面项目实践

尽管当下SPA横行,但是多页面项目依然有其存在的意义,webpack这件工具基本是为了SPA而专门准备的,网上看到很多利用webpack构建多页面的教程都是用gulp来配合使用的,在网上看大了一个思路只需对webpack简单配置一下就能实现大多数情景下的多页面项目。本文在vue-cli2.0的基础上做了对多页面vue项目的扩充。

实现思路

首先webpack的思想是用js来构建项目的一切,即html只有一个外壳载体,项目的入口文件和执行文件为js,多页面项目肯定是多个入口文件。然后对不同的页面引入不同的入口文件。即:

  1. 设置weback.base.coonf.js中的entry,从单一入口变为多入口配置项
  2. 在dev和prod的配置项中利用HtmlWebpackPlugin插件来对各个页面引入不同的入口js文件

    目录生成

    第一层目录概览:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ├── README.md
    ├── build
    ├── config
    ├── dist
    ├── index.html
    ├── node_modules
    ├── package-lock.json
    ├── package.json
    ├── pages # 多页面html存放目录
    ├── src #主要源码
    └── static

src目录主要结构:

1
2
3
4
5
6
7
├── App.vue #外壳
├── assets # 静态自愿存放
├── components #组件目录
├── main.js #第一个入口文件保留
├── pages #其他页面入口文件存放处
├── router #路由
└── store #vuex相关

扩展工具方法

build/utils.js底部增加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 多页面设置
class SetPages{
constructor(){
this.pagesArr=[]
this.pagesDir=path.resolve(__dirname,'../pages/');
this.pages=[];
this.pagesEntrys={
app: './src/main.js',
};
}
init(){
this.pagesArr= fs.readdirSync(this.pagesDir);
this.pagesArr.forEach(v => {
let fName=path.basename(v, '.html');
let temp={
filename: "",
template: '',
chunks:['manifest','vendor',fName],//设置允许加载的模块
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}
temp.filename=path.resolve(__dirname, '../dist/'+v);
temp.template=path.resolve(__dirname,this.pagesDir+'/'+v);
this.pages.push(temp);
this.pagesEntrys[fName]=`./src/pages/${fName}.js`
});

}

}
let setPages=new SetPages();
setPages.init();
exports.setPages= setPages.pages;
exports.pagesEntrys=setPages.pagesEntrys;//设置各个入口js

该扩展方法主要目的就是读取pages目录下所有的文件名字,生成一个entry入口文件配置项,并去src/pages找到同名的js文件在html中引入。

在各配置文件下使用

  1. build/weback.base.coonf.js中使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    module.exports = {
    context: path.resolve(__dirname, '../'),
    entry: utils.pagesEntrys,//引入生成的入口文件配置项
    output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production' ?
    config.build.assetsPublicPath :
    config.dev.assetsPublicPath
    },
    ...
  2. build/weback.dev.coonf.jsbuild/weback.pod.coonf.js中都插入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 复制多页面任务
    if(utils.setPages.length>0){
    utils.setPages.forEach(v => {
    v.minify={}
    devWebpackConfig.plugins.push(
    new HtmlWebpackPlugin(v)
    )
    });
    }

多页面开发流程

在第一层目录pages中新建一个about.html文件,内容复制index.html中的即可,然后在util/pages目录下新建一个与之前生成的html同名的about.js,这个js文件就是一个页面的入口文件,在其中进行开发即可。打包时也会单独打包出一个about.js对应一个页面about.html

缺点

  1. 当页面中引入了过多的第三方库会造成打包出的vendor.js体积过大。解决方案为把不经常改变的第三方库单独用script cdn加载,如lodash,jquery等。强烈建议对element-ui等ui库一定要按需引入组件,否则很容易造成vendor过大。
  2. 打包时间很长,不仅是多页面,spa项目里webpack打包速度也是非常的慢,只是多页面项目更加明显而已,暂时没有好的解决方法,只能等webpack新版本解决

    参考

    重写webpack多页应用配置脚手架
    Webpack 打包优化之体积篇