New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpack 4 不完全迁移指北 #60

Open
dwqs opened this Issue Feb 13, 2018 · 23 comments

Comments

Projects
None yet
@dwqs
Owner

dwqs commented Feb 13, 2018

webpack 3 发布 之后, webpack 团队向社区承诺,之后 webpack 主版本的迭代会有一个时间比较长且稳定的开发周期。而在2017年8月份的时候,webpack 团队从 master 分支切出了 next 分支用于 webpack 4 的开发,经历 5 个月的开发周期之后,webpack 4.0-beta 在 2018年1月 已经 Released 了,不仅兑现了之前的承诺,还带来了诸多新特性,在用户使用的体验上也作了诸多改进。

安装

如果需要使用 webpack 4,则需要从 next 分支上安装:

// yarn
yarn add webpack@next webpack-cli --dev

// npm 
npm install webpack@next webpack-cli --save-dev

不完全迁移指北

环境

不再支持 Node.js 4。

根据 package.json 配置, Node.js 的最低支持版本为 6.11.5

模块类型

webpack 4之前,js 是 webpack 中的唯一模块类型,因而不能有效地打包其它类型的文件。而 webpack 4 则提供了 5 种模块类型:

  • javascript/auto: (webpack 3中的默认类型)支持所有的JS模块系统:CommonJS、AMD、ESM
  • javascript/esm: EcmaScript 模块,在其他的模块系统中不可用(默认 .mjs 文件)
  • javascript/dynamic: 仅支持 CommonJS & AMD,EcmaScript 模块不可用
  • json: 可通过 requireimport 导入的 JSON 格式的数据(默认为 .json 的文件)
  • webassembly/experimental: WebAssembly 模块(处于试验阶段,默认为 .wasm 的文件)

此外,webpack 4 中会默认解析 .wasm, .mjs, .js.json 为后缀的文件。

在对应文件的 loader 配置,需要增加 type 字段来指定模块类型:

 module: {
    rules: [{
        test: /\.special\.json$/,
        type: "javascript/auto",
        use: "special-loader"
    }]
 }

javascript/auto / javascript/esm 都可以处理 ESM, 但后者会更加严格:

  • 导入的名称必须存在于导入的模块中
  • 动态的模块(非 ESM,如 CommonJS)只能通过默认 import 导入,其它方式(包括命名空间)的导入都会报错

对于 WebAssembly 模块:

  • 可以导入其它模块(JS 和 WASM)
  • 试图在 WASM 模块中导入不存在的模块将会得到一个警告或者错误
  • ESM 可以引入 WASM 模块中导出的模块名
  • 仅可在 async chunks(通过 import() 导入的模块)中使用,在 initial chunks 中是无效的(不利于提升 web 应用的性能)

import(): 动态导入

在 webpack 4 中,import() 会返回一个带命名空间(namespace)的对象,这对 ES Module 不会有影响,但对于遵循 commonjs 规范的模块则会加一层包裹:

// webpack 2/3
import("./commonjs").then(exports => {
	...
})

// webpack 4
import("./commonjs").then({default: exports}=> {
	...
})

mode: 模式配置

mode 是 webpack 4 中新增加的参数选项,其有两个可选值:productiondevelopmentmode 不可缺省,需要二选一:

  1. production 模式:
    • 默认提供所有可能的优化,如代码压缩/作用域提升等
    • 不支持 watching
    • process.env.NODE_ENV 的值不需要再定义,默认是 production
   /** webpack.production.config.js **/
   // webpack 2/3 
   module.exports = {
       plugins: [
        new UglifyJsPlugin(/* ... */),
        new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
       ]
     }
     
   // webpack 4  
   module.exports = {
   	mode: 'production'
   }
  1. development 模式:
    • 主要优化了增量构建速度和开发体验
    • process.env.NODE_ENV 的值不需要再定义,默认是 development
    • 开发模式下支持注释和提示,并且支持 eval 下的 source maps
   /** webpack.development.config.js **/
   // webpack 2/3 
   module.exports = {
       plugins: [
        new webpack.NamedModulesPlugin(),
        new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") })
       ]
     }
     
   // webpack 4  
   module.exports = {
   	mode: 'development'
   }

此外, webpack 4 还提供一种隐藏(none)模式,这种模式下会禁用一切优化

sideEffects 设置

webpack 4 在 package.json 中引入了对 sideEffects: false 的支持。当模块的 package.json 中添加该字段时,表明该模块没有副作用,也就意味着 webpack 可以安全地清除被用于重复导出(re-exports)的代码。

JSON

webpack 4 不仅支持本地处理 JSON,还支持对 JSON 的 Tree Shaking。当使用 ESM 语法 import json 时,webpack 会消除掉JSON Module 中未使用的导出。

此外,如果要用 loader 转换 json 为 js,需要设置 typejavascript/auto

module.rules: [
	{
	  test: /\.special\.json$/,
	  type: "javascript/auto",
	  use: "special-loader"
	}
]

配置

  • 删除了一些常用内置插件:
    • NoEmitOnErrorsPlugin -> optimization.noEmitOnErrors (生产模式默认)
    • ModuleConcatenationPlugin -> optimization.concatenateModules (生产模式默认)
    • NamedModulesPlugin -> optimization.namedModules (开发模式默认)。
    • 删除了 CommonsChunkPlugin,取而代之的是 optimization.splitChunksoptimization.runtimeChunk,这提供了细粒度的缓存策略控制
  • 可以使用 module.rules[].resolve 来配置解析,它会与全局配置合并。
  • optimization.minimize 用于控制 minimizing 的开关。 生产模式默认为开,开发模式默认为关。
  • optimization.minimizer 用于配置 minimizers 和选项。
  • 许多支持占位符(placeholders)的配置选项现也支持函数形式
  • 错误的 options.dependencies 配置将报错
  • sideEffects 可以通过 module.rules 覆盖
  • output.hashFunction 可以是一个构造函数,用于自定义 hash 函数。处于性能考虑,也可以提供非加密哈希函数
  • output.globalObject 可以用于配置运行时的全局对象引用
  • 默认配置
    • webpack 默认会按照 .wasm, .mjs, .js.json 的扩展名顺序查找模块。
    • output.pathinfo 在开发模式下默认是打开的
    • 生产环境下,默认关闭内存缓存
    • entry 的默认值是 ./srcoutput.path 的默认值是 ./dist
    • 在选择模式选项时,默认值是 production

优化

  • uglifyjs-webpack-plugin 发布 v1,支持 ES2015
  • 使用 JSONP 数组来代替 JSONP 函数 –> 异步支持
  • webpack 自身也可以删除无用代码。webpack 2/3 中是在 Uglify 时删除无用代码,webpack 4 中 webpack 也可以(在某些情况下)删除无用代码,避免 import() 引用无用代码时导致的奔溃
  • 作用域提升后的模块将生成更少的代码

性能

  • 默认情况,UglifyJS 会默认缓存和并行化(完全实现缓存和并行化将在 webpack 5 中实现)
  • 多个性能改进,尤其是在增量构建这方面
  • 改进了 RemoveParentModluesPlugin 的性能
  • 未使用模块不再有非必要的作用域提升
  • 添加 ProfilingPlugin,此插件会(在 Chrome 浏览器中)创建一个包含各插件时间消耗的文件
  • for of 代替 forEachMap/Set 代替 Objectsincludes 代替 indexOf
  • 同一个任务只会进入队列一次

完整的性能改善和优化列表可以参考 Release 4.0-beta.0

移除的功能

  • 移除了 module.loaders
  • 移除了 loaderContext.options
  • 移除了 Compilation.notCacheable
  • 移除了 NoErrorsPlugin
  • 移除了 Dependency.isEqualResource
  • 移除了 NewWatchingPlugin
  • 移除了 CommonsChunkPlugin

相关资源

@dwqs dwqs changed the title from Webpack 4.0 不完全迁移指北 to Webpack 4 不完全迁移指北 Feb 13, 2018

@yzw2017

This comment has been minimized.

yzw2017 commented Feb 14, 2018

66666

@njleonzhang

This comment has been minimized.

njleonzhang commented Feb 14, 2018

666

@Calerme

This comment has been minimized.

Calerme commented Feb 16, 2018

Mark.

@chentianyuan

This comment has been minimized.

chentianyuan commented Feb 25, 2018

awesome

@dwqs

This comment has been minimized.

Owner

dwqs commented Feb 27, 2018

webpack 4 中,如果要使用 webpack cli 命令,需要单独再安装 webpack-cli

@stuxt

This comment has been minimized.

stuxt commented Feb 28, 2018

six six six six

@aflext

This comment has been minimized.

aflext commented Feb 28, 2018

6的不行,mark

@njleonzhang

This comment has been minimized.

njleonzhang commented Feb 28, 2018

很多plugin还用不了,我玩了一下头有点疼啊

@269378737

This comment has been minimized.

269378737 commented Feb 28, 2018

htmlwebpackplugin 没法用啊,即使执行了 yarn add webpack-contrib/html-webpack-plugin -D,不知道哪里弄的不对

@dwqs

This comment has been minimized.

Owner

dwqs commented Feb 28, 2018

@269378737 试一下 yarn add html-webpack-plugin@webpack-contrib/html-webpack-plugin -D

@dwqs

This comment has been minimized.

Owner

dwqs commented Feb 28, 2018

广告:基于 webpack 4 的一个项目:https://github.com/dwqs/v2-lazy-list 😄😄😄

@njleonzhang

This comment has been minimized.

njleonzhang commented Feb 28, 2018

凑波热度:基于 webpack 4 的一个项目: https://github.com/njleonzhang/web-cached-persistence

@269378737

This comment has been minimized.

269378737 commented Mar 1, 2018

@dwqs 嗯,试了下,挺好用的,谢谢

@15521529438

This comment has been minimized.

15521529438 commented Mar 2, 2018

6666

1 similar comment
@jetango

This comment has been minimized.

jetango commented Mar 4, 2018

6666

@acmilank22

This comment has been minimized.

acmilank22 commented Mar 8, 2018

码一下

@fengyun2

This comment has been minimized.

fengyun2 commented Mar 8, 2018

凑波热度:基于 webpack 4 的一个项目:https://github.com/fengyun2/webpack4-demo

@titancat

This comment has been minimized.

titancat commented Mar 12, 2018

想请问一下如何获取 webpack 的 mode 值?
自问自答 🤣

@acmilank22

This comment has been minimized.

acmilank22 commented Mar 12, 2018

@titancat 谢了 亲测有效
module.exports = (env, argv) => { const mode = argv.mode; };

@geraldlrh

This comment has been minimized.

geraldlrh commented Apr 8, 2018

感兴趣的是,性能可以提升多少,欢迎升级后的盆友列下数据

@dawven

This comment has been minimized.

dawven commented Apr 8, 2018

six six six

@FredYing

This comment has been minimized.

FredYing commented Apr 8, 2018

马克

@ClarenceC

This comment has been minimized.

ClarenceC commented Apr 10, 2018

总结得不错啊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment