webpack4:2018年2月
webpack5:2021年10月10号
重大变更:
功能清除
- 清理弃用的能力
所有在 v4 中被废弃的能力都被移除。 - 废弃代码
- 语法废弃
- 不再为Node.js模块自动引用polyfills
webpack<=4.0版本:提供了许多Node.js核心模块的polyfills,当引用任何一个核心模块时(如crypto模块),webpack会自动引入polyfills。
如下代码:实现一个签名的函数。
const crypto = require('crypto')
// 将值通过私钥签名,由.分割原值和签名
function sign (val, secret) {
return val + '.' + crypto
.createHmac('sha256', secret)
.update(val)
.digest('base64')
.replace(/\=+$/, '');
};
module.exports = sign;
代码中使用到了 crypto 模块,因为在浏览器环境下是没有 crypto 这个东西,所以要引入 polyfills 做兼容处理。保证在浏览器中可以正常运行。
引入 polyfills 导致的问题就是打包的体积变大了。
怎么防止打包的时候把 crypto 模块打进去了,其实我们可以在 package.json 里面配置 browser 字段,然后设置值 false 就可以。这样代码就只能在 node 环境下运行了。
{
"name": "webpack4",
"version": "1.0.0",
"description": "",
"main": "index.js",
"browser": {
"buffer": false
},
"scripts": {
"webpck": "npx webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"webpack": "^4.35.3",
"webpack-cli": "^3.1.0"
}
}
webpack5:不再自动填充这些 polyfills,而会专注于前端模块兼容。目标是提高 web 平台的兼容性。因为 node 模块本身就不是为浏览器设计的。
- 尽量使用前端兼容的模块。比如 axios 这样的库,即可以在浏览器中运行,也可以在 node 环境中运行。
- 可以手动为 Node.js 核心模块添加 polyfill。错误提示会告诉如何实现。
比如下面的使用 webpack5 打包,报错信息是这样的。然后按照报错信息改。
let path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
library: 'result'
},
resolve: {
fallback: {
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify")
}
},
}
- 在 package.json 中添加 browser 字段,使 node 模块 与前端兼容。为浏览器提供其他的 dependencies 依赖。
下面 browser 字段的含义是在浏览器环境中把 crypto 模块替换为 crypto-js 模块。
{
"name": "webpack4",
"version": "1.0.0",
"description": "",
"main": "index.js",
"browser": {
"crypto": "crypto-js"
},
"scripts": {
"webpck": "npx webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"crypto-js": "^4.0.0","webpack":
"^4.35.3","webpack-cli": "^3.1.0"
}
}
总结:因为 webpack 打包默认是输出到浏览器端,如果我们在编写代码的时候引入了 node 的核心模块,此时 webpack5 就会抛出错误,提示我们需要配置 polyfills 。解决办法有三个,第一就是不要去使用 node 模块,而是替换成其他的前端模块。第二就是自己配置 polyfills,第三就不让 node 模块打包进行。
如果我们写的代码只运行在 node 环境,直接配置 taget 就可以。
let path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
library: 'result'
},
target: 'node'
}
参考文章:https://blog.51cto.com/u_15081056/2594195
长期缓存
- 确定的 Chunk、模块 ID 和导出名称()
- 真正的内容哈希
webpack<=4:使用内部结构的哈希值。 当只有注释被修改或变量被重命名时,这对长期缓存会有积极影响。这些变化在压缩后是不可见的。
webpack5:当使用 [contenthash] 时,Webpack 5 将使用真正的文件内容哈希值。
开发支持
- 命名代码块 ID
webpack<=4:import(/* webpackChunkName: “name” */ “module”)
webpack5:模块 ID 由其路径决定。代码块 ID 由代码块的内容决定。
1.可以在生产环境中使用 chunkIds: “named” 在生产环境中使用,但要确保不要不小心暴露模块名的敏感信息。
2.如果不喜欢在开发中改变文件名,可以通过 chunkIds: “natural” 来使用旧的模式。 - 模块联邦
支持崭新的 Web 平台特性
- JSON 模块
- import.meta
- 资源模块
- 原生 Worker 支持
- URIs
- 异步模块
- 外部资源
支持全新的 Node.js 生态特性
现在支持 package.json 中的 exports 和 imports 字段。
原生支持 Yarn PnP。
开发体验
- 经过优化的构建目标(target)
- Stats
- 进度
- 自动添加唯一命名
- 自动添加公共路径
- Typescript 类型
构建优化
- 嵌套的 tree-shaking
- 内部模块 tree-shaking
webpack 4: 没有分析模块的导出和引用之间的依赖关系。
webpack 5: 有一个新的选项 optimization.innerGraph,在生产模式下是默认启用的,它可以对模块中的标志进行分析,找出导出和引用之间的依赖关系。 - CommonJs Tree Shaking
- 副作用分析
- 每个运行时的优化
- 模块合并
- 通用 Tree Shaking 改进
- 开发与生产的一致性问题
webpack 4:由于 package.json 中的"sideEffects"标记不正确,这种优化导致了一些只在生产模式下出现的错误。
webpack 5:默认在两种模式下都启用了 "sideEffects "优化。在开发过程中启用这个优化可以更快更容易地发现这些问题。 - 改进代码生成
webpack 4:只生成 ES5 的代码。
webpack 5:既可以生成 ES5 又可以生成 ES6/ES2015 代码。 - 改进 target 配置
- 代码块拆分与模块大小
性能优化
- 持久缓存
- 编译器闲置和关闭
- 文件生成
长期未解决的问题
- 单一文件目标的代码分割
- 更新了解析器
- 没有 JS 的代码块
未来计划
- 实验特性
- 最小 Node.js 版本
最低支持的 Node.js 版本从 6 增加到 10.13.0(LTS)。
配置变更
未来计划
-
结构的变化
1.entry: {} 现在可以赋值一个空对象(允许使用插件来修改入口)。
2.target 支持数组,版本及 browserslist
3.output.filename 可以设置为函数 -
默认值变更
加载器相关变更
重大内部变更
- 新的插件运行顺序
- 运行时模块
- 序列化
- 用于缓存的插件
- 冻结钩子对象
- Tapable 插件升级
- Stage 钩子
- Main/Chunk/ModuleTemplate 废弃
- 入口文件描述符
- 入口文件输出文件名
- 入口文件依赖
- 入口文件类库
- 入口文件运行时
- 入口文件代码块加载
- 排序与 ID
- 从数组到集合(Set)
- Compilation.fileSystemInfo
- Filesystems
- 工作队列
- Logging
- 模块和 chunk 图
- Init Fragments
- 模块 Source Types
- Stats 的插件
- 全新的监听
- SizeOnlySource after emit
- Emitting assets multiple times
- ExportsInfo
- 代码生成阶段
- 依赖关系参考
- Presentational Dependencies
- 弃用 loaders
微小改动
…
其他微小改动
…
当 Webpack 作为句首时,Webpack 的 W 应该大写