Open Holybasil opened 4 years ago
既然准备升级webpack,索性将vue-loader和babel全部升级了。
由于webpack的CLI已经被单独集成一个包,所以在常规升级完webpack到4.x.x之后,记得顺手把webpack-cli也也安装到项目里。
webpack4提供了mode配置项,该项提供三个可选的值“none”,“development”,“production”。不同的mode会设置当前配置文件下的process.env.NODE_ENV,同时预设不同的插件,方便开发环境或者生产环境。该值可以在配置文件中写明,例如:
module.exports={ mode: "development" }
也可以通过webpack-cli,在参数中传递,例如package.json中:
"build": "webpack --mode production"
所以,我们可以移除原来用来定义process.env.NODE_ENV的DefinePlugin插件。
同时,webpack4在codeSplit这项重大功能上,废弃了CommonsChunkPlugin插件,取而代之的是optimization.splitChunks配置项。
CommonsChunkPlugin
optimization.splitChunks
我们可以看看这个 也就是说,如果将mode设置为production,webpack默认按照以上规则打包项目。 那么上面四条规则分别是在说什么呢?
node_modelus
node_modules
注意最后两条规则,这就告诉我们,在打包项目的时候,要注意平衡chunk的细碎度和并行请求数。
具体关于splitChunks的配置,可以仔细研读官网文档split-chunks-plugin。这里,主要提一下文档里没有讲清楚的三个特殊值all,inital,async。
all
inital
async
所以大多数的文章,包括webpack本身,都建议,通常情况下
optimization: { splitChunks: { // include all types of chunks chunks: 'all' } }
这样的打包规则适用于大多数项目。
更加定制化的打包规则,则需要先了解cacheGroups,这个属性可以简单理解为:cacheGroups是一个对象,每个键值对都代表着一个chunk的打包规则。
例如,在我的项目里,node_modules里有很多公共的依赖,包括echarts这种大型库。但是,只有很少的页面需要展示图表,并且并非首页。所以我的cacheGroups里有这样两组规则:
vendor:{ chunks: "initial", name: "chunk-vendor", test: /[\\/]node_modules[\\/]/, priority: 5, }, echarts:{ test: /[\\/]node_modules[\\/]echarts[\\/]/, name: "chunk-echarts", priority: 10 },
这两组规则表示,将echarts单独打包,node_modules中的其他同步引用模块统一打包。那么页面初始加载时,chunk-vender的size会减小很多,加载时间就会缩短,巧妙减少白屏时间。待按需加载的页面使用到echarts后,才会加载chunk-echart。对于一些只有某些页面用到的大型库,都可以这么处理。
同时,注意这里的priority,它表明了当前规则的应用优先级,意思是,打包时,先按第二组规则生成chunk-echarts,再按第一组规则生成chunk-vendor。由于默认规则的优先级均为负数,所以自定义规则的优先级需从正数开始。
priority
关于cacheGroups内规则的其他属性,亦可参考上面的链接。
将vue-loader升级为15..之后,记得
const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { // ... plugins: [ new VueLoaderPlugin() ] }
需要显式的应用插件。
同时VueLoader15不再默认开启PostCss(提供style scoped功能),所以如果要使用PostCSS,记得配置postcss-loader。
升级babel后,更换presets为@babel/preset-env(babel-preset-env)。
@babel/preset-env
这个plugin会通过browserslist智能的预置一系列的babel转换规则。因此,coder可以任意使用js的新特性,不用考虑是否支持目标浏览器版本。
browserslist
由于我的代码中使用了vue-router的LazyLoading,所以引入@babel/plugin-syntax-dynamic-import插件,确保正确解析import()。
@babel/plugin-syntax-dynamic-import
import()
此时此刻,npm run build之后,报!错!了!import("**/*.vue")无法被解析!难道我装了个假babel?
import("**/*.vue")
这里插一句,升级webpack的时候
npm install webpack@latest
最新的webpack版本为4.35.4。
各种关键词搜索之后,我找到了一个issue parse import error ,看来还是有一些人遇到了这个问题。请直接滑到@sokra的回复那里,原因讲的很清楚了,这里不再复述。
而我选了最直接的解决办法,将webpack的版本固定为4.28.4,解决了。
webpack4中,用MiniCssExtractPlugin替换了ExtractTextWebpackPlugin,能够支持异步加载,并且使用方式简单多了。
MiniCssExtractPlugin
ExtractTextWebpackPlugin
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader,'css-loader'] }
为了将打包后的css文件统一放置,MiniCssExtractPlugin中的filename和chunkFilename可以由路径和文件名组成,例如:“static/css/[id].css”意为打包后的css文件均在/dist/static/css文件夹下。MiniCssExtractPlugin的publicPath默认为output的publicPath。
webpack4默认压缩js的插件是TerserWebpackPlugin,是一个对ES6+支持的更好的压缩插件。注意,记得设置sourceMap: true,这样当productionSourceMap为true时,才会生成.map文件。
TerserWebpackPlugin
sourceMap: true
在开发环境中,由于WebpackDevServer接手了服务,所以一系列的优化可以在devServer中配置。(如果支持的话)可以设置progress:true,感受项目启动的进度。FriendlyErrorsWebpackPlugin和quiet:true则去掉了一些我们不关心的输出。 在生产环境,项目打包完毕,会需要看chunk的一些信息,以及打包速度,之后有目的的优化。webpack提供stat配置项,允许细粒度的控制输出信息。常规输出的配置如下:
WebpackDevServer
FriendlyErrorsWebpackPlugin
stats: { all: undefined, colors: true, modules: false, children: false, chunks: false }
到目前为止,webpack这次的升级已经很成功了,项目的打包速度和打包之后的文件体积都有了很大的进步。但是一般都会配置devServer的open:true,这样每次启动服务,浏览器(Chrome)都会自己打开页面,很方便。但是每次启动服务,都会开启一个新的tab,这就麻烦了不是,本来我的显示器就小,分辨率也不高。
需求明确了,就是搜索怎么办了,关键词reuse,tab,chrome,几经波折,从create-react-app的源码中,找到了一段applescript。配合同级目录下的openBrower.js,这不就是我想要的嘛。注意openBrower.js文件返回的是opn(url)(这里我把open换成了opn),所以该怎么用已经很明了了。
create-react-app
applescript
openBrower.js
然后问题又来了,我怎么在项目里最方便的用他们呢?既然是开发环境,那么再去地毯式搜索了WebpackDevServer的配置项,after这个属性正好是我需要的。他是在所有内置中间件执行完毕后,将服务暴露出来,之后想做什么,做!于是我
after: function(app, server) { if(config.dev.autoOpenBrowser) server.middleware.waitUntilValid(()=>{ const url = "http://"+ config.dev.host + ":" + process.env.PORT openBrower(url) }) }
这里的openBrower当然就是刚才两个文件提供的神器了。
测试,后开启的服务果然找到了之前的tab,在原tab上刷新,不会打开新的tab了。
撒花 over
To v4 from v3 built-in optimizations depending on mode Webpack (v4) Code Splitting using SplitChunksPlugin
😆👏
webpack4升级踩坑指南(vue)
mode
由于webpack的CLI已经被单独集成一个包,所以在常规升级完webpack到4.x.x之后,记得顺手把webpack-cli也也安装到项目里。
webpack4提供了mode配置项,该项提供三个可选的值“none”,“development”,“production”。不同的mode会设置当前配置文件下的process.env.NODE_ENV,同时预设不同的插件,方便开发环境或者生产环境。该值可以在配置文件中写明,例如:
也可以通过webpack-cli,在参数中传递,例如package.json中:
所以,我们可以移除原来用来定义process.env.NODE_ENV的DefinePlugin插件。
splitChunks
同时,webpack4在codeSplit这项重大功能上,废弃了
CommonsChunkPlugin
插件,取而代之的是optimization.splitChunks
配置项。我们可以看看这个 也就是说,如果将mode设置为production,webpack默认按照以上规则打包项目。 那么上面四条规则分别是在说什么呢?
node_modelus
文件夹的第三方依赖是被共享的。->node_modules
中的第三方依赖会被打包成一个chunk注意最后两条规则,这就告诉我们,在打包项目的时候,要注意平衡chunk的细碎度和并行请求数。
具体关于splitChunks的配置,可以仔细研读官网文档split-chunks-plugin。这里,主要提一下文档里没有讲清楚的三个特殊值
all
,inital
,async
。所以大多数的文章,包括webpack本身,都建议,通常情况下
这样的打包规则适用于大多数项目。
更加定制化的打包规则,则需要先了解cacheGroups,这个属性可以简单理解为:cacheGroups是一个对象,每个键值对都代表着一个chunk的打包规则。
例如,在我的项目里,node_modules里有很多公共的依赖,包括echarts这种大型库。但是,只有很少的页面需要展示图表,并且并非首页。所以我的cacheGroups里有这样两组规则:
这两组规则表示,将echarts单独打包,node_modules中的其他同步引用模块统一打包。那么页面初始加载时,chunk-vender的size会减小很多,加载时间就会缩短,巧妙减少白屏时间。待按需加载的页面使用到echarts后,才会加载chunk-echart。对于一些只有某些页面用到的大型库,都可以这么处理。
同时,注意这里的
priority
,它表明了当前规则的应用优先级,意思是,打包时,先按第二组规则生成chunk-echarts,再按第一组规则生成chunk-vendor。由于默认规则的优先级均为负数,所以自定义规则的优先级需从正数开始。关于cacheGroups内规则的其他属性,亦可参考上面的链接。
VueLoader 15
将vue-loader升级为15..之后,记得
需要显式的应用插件。
同时VueLoader15不再默认开启PostCss(提供style scoped功能),所以如果要使用PostCSS,记得配置postcss-loader。
Babel7
升级babel后,更换presets为
@babel/preset-env
(babel-preset-env)。这个plugin会通过
browserslist
智能的预置一系列的babel转换规则。因此,coder可以任意使用js的新特性,不用考虑是否支持目标浏览器版本。由于我的代码中使用了vue-router的LazyLoading,所以引入
@babel/plugin-syntax-dynamic-import
插件,确保正确解析import()
。此时此刻,npm run build之后,报!错!了!
import("**/*.vue")
无法被解析!难道我装了个假babel?这里插一句,升级webpack的时候
最新的webpack版本为4.35.4。
各种关键词搜索之后,我找到了一个issue parse import error ,看来还是有一些人遇到了这个问题。请直接滑到@sokra的回复那里,原因讲的很清楚了,这里不再复述。
而我选了最直接的解决办法,将webpack的版本固定为4.28.4,解决了。
MiniCssExtractPlugin
webpack4中,用
MiniCssExtractPlugin
替换了ExtractTextWebpackPlugin
,能够支持异步加载,并且使用方式简单多了。为了将打包后的css文件统一放置,
MiniCssExtractPlugin
中的filename和chunkFilename可以由路径和文件名组成,例如:“static/css/[id].css”意为打包后的css文件均在/dist/static/css文件夹下。MiniCssExtractPlugin
的publicPath默认为output的publicPath。TerserWebpackPlugin
webpack4默认压缩js的插件是
TerserWebpackPlugin
,是一个对ES6+支持的更好的压缩插件。注意,记得设置sourceMap: true
,这样当productionSourceMap为true时,才会生成.map文件。优化
在开发环境中,由于
WebpackDevServer
接手了服务,所以一系列的优化可以在devServer中配置。(如果支持的话)可以设置progress:true,感受项目启动的进度。FriendlyErrorsWebpackPlugin
和quiet:true则去掉了一些我们不关心的输出。 在生产环境,项目打包完毕,会需要看chunk的一些信息,以及打包速度,之后有目的的优化。webpack提供stat配置项,允许细粒度的控制输出信息。常规输出的配置如下:到目前为止,webpack这次的升级已经很成功了,项目的打包速度和打包之后的文件体积都有了很大的进步。但是一般都会配置devServer的open:true,这样每次启动服务,浏览器(Chrome)都会自己打开页面,很方便。但是每次启动服务,都会开启一个新的tab,这就麻烦了不是,本来我的显示器就小,分辨率也不高。
需求明确了,就是搜索怎么办了,关键词reuse,tab,chrome,几经波折,从
create-react-app
的源码中,找到了一段applescript
。配合同级目录下的openBrower.js
,这不就是我想要的嘛。注意openBrower.js
文件返回的是opn(url)(这里我把open换成了opn),所以该怎么用已经很明了了。然后问题又来了,我怎么在项目里最方便的用他们呢?既然是开发环境,那么再去地毯式搜索了
WebpackDevServer
的配置项,after这个属性正好是我需要的。他是在所有内置中间件执行完毕后,将服务暴露出来,之后想做什么,做!于是我这里的openBrower当然就是刚才两个文件提供的神器了。
测试,后开启的服务果然找到了之前的tab,在原tab上刷新,不会打开新的tab了。
撒花 over
参考
To v4 from v3 built-in optimizations depending on mode Webpack (v4) Code Splitting using SplitChunksPlugin