webpack 3.X - 4.X 之升级之旅

鉴于公司项目越来越大编译的速度越来越慢,打出来的包也越来越大。webpack4 渐渐的走进了我们的视野,据官方表明,webpack4 新增加了很多默认配置项使开发人员不用编写 webpack.config.js 就能打包开发。极大的降低了学习成本,并对其进行了打包速度的优化以及压缩文件大小的优化。此次升级以 TTK 前端开源框架 的 ttk-app-core 项目 做为实例。欢迎各路大神加入我们。


文章最末附图升级前后启动提升 31% 编译构建提升 43% 速度,可以看出提升是很明显的,后续我会对项目进行压缩优化(因为之前大神已经进行过很多的优化所以目前不知道还能有多少优化的空间),让我们期待 webpack4 更好的表现吧。


升级过程

网上升级的帖子也有很多大家可以自行搜索,在此我只记录一下自己成功升级后的方法。分三步

  • 首先区别网上一些通过 npm-check-updates 来查看 package.json 中所有包的最新版本并选择安装,我这里只选择安装 webpack webpack-cli webpack-dev-server
npm install -D webpack@latest webpack-cli webpack-dev-server@latest
  • 然后不要着急根据所了解 webpack4 的新变化来修改项目中 webpack.config.js 文件,我选择启动/编译构建我们的项目。一般会在 package.json 的 scripts 中定义为 npm run start / npm run release 这个命令因个人项目定义而异。
  • 最后逐一解决步骤2收到的很多很多的报错。过程中就不一一赘述报错插件的作用介绍了。如果想了解可以看我的 plugin 插件篇 (持续更新常用插件的个人理解,如果找不到你想要的请联系个人邮箱 [email protected] 我们共同学习共同进步)

踩坑之旅 error

遇到报错不要慌乱首先看 bash 的输出报错是什么,然后 Bing 即可。下述错误不进行排序,因为每个人遇到的顺序肯定是不一样的。

首先进行的是 start

  • ValidationError: Dll Reference Plugin Invalid Options 截图如下:
webpackerr1.jpg

找到报错大致意思是 DllRefrencePlugin 这个插件是无效的操作。那么就要先看一下项目中 webpack.config.js 中的配置了

plugins.push(new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: merge(require('./vendor/vendor.manifest.json')),
}))

通过搜索老外的得出来的解决方案:
Simply running webpack --config webpack.config.vendor.js with the latest webpack-cli rebuilt vendor-manifest.json (the DLL), and allowed me to get past the error.
大致意思是我们需要重新生成一下我们 vendor 中的 manifest.json 文件即可,本项目需要在 bash 中执行 npm run dll 期间收到一些 warning 因为不影响流程所以我把他们都放到了最后来讲解。然后继续 start

  • webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead. 截图如下:
webpackerr2.jpg

这个就很明确的告诉我们 webpack.optimize.CommonsChunkPlugin 这个东西被移除了你需要 config.optimization.splitChunks 来代替它。那么首先我就需要注释掉对应部分的代码并添加新配置如下:

/*plugins.push(new webpack.optimize.CommonsChunkPlugin({
    names: ['edf'],
    filename: '[name].min.js',
    minChunks: Infinity
}))*/
//并在配置中增加如下代码。
    optimization: {
        splitChunks: { 
            chunks: 'async',
            minSize: 30000,
            maxSize: 0,
            minChunks: 1,
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            automaticNameDelimiter: '~',
            name: true,
            cacheGroups: {
                /*vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10
                },*/
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    },

然后继续 start 这次看到进度百分比了说明我的努力已经收到成效了。

  • Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead 截图如下:
webpackerr3.jpg

这个经查阅资料分析是 css 代码分离出问题了,那么我们使用的插件是 extract-text-webpack-plugin 现在问题就简单了直接 npm install extract-text-webpack-plugin@latest -D 命令升级即可
然后 start 发现会报一个重复的错误,那么继续查阅资料发现最新版本仍不能满足 webpack4 我们需要升级成 next 版本,执行命令 npm install extract-text-webpack-plugin@next -D
然后继续 start Compiled successfully. 成功了!但是打开项目发现样式错乱了。这时候我首先想到的就是把 样式相关的 loader 进行升级,查找了一下我项目大致用到了 css-loader、less、less-loader、file-loader、url-loader、style-loader 不管三七二十一全部升级。然后喜闻乐见的又报错了

  • .bezierEasingMixin(); 截图如下:
    Inline JavaScript is not enabled. Is it set in your options?
webpackerr4.jpg

通过查阅资料我们知道这是 less 升级到 3.0 之后的报错。解决方案是修改less的配置 options: { javascriptEnabled: true } 对应项目代码如下:

plugins.push(new HappyPack({
    id: 'css',
    // loaders: ['css-loader', clientInformation'less-loader'],
    loaders: [{
        loader: 'css-loader',
    }, {
        loader: "less-loader",
        options: {
            "modifyVars": modifyVars, // 变量
            "javascriptEnabled": true
        }
    }],
    threadPool: happyThreadPool, // 变量
}))

接下来我们继续 start,这次又启动成功了。尴尬的是页面还是错乱的,所以说上述改进好像没有生效,但是作为插件升级也就不回退了,理论上是有利于后续打包压缩优化的。
接下来我们继续分析和样式有关的插件 plugin 有什么,我们就找到了 extract-text-webpack-plugin 这个上面让我们踩了两次坑的破插件,然后我们查看 github 文档我们会看到它的 options 有这样一个属性说明,截图如下:

extract-text-webpack-plugin1.jpg

大致意思呢就是当我们使用 CommonsChunkPlugin 插件并且 ExtractTextPlugin.extract 有在公共模块使用时 allChunks 属性必须设置为 true。虽然我们已经弃用了 CommonsChunkPlugin 但是还是需要尝试一下,所以我们修改代码如下:

plugins.push(new ExtractTextPlugin({
    filename: '[name].css',
    allChunks: true 
}))

然后 start,这次又启动成功了。而且页面完好,点进项目也没有出问题。至此我们启动算是大功告成。接下来是踩在启动的肩膀上来构建编译项目。来看项目的打包 release 命令:

"release": "cross-env NODE_ENV=single npm run build && npm run css && npm run modules && npm run merge:manifest",
"build": "cross-env NODE_ENV=production NODE_ENV=single webpack --progress --colors --display-error-details --config webpack.config.prd.js",
"css": "cross-env NODE_ENV=production NODE_ENV=single webpack --progress --config webpack.config.css.prd.js",
"modules": "npm run module --edf && npm run module --test",
"module": "cross-env NODE_ENV=production webpack --progress --colors --display-error-details --config webpack.config.module.js",
"merge:manifest": "node createManifest.js",

所以我只需要查看并先按照上述 webpack.config.js、webpack.dll.js 来做修改 webpack.config.prd.js、webpack.config.css.prd.js、webpack.config.module.js、createManifest.js 这四个文件的代码。
然后执行 release 喜闻乐见的报错了

  • .bezierEasingMixin() 但是这个报错我们出现过,在 start 的解决方案并不能满足 release 的打包原因不得而知,我只知道 extract-text-webpack-plugin 插件是个十足的大坑,接下来通过查阅 webpack 的官方文档我们看到下述说明,截图如下:
extract-text-webpack-plugin3.jpg

大致意思呢是 webpack4 中抽离 css 用 mini-css-extract-plugin 来代替 extract-text-webpack-plugin 这个大坑,虽然查阅资料还有其他解决方案继续使用 extract-text-webpack-plugin 但是我放弃抵抗了决定弃用它,做如下改动:

// 首先在 bash 中安装
npm install -D mini-css-extract-plugin 
// 然后引入进来
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 根据官方说明来做代码调整如下
// 插件替换
/*plugins.push(new ExtractTextPlugin({
    filename: '[name].css',
    allChunks: true
}))*/
plugins.push(new MiniCssExtractPlugin({ // webpack 4
    filename: '[name].css',
    chunkFilename: '[id].css',
}))
// module 替换引入
        rules: [{
            test: /\.(css|less)/,
            /*use: ExtractTextPlugin.extract({ // webpack 3
                use: ['happypack/loader?id=css']
            })*/
            use: [MiniCssExtractPlugin.loader, 'happypack/loader?id=css'] // webpack 4
        }

然后先 start 试验一下启动成功项目也没有任何问题,那么我们继续 release 操作打包成功。启动 MAMP 启动服务器来测试一下,没有任何问题至此大功告成!!!
当然在实际升级过程中并没有这么顺利,走了很多很多的弯路和意想不到的报错,为此付出了很多的努力,最后总结出这么一套流程。看上去是非常之简单了。

踩坑之旅 warning
  • WARNING in configuration
    The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
    You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/ 截图如下:
    warning1.jpg

这就是 webpack4 让你在配置文件设置一下你的环境是生产还是开发,我们只需要在配置文件中设置 mode 属性即可。

  • WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
    This can impact web performance.
    Assets:
    vendor.e282754a.dll.js (1.7 MiB) 截图如下:
warning2.jpg

这是建议你的入口文件大小限制的,我们只需要告诉它不要管我就可以了,我们需要在配置文件中加入 performance: { hints: false } 的属性设置即可。

项目启动/编译构建升级前后时间对比
  • start 启动 29828ms 对比 43149ms 快了大概 31% 的样子
升级前start.jpg
升级后start.jpg
  • release 编译构建 52035ms 对比 91424ms 快了大概 43% 的样子
    注:这里 webpack.config.module.js 执行两次因为我们有两个 module 模块。
升级前release1.jpg
升级前release2.jpg
升级前release3.jpg
升级前release4.jpg
升级后release1.jpg
升级后release2.jpg
升级后release3.jpg
升级后release4.jpg

你可能感兴趣的:(webpack 3.X - 4.X 之升级之旅)