@@ -14,6 +14,7 @@ contributors:
14
14
- AnayaDesign
15
15
- aholzner
16
16
- snitin315
17
+ - Yucohny
17
18
translators :
18
19
- QC-L
19
20
- jacob-lcs
@@ -25,15 +26,15 @@ related:
25
26
26
27
T> 本指南继续沿用 [ 起步] ( /guides/getting-started ) 、[ 管理输出] ( /guides/output-management ) 和 [ 代码分离] ( /guides/code-splitting ) 中的代码示例。
27
28
28
- 以上,我们使用 webpack 来打包我们的模块化后的应用程序 ,webpack 会生成一个可部署的 ` /dist ` 目录,然后把打包后的内容放置在此目录中。只要 ` /dist ` 目录中的内容部署到 server 上,client (通常是浏览器)就能够访问此 server 的网站及其资源 。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 [ 缓存] ( < https://en.wikipedia.org/wiki/Cache_(computing) > ) 的技术。可以通过命中缓存,以降低网络流量, 使网站加载速度更快, 然而,如果我们在部署新版本时不更改资源的文件名 ,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。
29
+ 接下来继续使用 webpack 打包模块化应用程序。在打包后 ,webpack 会生成一个可部署的 ` /dist ` 目录,然后就打包后的内容放置在此目录中。一旦 ` /dist ` 目录中的内容部署到服务器上,客户端 (通常是浏览器)就能够访问此服务器以获取站点及其资源 。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 [ 缓存] ( < https://en.wikipedia.org/wiki/Cache_(computing) > ) 的技术。命中缓存可以降低网络流量, 使网站加载速度更快。 然而,如果在部署新版本时不更改资源的文件名 ,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。
29
30
30
- 此指南的重点在于通过必要的配置,以确保 webpack 编译生成的文件能够被客户端缓存, 而在文件内容变化后,能够请求到新的文件。
31
+ 此指南的重点在于通过必要的配置,确保 webpack 编译生成的文件能够被客户端缓存; 而在文件内容变化后,能够请求到新的文件。
31
32
32
- ## 输出文件的文件名(output filename) $#output-filenames$
33
+ ## 输出文件的文件名 $#output-filenames$
33
34
34
- 我们可以通过替换 ` output.filename ` 中的 [ substitutions] ( /configuration/output/#outputfilename ) 设置,来定义输出文件的名称 。webpack 提供了一种使用称为 ** substitution( 可替换模板字符串) ** 的方式,通过带括号字符串来模板化文件名。其中,` [contenthash] ` substitution 将根据资源内容创建出唯一 hash 。当资源内容发生变化时,` [contenthash] ` 也会发生变化。
35
+ 更改 ` output.filename ` 中的 [ substitutions] ( /configuration/output/#outputfilename ) 以定义输出文件的名称 。webpack 提供了一种称为 ** substitution( 可替换模板字符串) ** 的方式,通过带括号字符串来模板化文件名。其中,` [contenthash] ` substitution 将根据资源内容创建唯一哈希值 。当资源内容发生变化时,` [contenthash] ` 也会发生变化。
35
36
36
- 这里使用 [ 起步] ( /guides/getting-started ) 中的示例和 [ 管理输出] ( /guides/output-management ) 中的 ` plugins ` 插件来作为项目基础,所以我们依然不必手动地维护 ` index.html ` 文件:
37
+ 这里使用 [ 起步] ( /guides/getting-started ) 中的示例和 [ 管理输出] ( /guides/output-management ) 中的 ` plugins ` 插件作为项目基础,所以不必手动维护 ` index.html ` 文件:
37
38
38
39
** project**
39
40
@@ -71,7 +72,7 @@ webpack-demo
71
72
};
72
73
```
73
74
74
- 使用此配置,然后运行我们的 build script ` npm run build ` ,产生以下输出 :
75
+ 调整配置后构建脚本,将会看到像下面一样的输出 :
75
76
76
77
``` bash
77
78
...
@@ -81,7 +82,7 @@ main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main
81
82
...
82
83
```
83
84
84
- 可以看到,bundle 的名称是它内容(通过 hash)的映射。如果我们不做修改,然后再次运行构建,我们以为文件名会保持不变。然而,如果我们真的运行,可能会发现情况并非如此 :
85
+ 可以看到,bundle 的名称是其内容通过哈希的映射。如果不做修改,再次运行构建,也许会认为文件名将保持不变。然而事实并非如此,试试再次构建脚本 :
85
86
86
87
``` bash
87
88
...
@@ -91,13 +92,13 @@ main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main
91
92
...
92
93
```
93
94
94
- 这也是因为 webpack 在入口 chunk 中,包含了某些 boilerplate( 引导模板) ,特别是 runtime 和 manifest。(译注:boilerplate 指 webpack 运行时的引导代码)
95
+ 这是因为 webpack 在入口 chunk 中,包含了某些 boilerplate( 引导模板) ,特别是 runtime 和 manifest。(译注:boilerplate 指 webpack 运行时的引导代码。 )
95
96
96
- W> 输出可能会因当前的 webpack 版本而稍有差异。与旧版本相比,新版本不一定有完全相同的问题,但我们仍然推荐的以下步骤,确保结果可靠 。
97
+ W> 输出可能会因当前的 webpack 版本而稍有差异。与旧版本相比,新版本未必持有同样的哈希机制,但我们仍然建议采取以下步骤以确保安全 。
97
98
98
- ## 提取引导模板(extracting boilerplate) $#extracting-boilerplate$
99
+ ## 提取引导模板 $#extracting-boilerplate$
99
100
100
- 正如我们在 [ 代码分离] ( /guides/code-splitting ) 中所学到的,[ ` SplitChunksPlugin ` ] ( /plugins/split-chunks-plugin/ ) 可以用于将模块分离到单独的 bundle 中。webpack 还提供了一个优化功能,可使用 [ ` optimization.runtimeChunk ` ] ( /configuration/optimization/#optimizationruntimechunk ) 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 ` single ` 来为所有 chunk 创建一个 runtime bundle:
101
+ 正如我们在 [ 代码分离] ( /guides/code-splitting ) 中所学到的,[ ` SplitChunksPlugin ` ] ( /plugins/split-chunks-plugin/ ) 可以用于将模块分离到单独的 bundle 中。webpack 还提供了一个优化功能,可以使用 [ ` optimization.runtimeChunk ` ] ( /configuration/optimization/#optimizationruntimechunk ) 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 ` single ` 以为所有 chunk 创建一个 runtime bundle:
101
102
102
103
** webpack.config.js**
103
104
@@ -123,7 +124,7 @@ W> 输出可能会因当前的 webpack 版本而稍有差异。与旧版本相
123
124
};
124
125
```
125
126
126
- 再次构建,然后查看提取出来的 ` runtime ` bundle:
127
+ 更改配置后再次构建,查看提取出来的 ` runtime ` bundle:
127
128
128
129
``` bash
129
130
Hash: 82c9c385607b2150fab2
@@ -139,8 +140,8 @@ runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime
139
140
+ 1 hidden module
140
141
```
141
142
142
- 将第三方库(library)(例如 ` lodash ` 或 ` react ` )提取到单独的 ` vendor ` chunk 文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致 。
143
- 这可以通过使用 [ SplitChunksPlugin 示例 2] ( /plugins/split-chunks-plugin/#split-chunks-example-2 ) 中演示的 [ ` SplitChunksPlugin ` ] ( /plugins/split-chunks-plugin/ ) 插件的 [ ` cacheGroups ` ] ( /plugins/split-chunks-plugin/#splitchunkscachegroups ) 选项来实现。我们在 ` optimization.splitChunks ` 添加如下 ` cacheGroups ` 参数并构建 :
143
+ 由于像 ` lodash ` 或 ` react ` 这样的第三方库很少像本地源代码一样频繁修改,因此通常推荐将第三方库提取到单独的 ` vendor ` chunk 中。这一步将减少客户端对服务器的请求,同时保证自身代码与服务器一致 。
144
+ 可以通过使用 [ SplitChunksPlugin 示例 2] ( /plugins/split-chunks-plugin/#split-chunks-example-2 ) 中演示的 [ ` SplitChunksPlugin ` ] ( /plugins/split-chunks-plugin/ ) 插件的 [ ` cacheGroups ` ] ( /plugins/split-chunks-plugin/#splitchunkscachegroups ) 选项来实现。试试在 ` optimization.splitChunks ` 添加如下 ` cacheGroups ` 参数并执行构建 :
144
145
145
146
** webpack.config.js**
146
147
@@ -187,9 +188,9 @@ vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors
187
188
...
188
189
```
189
190
190
- 现在,我们可以看到 ` main ` 不再含有来自 ` node_modules ` 目录的 ` vendor ` 代码,并且体积减少到 ` 240 bytes ` !
191
+ 现在,可以看到 ` main ` 不再含有来自 ` node_modules ` 目录的 ` vendor ` 代码,并且体积减少到 ` 240 bytes ` !
191
192
192
- ## 模块标识符(module identifier) $#module-identifiers$
193
+ ## 模块标识符 $#module-identifiers$
193
194
194
195
在项目中再添加一个模块 ` print.js ` :
195
196
@@ -224,7 +225,7 @@ webpack-demo
224
225
function component() {
225
226
const element = document.createElement('div');
226
227
227
- // lodash 是由当前 script 脚本 import 进来的
228
+ // lodash 现在使用 import 引入
228
229
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
229
230
+ element.onclick = Print.bind(null, 'Hello webpack!');
230
231
@@ -234,7 +235,7 @@ webpack-demo
234
235
document.body.appendChild(component());
235
236
```
236
237
237
- 再次运行构建,然后我们期望的是 ,只有 ` main ` bundle 的 hash 发生变化 ,然而……
238
+ 通常我们会期望,当再次执行构建后 ,只有 ` main ` bundle 的哈希值会发生变化 ,然而……
238
239
239
240
``` bash
240
241
...
@@ -246,13 +247,13 @@ webpack-demo
246
247
...
247
248
```
248
249
249
- ……我们可以看到这三个文件的 hash 都变化了 。这是因为每个 [ ` module.id ` ] ( /api/module-variables/#moduleid-commonjs ) 会默认地基于解析顺序( resolve order)进行增量。也就是说 ,当解析顺序发生变化,ID 也会随之改变。简要概括 :
250
+ 可以发现,三个文件的哈希值都发生了变化 。这是因为每个 [ ` module.id ` ] ( /api/module-variables/#moduleid-commonjs ) 会默认基于解析顺序( resolve order)增量。换言之 ,当解析顺序发生变化,ID 也会随之改变。简要概括便是 :
250
251
251
252
- ` main ` bundle 会随着自身的新增内容的修改,而发生变化。
252
253
- ` vendor ` bundle 会随着自身的 ` module.id ` 的变化,而发生变化。
253
254
- ` manifest ` runtime 会因为现在包含一个新模块的引用,而发生变化。
254
255
255
- 第一个和最后一个都是符合预期的行为, ` vendor ` hash 发生变化是我们要修复的。我们将 [ ` optimization.moduleIds ` ] ( /configuration/optimization/#optimizationmoduleids ) 设置为 ` 'deterministic' ` :
256
+ 上面的第一点与最后一点都是符合预期的行为,而 ` vendor ` 的哈希值发生变化是我们要修复的。试试将 [ ` optimization.moduleIds ` ] ( /configuration/optimization/#optimizationmoduleids ) 设置为 ` 'deterministic' ` :
256
257
257
258
** webpack.config.js**
258
259
@@ -288,7 +289,7 @@ webpack-demo
288
289
};
289
290
```
290
291
291
- 现在,不论是否添加任何新的本地依赖,对于前后两次构建,` vendor ` hash 都应该保持一致 :
292
+ 现在,不论是否添加任何新的本地依赖,对于前后两次构建,` vendor ` 的哈希值都应保持一致 :
292
293
293
294
``` bash
294
295
...
@@ -301,7 +302,7 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
301
302
...
302
303
```
303
304
304
- 然后,修改 ` src/index.js ` , 临时移除额外的依赖:
305
+ 接下来修改 ` src/index.js ` 临时移除额外的依赖:
305
306
306
307
** src/index.js**
307
308
@@ -313,7 +314,7 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
313
314
function component() {
314
315
const element = document.createElement('div');
315
316
316
- // lodash 是由当前 script 脚本 import 进来的
317
+ // lodash 现在使用 import 引入
317
318
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
318
319
- element.onclick = Print.bind(null, 'Hello webpack!');
319
320
+ // element.onclick = Print.bind(null, 'Hello webpack!');
@@ -324,7 +325,7 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
324
325
document.body.appendChild(component());
325
326
```
326
327
327
- 最后,再次运行我们的构建 :
328
+ 最后,再次执行构建 :
328
329
329
330
``` bash
330
331
...
@@ -337,8 +338,8 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
337
338
...
338
339
```
339
340
340
- 我们可以看到,这两次构建中 ,` vendor ` bundle 文件名称,都是 ` 55e79e5927a639d21a1b ` 。
341
+ 可以看到,在这两次构建中 ,` vendor ` bundle 的文件名称都是 ` 55e79e5927a639d21a1b ` 。
341
342
342
- ## 结论 $#conclusion$
343
+ ## 总结 $#conclusion$
343
344
344
- 缓存可能很复杂,但是从应用程序或站点用户可以获得的收益来看,这值得付出努力。想要了解更多信息,请查看下面 * 进一步阅读* 部分。
345
+ 缓存可能很复杂,但是从应用程序或站点用户可以获得的收益来看,这值得付出努力。想要了解更多信息,请查看下面 ** 进一步阅读* * 部分。
0 commit comments