Webpack 4 升级与使用

Posted by hubcarl on 18-03-10

最近一段时间, 在尝试 easywebpack 工程化方案升级到 Webpack 4 版本,在此期间遇到比较多问题:

  • Webpack 4 虽然发布了,但没有文档,只能看源代码
  • Webpack 4 相关插件没有及时适配, 需要提issue,让作者适配,需要等待
  • ssr 构建中遇到问题 6681
  • 配置适配兼容,包括 mode, commonsChunk, 默认插件
  • 骨架升级测试, 会遇到一些奇怪问题,然后去升级对应的插件

Webpack 4 最新问题(2018-3-27)

Webpack 4 版本特性

  • 配置默认初始化一些配置, 比如 entry 默认 ‘./src’
  • 开发模式和发布模式, 插件默认内置
  • CommonsChunk 配置简化
  • 使用 ES6 语法,比如 Map, Set, includes
  • 新增 WebAssembly 构建支持
  • 如果要使用 webpack cli 命令,需要单独再安装 webpack-cli

目前 Webpack4 已经基本稳定,还是有些 bug 再不断的修复,目前已经 4.1.1。 具体见:https://github.com/webpack/webpack/releases 目前 Webpack 4 的文档还没有出来,只能看 Webpack 源码了。

配置

默认配置

在 Webpack 4 中,不再强制要求指定 entry 和 output 路径。webpack 4 会默认 entry 为 ./src,output 为 ./dist

构建模式 mode:

Webpack 4 配置, 必须配置 mode 属性, 可选值有 development,production,none

development 默认开启插件(无需配置):

  • NamedModulesPlugin->optimization.namedModules
  • development 模式 使用 eval 构建 module,用来提升构建速度
  • webpack.DefinePlugin 插件的 process.env.NODE_ENV 的值不需要再定义,默认是 development

production 默认开启插件(无需配置):

  • NoEmitOnErrorsPlugin->optimization.noEmitOnErrors
  • ModuleConcatenationPlugin->optimization.concatenateModules
  • webpack.DefinePlugin 插件的 process.env.NODE_ENV 的值不需要再定义,默认是 production

公共代码提取

Webpack3的commonschunk hash问题非常的不雅,使用复杂, Webpack 4 直接将 CommonsChunkPlugin 插件直接改为 optimization.splitChunks 和 optimization.runtimeChunk 两个配置

  • Webpack 3
plugins:[
  new webpack.optimize.CommonsChunkPlugin({ names: 'common'}),
  new webpack.optimize.CommonsChunkPlugin({ name: 'runtime', chunks:['common']})
]
  • Webpack 4
optimization: {
   splitChunks: {
   	 chunks: 'all',
   	 name: 'common',
   },
   runtimeChunk: {
	 name: 'runtime',
   }
 }

压缩

压缩插件更新到 uglifyjs-webpack-plugin 1.0 版本,支持多进程压缩,缓存以及es6语法,无需单独安装转换器。当 mode=’production’ 默认开启压缩,无需配置。可以通过 optimization.minimizeoptimization.minimizer 自定义配置。测试发现,第二次打包时间是第一次打包的一半左右。

  • optimization.minimize 是否启用压缩
  • optimization.minimizer 制定压缩库, 默认 uglifyjs-webpack-plugin 1.0
optimization: {
   minimize:true
}

Webpack4 代码: WebpackOptionsDefaulte.js#L261

优化配置

Webpack 4 默认内置了一些配置, 但额外又增加了一些配置,比如 optimization 配置属性,差不多 20 各左右的属性配置, 具体看webpack/schemas/WebpackOptions.json

sideEffects 构建大小优化

Webpack 4 提供了 sideEffects 的配置,引入的第三方插件在 package.json 里面配置 sideEffects:false 后,据说是可以大幅度地减小打包出的文件的体积,具体待验证。

目前初步了解 sideEffects 的信息:sideEffects:false 表示该模块无副作用。当你需要导入,但不需要导出任何东西时,但需要在导入时做其他事情(必然初始化,pollyfill等),这就是导入模块的副作用. 目前对这个理解的不多,具体在第三方库的构建上面没有一个直观的感受,需要继续慎入了解。

目前查到的资料:https://stackoverflow.com/questions/41127479/es6-import-for-side-effects-meaning

插件事件注册与调用

Webpack4 代码层面最大的变化是整个Plugin的事件注册和事件触发机制完全重写了,导致大部分第三方插件都要修改才能用,有些插件作者一两年都没有更新,提了issue只能耐心等待,如果要用只能自己硬着头皮去翻源码然后PR了。 到目前为止, 常用的插件都已经适配。

Webpack3:

注册:

compiler.plugin(done,callback)

触发:

compilitation.applyPlugins(done,params)

Webpack4:

  • 注册:
compiler.hooks.done.tap(mypluinname,callback)
  • 触发:
compiler.hooks.done.call()

常用插件版本

  • eslint-loader: ^ 2.0.0
  • file-loader:^1.1.10
  • vue-loader: ^14.1.1
  • webpack-hot-middleware
  • extract-text-webpack-plugin: ^4.0.0-beta.0

工程化支持

easywebpack 前端工程化方案已经支持 Webpack4 配置, 对应方案是 ^4.x.x 版本。 如果你之前已经使用 easywebpack(webpack3)工程化方案, 你只需要按照版本发布指引升级或删除 package.json 对应插件依赖即可。 webpack.config.js 无需修改,easywebpack 4 已经向下兼容了。

已经适配 Webpack4 的骨架项目代码在对应的 webpack4 分支,有需要可以玩玩。

参考资料

https://github.com/webpack/webpack/releases

https://medium.com/webpack/webpack-4-released-today-6cdb994702d4

https://github.com/dwqs/blog/issues/60