webpack5 :
这个版本的重点在于以下几点。
- 尝试用持久性缓存来提高内置性能。
- 尝试用更好的算法和最小值来改进长期缓存。
- 尝试用更好的Tree Shaking和代码生成来改善包大小。
- 尝试改善与网络平台的兼容性。
- 尝试在不约会任何破坏性变化的情况下,清理那些在实现v4功能时处于奇怪状态的内部结构。
- 尝试通过现在约会突破性的变化来为未来的功能做准备,使其能够重新连续地保持在v5版本上。
一、webpack 5 的介绍及下载
webpack 5 通过持久缓存提高构建性能。
webpack 5 使用更好的算法和默认值来改善长期缓存。
webpack 5 通过更好的树摇和代码生成来改善捆绑包大小。
webpack 5 清除处于怪异状态的内部结构,同时在 v4 中实现功能而不引入任何重大更改。
webpack 5 通过引入重大更改来为将来的功能做准备,以使我们能够尽可能长时间地使用 v5。
webpack 5 的下载可以通过 npm i webpack@next webpack-cli -D 命令进行下载。
重大变更:功能清除
清理弃用的能力
所有在v4中被废弃的能力都被删除。
迁移:确保您的webpack 4构建没有打印废弃警告。
以下是一些被移除但在v4中没有废弃警告的东西:
- IgnorePlugin和BannerPlugin现在必须只传递一个参数,这个参数可以是对象,字符串或函数。
废弃代码
新的弃用包括一个弃用代码,这样他们更容易被引用。
语法废弃
require.include
已被废弃,使用时默认会发出警告。
可以通过Rule.parser.requireInclude
将行为改造允许,废弃或替代。
不再为Node.js模块自动引用
在早期,webpack的目的是为了让大多数的Node.js模块运行在浏览器中,但如今模块的布局已经发生了变化,现在很多模块主要是为前端而编写。webpack <= 4的版本中提供了很多Node.js核心模块的polyfill,一旦有人模块引用了任何一个核心模块(如cypto
模块),webpack就会自动引用这些polyfill。
尽管这会有助于使用为Node.js编写模块变得容易,但它在建造时给bundle附加了庞大的polyfill。在大部分情况下,这些polyfill不一定。
从webpack 5开始不再自动填充这些polyfills,而会专注于前端模块兼容。我们的目标是提高web平台的兼容性。
迁移:
- 尽量使用前端兼容的模块。
- 可以手动为Node.js核心模块添加polyfill。错误提示会告诉你如何实现。
- 包作者:在
package.json
中添加browser
前缀,使包与前端兼容。为浏览器提供其他的实现/依赖项。
重大变更:长期缓存
确定的Chunk,模块ID和衍生名称
新增了长期缓存的算法。这些算法在生产模式下是替代启用的。
chunkIds: "deterministic"
moduleIds: "deterministic"
mangleExports: "deterministic"
该算法机理性的方式为模块和分块分配短的(3或5位)数字ID,这是包大小和长期缓存之间的一种权衡。
moduleIds/chunkIds/mangleExports: false
请注意,在webpack 4中,moduleIds/chunkIds: false
如果没有自定义插件,则可以正常运行,而在webpack 5中,您必须提供一个自定义插件。
迁移:最好使用chunkIds
,moduleIds
状语从句:mangleExports
的默认值你也。可以选择使用旧的默认值。chunkIds: "size",moduleIds: "size", mangleExports: "size"
,这将会生成更小的包,但为了缓存,会更频繁地将其失效。
注意:在webpack 4中,散列的模块id会导致gzip性能降低。这与模块顺序的改变有关,已经被修正。
注意:在webpack 5中,deterministic
Ids在生产模式下是替代启用的。
真正的内容哈希
当使用[contenthash]
时,Webpack 5将使用真正的文件内容哈希值。之前它“只”使用内部结构的哈希值。当只有注释被修改或变量被重命名时,这对长期缓存会有积极影响。这些变化在压缩后是不可见的。
重大变更:开发支持
命名代码块
在开发模式下,默认启用的新命名代码块ID算法为模块(和文件名)提供了人类的名字。模块ID由其路径决定,相对于context
。代码块ID由代码块的内容决定。
所以你不再需要使用import(/* webpackChunkName: "name" */ "module")
来调试。
可以在生产环境中使用chunkIds: "named"
在生产环境中使用,但要确保不要不小心暴露模块名的敏感信息。
迁移:如果你不喜欢在开发中改变文件名,你可以通过chunkIds: "natural"
来使用旧的数字模式。
模块联邦
Webpack 5增加了一个新的功能“模块联邦”,它允许多个webpack构建一起工作。从运行时的角度来看,多个集成的模块将表现得像一个巨大的连接模块图。从开发者的角度来看,模块可以从指定的远程内置中引入,并以最小的限制来使用。
重大变更:支持崭新的Web平台特性
JSON模块
从严格的ECMAScript模块导入时,JSON模块不再有命名的导出。
迁移:使用替换导出。
即使使用替换生成,未使用的属性optimization.usedExports
也会被优化,属性会被optimization.mangleExports
优化打乱。
可以在Rule.parser.parse
中指定一个自定义的JSON解析器来引入类似JSON的文件(例如针对toml,yaml,json5等)。
import.meta
import.meta.webpackHot
是module.hot
的别名,在严格的ESM中也可以使用。import.meta.webpack
是webpack的主要版本号。import.meta.url
是当前文件的file:
url(而非__filename
,但作为文件url)。
资源模块
Webpack 5现在已经对表示资源的模块提供了内置支持。这些模块可以向输出文件夹发送一个文件,或者向javascript包注入一个DataURI。
它们可以通过多种方式被使用:
import url from "./image.png"
和在module.rule
中设置type: "asset"
当匹配这样的引入时。(老方法)new URL("./image.png", import.meta.url)
(新方式)
选择“新的方式”语法是为了允许在没有打包工具的情况下运行代码。这种语法也可以在浏览器中的原生ECMAScript模块中使用。
原生工人支持
当把资源的new URL
和new Worker
/ / new SharedWorker
/navigator.serviceWorker.register
结合起来时,webpack会自动为web worker创建一个新的入口点(entrypoint)。
new Worker(new URL("./worker.js", import.meta.url))
选择这种语法也是为了允许在没有打包工具的情况下运行代码。这种语法在浏览器的原生ECMAScript模块中也可以使用。
URIs
Webpack 5支持在请求中处理协议。
- 支持
data:
。支持Base64或原始编码。Mimetype可以在module.rule
中被映射到加载器和模块类型。例如:import x from "data:text/javascript,export default 42"
。 - 支持
file:
。 - 支持
http(s):
,但需要通过new webpack.experiments.s schemesHttp(s)UriPlugin()
选择加入。- 默认情况下,当目标为“ web”时,这些URI会导致对外部资源的请求(它们是外部资源)。
支持请求中的片段。例如:./file.js#fragment
。
初步模块
Webpack 5支持所谓的“异步模块”。这些模块并非同步解析的,或者基于异步和Promise的。
通过“ import”导入它们会被自动处理,不需要额外的语法,而且几乎看不到区别。
通过require()
引入它们会返回一个解析到衍生的Promise。
在webpack中,有多种方式来拥有异步模块。
- 初步的外部资源(异步外部)
- 新规范中的WebAssembly模块
- 使用顶层Await的ECMAScript模块。
外部资源
Webpack 5增加了更多的外部类型来覆盖更多的应用:
promise
:一个评估为Promise的表达式。外部模块是一个初始化模块,解析值作为模块转换使用。
import
。原生的import()
用于加载指定的请求,外部模块是一个初始化模块,解析值作为模块转换。外部模块是一个初始化模块。
module
:尚未实现,但计划通过import x from "..."
加载模块。
script
:通过<script>
标签加载一个url,并从一个类别变量(以及它的可选属性)中获取输出。外部模块是一个异步模块。
重大变更:支持全新的Node.js生态特性
解析
现在支持package.json中的exports
和imports
细分。
原生支持Yarn PnP。
重大变更:开发体验
经过优化的重建目标
Webpack 5允许传递一个目标列表,和支持目标的版本。
例如target: "node14"``target: ["web", "es2020"]
。
这是一个简单的方法,为webpack提供它需要确定的所有信息:
- 代码块加载机制,以及
- 支持的语法,如箭头函数
统计资料
改进了替代值,改为不那么扩展长,也适合大型建造。
- 现在默认情况下,代码块关系是隐藏的,用可以
stats.chunkRelations
来e月刊。 - Stats现在可以区分
files
和auxiliaryFiles
。 - Stats现在重置隐藏模块和代码块的id。这可以通过
stats.ids
来切换。 - 现在所有模块的列表是按照到入口点的距离排序的。这可以通过
stats.modulesSort
来改变。 - 代码块模块的列表现在按模块名称排序。这可以通过
stats.chunkModulesSort
来改变。 - 内置模块的列表现在是按失真结构排序的。这可以通过
stats.nestedModulesSort
来改变。 - 现在,代码块和资源会显示代码块id提示。
- 资产和模块将以树状而不是列表/表格的形式显示。
- 一般信息现在会在最后的摘要中显示。它显示了webpack版本,配置名称和警告/错误计数。
- 哈希值现在重置是隐藏的。这可以通过
stats.hash
来改变。 - 默认情况下不再不再显示重建的临时,这可以通过
stats.builtAt
开启。它会在摘要中显示替代。 - 默认情况下,不再显示子编译。可以它们用
stats.children
来显示。
进度
对ProgressPlugin
所做的一些改进,它被CLI在参数--progress
开启时使用,但也可以作为插件手动使用。
现在它可以计算“入口”,“依赖”和“模块”。现在所有的模块都替换显示了。
以前它只显示了当前处理的模块。这造成了很多stderr输出,在一些控制台上产生了性能问题。现在这个功能被替换关闭(activeModules
选项)。这也减少了控制台的垃圾信息量。现在,在构建模块的过程中,向stderr写入的时间被控制在500ms以内。
剖析模式也得到了升级,将显示附加进度消息的时间。这使得它更容易弄清楚清楚插件导致了性能问题。
新增加的percentBy
-选项通知ProgressPlugin
如何计算进度百分比。
new webpack.ProgressPlugin({
percentBy: 'entries' });
为了使进度百分比更准确,ProgressPlugin
会缓存最后已知的总模块数,并在下一次重建时重新使用这个值。
自动添加唯一命名
在webpack 4中,多个webpack运行时可能会在同一个HTML页面上发生冲突,因为它们使用同一个变量变量进行代码块加载。为了解决这个问题,需要为output.jsonpFunction
配置提供一个自定义的名称。
5的WebPack会确实从package.json
name
中自动推断出一个唯一的构建名称,其并将作为output.uniqueName
的默认值。
这个值用于使所有潜在的冲突的变量变量成为唯一。
迁移:由于package.json
中有唯一的名称,可将output.jsonpFunction
删除。
自动添加公共路径
Webpack 5会在可能的情况下自动确定output.publicPath
。
打字稿类型
Webpack 5从源码中生成typescript类型,并通过npm包暴露它们。
迁移:删除@types/webpack
。当名称不同时更新引用。
重大变更:构建优化
嵌套的
webpack现在能够跟踪对补充的嵌套属性的访问。这可以改善重新转换命名空间对象时的Tree Shaking(清除未使用的引入和替换导出)。
// inner.js
export const a = 1;
export const b = 2;
// module.js
export * as inner from './inner';
// 或 import * as inner from './inner'; export { inner };
// user.js
import * as module from './module';
console.log(module.inner.a);
在这个例子中,可以在生产模式下删除导出的b
。
内部模块摇树
webpack 5没有分析模块的导出和引用之间的依赖关系。webpack 5有一个新的选项optimization.innerGraph
,在生产模式下是替换启用的,它可以对模块中的标志进行分析,找到衍生和引用之间的依赖关系。
在这样的模块中:
import {
something }