Webpack4+ 多入口程序构建

其实,说实话这篇文章的由来也是有很多的原因在里面的。在这之前,我也做过不少的项目。有新的项目,也有旧的项目。通过对旧项目的不断研究,改进。再结合自己的理解,将新的构建应用到新的项目中。经过时间的积累,慢慢的就有了一套感觉上还比较适合的webpack前端构建规范。

那这里来说说,webpack4+构建上的一些事吧。

多入口的意思大概就是,访问不同页面的时候,主要的前端JS功能文件是不同的。最好的对比和区别就是SPA单页面应用,每个页面引入的文件都是同一份JS文件。

我期望的构建是:

  1. 一气呵成(编码过程爽不爽)
  2. 极大程度脱离后端语言限制(解耦)
  3. 多入口(多入口,多页面)

一气呵成,意味着项目从你执行git clone,拉取代码开始,直到你git push推送代码。这之间,所有与编码无关的,是一气呵成的,并不需要你过多的配置。希望做到的就是编码的极致体验。整个过程,期望开发人员关心的只有一件事,就是自己编写的代码是否OK。

那也意味着webpack构建需要做更多的事。

说起脱离后端语言,这并不是什么好事,只不过要看项目合不合适。在最近写的项目里面,使用的是vue + Node.js。使用vue ,一般意味着模版文件里面其他很少有Node.js模版(例如:jade,swig)代码,也很少有前端代码。也就是一个空壳页面,做过SPA单页面应用的应该比较熟悉。

那也就是这个空壳页面,其实和后端语言没有太大的耦合关系。那也意味着,我可以极大程度的做到前后端代码解耦。这是什么意思?

试想一下,自己在开发过程中,需要关注的无非就2个东西:页面,静态资源。编码上与后端有耦合的就是只有页面,就像上面说的,使用vue做SPA,其实页面里面其实并没有和后端有耦合。

也就说,这为前后端结构上解耦,提供了便利。前端所有资源可以独立出来,只要保证,通过构建之后,能将页面,静态资源生成到指定项目目录即可。

那构建这里就是由webpack来做。

上图中已经标明:

  1. client:是放前端资源目录
  2. server:是放后端资源的目录。这里假如后端为Node.js
  3. static:是静态资源目录。也就是js/css文件放置的地方

那这里就引出了一个值得先思考的问题,webapck构建的目的是什么?落实到工程项目里面,构建的目的又是什么?

结合上面的目录结构图,如果说webpack的目的是将静态资源打包编译;那么在工程上,就是将前端资源client目录资源通过webpack构建到指定的staticserver/views目录。

那这样是不是就做到了极大程度的解耦呢。

那如何在单入口的webpak构建工程上进行修改变为多入口构建工程?这就是今天这篇文章需要解决的问题,也是我一直以来需要解决的问题,也是写这篇文章的初衷。

面对这个多入口程序构建问题,这里先从当前现状说起吧。

注意:以下的所有内容都是在单入口的基础上进行讲述的,相关demo在这里:webpack案例

webpack构建现状

一直以来,webpack构建我只做了单入口构建。也就是大家熟悉的SPA。这也并没有影响到项目的运行,因为项目功能单一,目标明确,资源文件不会太大,所以打包压缩之后,出来的文件也不会很大,适当的进行拆分就可以。

如图,构建很简单,单入口,单页面。所有的文件都是通过main.js和其引入的子模块引入,形成单入口。作为经典的SPA项目,就一个入口页面index.html,前端跳转由前端路由和后端路由协作完成。

那么需要webpack做的事情其实就很好理解了:

  1. 引入对应文件的模块解析。例如:vue-loaderbabel-loadercss-loader
  2. 提取css为外部引入,通过link标签引入
  3. 文件压缩
  4. 大文件拆分
  5. 公共文件提取为独立文件
  6. 通过html-webpack-plugin将所有依赖的js/css等静态资源注入模版文件,生成目标文件保存到指定服务器模版文件目录

都说了,其实前端最后需要处理的文件大概率就3个htmljscss

demo详情地址–>> 单入口案例

webpack4+ 多入口构建思路

既然都已经知道单入口构建怎么玩的了。那么就来思考一下webpack多入口构建怎么玩呗。

先不说,webpack怎么配置。从需求上来说,不就是期望:

  1. 有很多的入口文件
  2. 有很多的html模版文件生成。这里会生成到server/views目录
  3. html模版文件引入自己模块需要的js/css等静态资源即可,其他模块的不引入,以免产生冗余代码

上图的静态资源js/css会生成并保存到static目录。

也就是说上图的pagea.js入口文件,通过webpack构建之后,只会注入pagea.html。而不会注入pageb.html

这里其实难点,就一个:如何让对应的入口文件的html模版文件,引入只与本模块有关的js/css

webpack4+ 多入口构建配置实战

那不废话,实战中要如何配置呢?这恐怕并不是只有我一个人想知道。其实上面的每个问题在这里都有解决的方案。

如图,可以看到多入口配置,超级简单在entry添加对应模块入口即可。

1
2
3
4
entry:{//入口文件
pagea:'./client/pagea/index.js',
pageb:'./client/pageb/index.js'
}

这里demo里面有2个入口文件pagea.jspageb.js

针对这个如何让对应的入口文件的html模版文件,引入只与本模块有关的js/css问题。

可以通过html-webpack-plugin解决。首先配置多个html-webpack-plugin实例对象,然后指定每个实例对象需要引入的chunks文件即可。

1
2
3
4
5
6
7
8
9
10
new HtmlWebpackPlugin({
filename: './../../server/views/pagea.html',
chunks:['pagea'],
template: path.resolve(__dirname , './client/template.html')
}),
new HtmlWebpackPlugin({
filename: './../../server/views/pageb.html',
chunks:['pageb'],
template: path.resolve(__dirname , './client/template.html')
})

这里配置很简单。pagea.html配置只引入pagea.js。当需要引入多个的时候只需要在数组里面添加对应的模块名称即可。

配置完了,来看看结果如何吧。

执行npm install 先下载完所需要的模块,再通过执行webpack命令进行构建。

webpack请全局安装,需要 v4.5+。

可以看到,通过webpack打包编译,生成了我们想要的pagea.htmlpageb.html。并且js文件注入正常。

那现在可执行npm run develop命令启动node.js服务。在浏览器打开127.0.0.1:4000 就看到了页面了。

pagea.htmlpageb.html,引入正常,并正常运行。大功告成!!!!

demo详情地址–>> 多入口案例

webpack4+ 优化

当你以为一切回归平静时,其实才是挑战的开始。要做到多入口,其实感觉还是挺简单的。要做的好,其实距离还是很远的。再往下的篇幅其实已经和多口构建没有多少关系了。主要是一些基于webpack4+ 优化的点,也就是遇到相关问题的解决方案。

Split Chunks模块拆分

项目小的时候,感觉什么都是那么爽。啥事也没有。可是项目一旦变得复杂,那么其实很多之前没有遇到的问题就会暴露无遗。

当我在pagea.js尝试引入vuetui-chart图表模块的时候,发现了打包出来的文件过于庞大,达到了2.2MB,即使压缩之后一样。

那么是时候引入文件拆分了,因为webpack4+之后,并不建议再使用CommonChunks模块,所以使用新的官方推荐的SplitChunks模块。

通过在webpack的plugin里面添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
new webpack.optimize.SplitChunksPlugin({
chunks: 'all',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '-',
name: true,
cacheGroups: {
vue: {
test: /[\\/]node_modules[\\/]vue[\\/]/,
priority: -10,
name: 'vue'
},
'tui-chart': {
test: /[\\/]node_modules[\\/]tui-chart[\\/]/,
priority: -20,
name: 'tui-chart'
}
}
})

添加splitChunks方式有多种,上面只是其中一种。

通过在cacheGroups里面设置公共模块,达到模块复用。需要注意的就是,在html-webpack-plugin实例中引入chunks时,需要加入对应的模块。

1
2
3
4
5
new HtmlWebpackPlugin({
filename: './../../server/views/pagea.html',
chunks:['vue','tui-chart','pagea'],
template: path.resolve(__dirname , './client/template.html')
})

上面的pagea.html不仅需要引入pagea,还需要而为引入vuetui-chart

通过上图,最后看到打包拆分出来的js文件体积还是很可观的。

MiniCssExtract提取为外部CSS

说完了JavaScript的体积拆分,其实CSS上面也有一个问题。就是,我并没有在上面的demo中做到通过link标签引入。这里将解决这个问题。

webpack4+ 提供了一个新的模块叫做MiniCssExtract。这个模块就可以处理.css外链引入的问题。

首先在rules里面配置:

1
2
3
4
{
test: /\.s?[ac]ss$/,//postcss-loader 依赖 postcss-config.js
use: [MiniCssExtractPlugin.loader,'css-loader','postcss-loader','sass-loader']
}

主要是将原来的style-loader替换成MiniCssExtractPlugin.loader。如果需要区分环境,进行不同引入也是可以的。

然后需要在下面进行plugins引入:

1
2
3
new MiniCssExtractPlugin({ //提取为外部css代码
filename:'[name].css?v=[contenthash]'
})

当一切完成之后。执行相关命令。

可以看到,生成的html文件成功的引入了自己需要的文件。

是不是成功了呢? 哈哈。。。。。

赶紧去验证吧!!!!!!一定要验证哦。。。。。。。。。。

demo详情地址–>> 多入口优化案例

总结

大体上,webpack4+构建和其他版本的没有多大区别,最多就是模块的使用有点不同。不过对于我来说,解决了我原来纠结的多入口构建问题。但同时这也是一个demo,算不上是一个完整的构建。还缺很多的东西,但是基础已经在这里了,所以可以在此基础上优化,最终达到自己想要的构建配置。

最后有一个问题,那就是所有打包后生成的文件入不入版本库呢?

这里我给出所谓答案在这篇文章:小马的大前端之路–Node.js初探