webpack@v4升级踩坑

— By BingqiChen

之前看到各大公众号都在狂推 webpack 新版发布的相关内容,之前就尝试了升级,由于部分插件的原因,未能成功,现在想必过了这么久已经可以了,今天就来试一下在我的项目中升级会遇到哪些坑。

查阅更新日志

在安装更新之前,先大致浏览了一下更新日志,对大部分用户来说迁移上需要注意的应该就是这些点:

迁移

  1. 安装最新的 webpackwebpack-cliwebpack-dev-server
  2. 为开发中和发布分别配置 mode ,删除 webpack.DefinePlugin 配置,并且去掉 package.json 中启动脚本的 NODE_ENV 区别环境变量定义;
  3. 去掉 new webpack.optimize.UglifyJsPluginModuleConcatenationPlugin 配置。

爬坑

别慌

  1. 在这些配置好之后我遇到的第一个问题就是打包时 extract-text-webpack-plugin 插件炸了!这里提供了这里有两种解决方案:

    • 方法一:安装指定 extract-text-webpack-plugin 版本 @next

    • 方法二:使用 mini-css-extract-plugin 替代。

      如果使用方法二注意在发布打包时需要指定 css 压缩库配置,并且需要同时写入 js 压缩库,因为你一旦指定了 optimization.minimizer 就会弃用内置的代码压缩:

      /* webpack.config.js */
      const MiniCssExtractPlugin = require('mini-css-extract-plugin');
      
      module.exports = () => {
        const config = {
          module: {
            rules: [
              {
                test: /\.css$/,
                use: [
                  MiniCssExtractPlugin.loader,
                  'css-loader?importLoaders=1',
                  'postcss-loader'
                ]
              },
              {
                test: /\.less$/,
                use: [
                  MiniCssExtractPlugin.loader,
                  'css-loader?importLoaders=1',
                  'postcss-loader',
                  'less-loader'
                ]
              }
            ]
          },
          resolve: {
            extensions: ['.js', '.jsx', '.less']
          }
        };
      
        if (process.env.NODE_ENV === 'development') {
          config.module.rules[0].use = [
            'css-hot-loader',
            MiniCssExtractPlugin.loader,
            'css-loader?importLoaders=1',
            'postcss-loader'
          ];
          config.module.rules[1].use = [
            'css-hot-loader',
            MiniCssExtractPlugin.loader,
            'css-loader?importLoaders=1',
            'postcss-loader',
            {
              loader: 'less-loader',
              options: {
                modifyVars: theme
              }
            }
          ];
        }
      
        return config;
      };
      
      /* webpack.config.prod.js */
      const merge = require('webpack-merge');
      const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
      const MiniCssExtractPlugin = require('mini-css-extract-plugin');
      const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
      const webpackBaseConfig = require('./webpack.config')();
      
      module.exports = merge(webpackBaseConfig, {
        mode: 'production',
        optimization: {
          minimizer: [
            new UglifyJsPlugin({
              cache: true,
              parallel: true,
              uglifyOptions: {
                compress: {
                  warnings: false,
                  drop_debugger: true,
                  drop_console: false
                }
              }
            }),
            new OptimizeCSSAssetsPlugin({})
          ]
        },
        plugins: [
          new MiniCssExtractPlugin({
            filename: 'css/[name].css'
          })
        ]
      });
      
  2. happypack 炸了,小场面,升级就好 `@5.0.0-beta.3happypackextract-text-webpack-plugin搭配使用更佳,mini-css-extract-plugin` 未测试)。

  3. webpack-browser-plugin 炸了,小场面,弃用就好,然后在 devServer 中配置 openopenPage

  4. 上面的配置中可以看到我使用判断语句 process.env.NODE_ENV === 'development' 在开发配置中加入了 css-hot-loader ,但是这里实际上是获取到的是 undefined ,咦?这是什么鬼?查阅更新日志是怎么说的:

    process.env.NODE_ENV are set to production or development (only in built code, not in config)

    意思就是说我们在使用的工程项目代码中会获取到这个变量,但是打包配置中使用这个变量还是获取不到的,我也实际验证了这个结果,so,我在 package.json 的开发启动脚本中还是加上了 NODE_ENV='development'

最后

总体来说现在的升级时机已经成熟,大多需要用到的功能和插件都有平滑的升级或替代方案,建议在开始升级前安装最新发布的插件版本,也可以参考下我的项目配置react-with-mobx-template

还有对插件的一些 API 也做了一些更改,如果你是插件开发者也可以尝试发布新的插件版本,我在使用自己的版本号提取插件webpack-version-plugin时发现 compiler.plugin 已经被提示过气了, webpack@v4 使用最新的 compiler.hooks.emit.tap 触发事件,嗯,最后的这部分广告真硬!

23333