当 Webpack 进行打包时,它也会维护一个 manifest 文件。您可以在此项目中生成的 vendor 包中找到它。manifest 描述了 Webpack 应该加载的文件。我们可以提取它并开始快速地加载项目的文件,而不必等待加载 vendor 包。
如果 webpack 生成的哈希更改,manifest 也会更改。结果就是,供应商包的内容发生变化,并变为无效。通过将 manifest 提取为一个文件或将其内联写入项目的 index.html,则可以消除该问题。
提取 manifest
大部分工作在分割打包章节中设置 extractBundles
时就已经完成了。要提取 manifest,请按如下定义 optimization.runtimeChunk
:
webpack.config.js
const productionConfig = merge([
...
{
optimization: {
splitChunks: {
...
},
runtimeChunk: {
name: "manifest",
},
},
},
...
]);
按照惯例,我们将它命名为 manifest
。您可以使用任何其他名称,它仍然可以使用。
如果你现在构建项目(npm run build
),你应该看到一些东西:
Hash: 2e1c61341de0fd7e0e5c
Version: webpack 4.1.1
Time: 3347ms
Built at: 3/16/2018 6:24:51 PM
Asset Size Chunks Chunk Names
manifest.d41d.css 0 bytes 1 [emitted] manifest
0.73a8.js 160 bytes 0 [emitted]
vendors~main.3af5.js 96.8 KiB 2 [emitted] vendors~main
main.8da2.js 546 bytes 3 [emitted] main
main.5524.css 1.2 KiB 3 [emitted] main
vendors~main.3dd5.css 1.32 KiB 2 [emitted] vendors~main
manifest.8cac.js 1.81 KiB 1 [emitted] manifest
0.73a8.js.map 203 bytes 0 [emitted]
manifest.8cac.js.map 10 KiB 1 [emitted] manifest
vendors~main.3af5.js.map 235 KiB 2 [emitted] vendors~main
main.8da2.js.map 1.45 KiB 3 [emitted] main
index.html 460 bytes [emitted]
...
此更改提供了一个包含 manifest 的单独文件。在上面的输出中,它已标记为manifest
。因为我们设置了 HtmlWebpackPlugin
,所以无需担心 manifest 文件的加载问题,因为插件在 index.html 中添加了对它们的引用。
像 inline-manifest-webpack-plugin、html-webpack-inline-chunk-plugin 和 assets-webpack-plugin 之类的插件,可以配合 HtmlWebpackPlugin
一起使用,并允许您在_index.html_ 中写入 manifest,以避免额外的请求。
尝试调整 src/index.js 并查看哈希值如何变化。这一次 vendor 包应该不会失效,只有 manifest 和应用程序包名称会产生变化。
要更好地了解 manifest 内容,请在开发模式下运行构建或在配置中将
none
传递给 mode。你会看到一些熟悉的东西。
要与资源管道集成,您可以考虑使用以下插件,如 chunk-manifest-webpack-plugin,webpack-manifest-plugin,webpack-assets-manifest 或 webpack-rails-manifest-plugin。这些解决方案会生成一个 JSON 文件,将原始资源路径映射到新资源路径。
通过 CDN 加载流行的依赖项(如React)可以进一步改进构建。这将进一步减少 vendor 包的大小,因为不必在包中包含外部依赖想。如果用户之前已经命中过 CDN,那么缓存还会生效。
使用记录
正如分割打包一章所述,插件如 AggressiveSplittingPlugin
使用记录来实现缓存。上面讨论的方法仍然有效,但记录更进了一步。
记录在不同的构建中使用存储模块 ID,而且您需要保存这些模块。如果您在本地构建,则可以选择将其包含在版本控制中。
要生成 records.json 文件,请按如下所示调整配置:
webpack.config.js
const productionConfig = merge([
{
...
recordsPath: path.join(__dirname, "records.json"),
},
...
]);
如果构建项目(npm run build
),则应在项目根目录中看到一个新文件 records.json。下一次 Webpack 构建时,它会通过该文件获取记录信息并重写已经变动过的文件。
如果您设置的代码分割比较复杂并希望分割部分能够获得良好的应用缓存,则记录特别有用。最大的问题是维护记录文件。
recordsInputPath
和recordsOutputPath
对输入输出进行更细粒度的控制,但通常只设置recordsPath
就已经足够了。
如果您更改 Webpack 处理模块 ID 的方式(即删除
HashedModuleIdsPlugin
),现有的记录可能仍然会被考虑在内!如果要使用新模块 ID 方案,则还必须删除旧的记录文件。
总结
该项目现在具有基本的缓存行为。如果您尝试修改 index.js 或 component.js,则 vendor 包应保持不变。
回顾一下:
- Webpack 维护一个包含运行应用程序所需信息的 manifest。
- manifest 发生变动,会使其包含的包失效。
- 某些插件允许您将 manifest 写入生成的 index.html。也可以将信息提取到 JSON 文件,JSON 文件在服务端渲染中可以派上用场。
- 记录允许您跨构建存储模块ID。缺点是,您必须跟踪记录文件。
您将在下一章中学习如何分析构建,因为它对于理解和改进构建至关重要。