Skip to content

Commit

Permalink
docs(cn): review and update
Browse files Browse the repository at this point in the history
  • Loading branch information
Yucohny committed Jul 24, 2023
1 parent 7118569 commit 8d9fb62
Showing 1 changed file with 28 additions and 27 deletions.
55 changes: 28 additions & 27 deletions src/content/guides/caching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ contributors:
- AnayaDesign
- aholzner
- snitin315
- Yucohny
translators:
- QC-L
- jacob-lcs
Expand All @@ -25,15 +26,15 @@ related:

T> 本指南继续沿用 [起步](/guides/getting-started)[管理输出](/guides/output-management)[代码分离](/guides/code-splitting) 中的代码示例。

以上,我们使用 webpack 来打包我们的模块化后的应用程序,webpack 会生成一个可部署的 `/dist` 目录,然后把打包后的内容放置在此目录中。只要 `/dist` 目录中的内容部署到 server 上,client(通常是浏览器)就能够访问此 server 的网站及其资源。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 [缓存](<https://en.wikipedia.org/wiki/Cache_(computing)>) 的技术。可以通过命中缓存,以降低网络流量,使网站加载速度更快然而,如果我们在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。
接下来继续使用 webpack 打包模块化应用程序。在打包后,webpack 会生成一个可部署的 `/dist` 目录,然后就打包后的内容放置在此目录中。一旦 `/dist` 目录中的内容部署到服务器上,客户端(通常是浏览器)就能够访问此服务器以获取站点及其资源。而最后一步获取资源是比较耗费时间的,这就是为什么浏览器使用一种名为 [缓存](<https://en.wikipedia.org/wiki/Cache_(computing)>) 的技术。命中缓存可以降低网络流量,使网站加载速度更快然而,如果在部署新版本时不更改资源的文件名,浏览器可能会认为它没有被更新,就会使用它的缓存版本。由于缓存的存在,当你需要获取新的代码时,就会显得很棘手。

此指南的重点在于通过必要的配置,以确保 webpack 编译生成的文件能够被客户端缓存而在文件内容变化后,能够请求到新的文件。
此指南的重点在于通过必要的配置,确保 webpack 编译生成的文件能够被客户端缓存而在文件内容变化后,能够请求到新的文件。

## 输出文件的文件名(output filename) $#output-filenames$
## 输出文件的文件名 $#output-filenames$

我们可以通过替换 `output.filename` 中的 [substitutions](/configuration/output/#outputfilename) 设置,来定义输出文件的名称。webpack 提供了一种使用称为 **substitution(可替换模板字符串)** 的方式,通过带括号字符串来模板化文件名。其中,`[contenthash]` substitution 将根据资源内容创建出唯一 hash。当资源内容发生变化时,`[contenthash]` 也会发生变化。
更改 `output.filename` 中的 [substitutions](/configuration/output/#outputfilename) 以定义输出文件的名称。webpack 提供了一种称为 **substitution可替换模板字符串** 的方式,通过带括号字符串来模板化文件名。其中,`[contenthash]` substitution 将根据资源内容创建唯一哈希值。当资源内容发生变化时,`[contenthash]` 也会发生变化。

这里使用 [起步](/guides/getting-started) 中的示例和 [管理输出](/guides/output-management) 中的 `plugins` 插件来作为项目基础,所以我们依然不必手动地维护 `index.html` 文件:
这里使用 [起步](/guides/getting-started) 中的示例和 [管理输出](/guides/output-management) 中的 `plugins` 插件作为项目基础,所以不必手动维护 `index.html` 文件:

**project**

Expand Down Expand Up @@ -71,7 +72,7 @@ webpack-demo
};
```

使用此配置,然后运行我们的 build script `npm run build`,产生以下输出
调整配置后构建脚本,将会看到像下面一样的输出

```bash
...
Expand All @@ -81,7 +82,7 @@ main.7e2c49a622975ebd9b7e.js 544 kB 0 [emitted] [big] main
...
```

可以看到,bundle 的名称是它内容(通过 hash)的映射。如果我们不做修改,然后再次运行构建,我们以为文件名会保持不变。然而,如果我们真的运行,可能会发现情况并非如此
可以看到,bundle 的名称是其内容通过哈希的映射。如果不做修改,再次运行构建,也许会认为文件名将保持不变。然而事实并非如此,试试再次构建脚本

```bash
...
Expand All @@ -91,13 +92,13 @@ main.205199ab45963f6a62ec.js 544 kB 0 [emitted] [big] main
...
```

这也是因为 webpack 在入口 chunk 中,包含了某些 boilerplate(引导模板),特别是 runtime 和 manifest。(译注:boilerplate 指 webpack 运行时的引导代码)
这是因为 webpack 在入口 chunk 中,包含了某些 boilerplate引导模板,特别是 runtime 和 manifest。(译注:boilerplate 指 webpack 运行时的引导代码

W> 输出可能会因当前的 webpack 版本而稍有差异。与旧版本相比,新版本不一定有完全相同的问题,但我们仍然推荐的以下步骤,确保结果可靠
W> 输出可能会因当前的 webpack 版本而稍有差异。与旧版本相比,新版本未必持有同样的哈希机制,但我们仍然建议采取以下步骤以确保安全

## 提取引导模板(extracting boilerplate) $#extracting-boilerplate$
## 提取引导模板 $#extracting-boilerplate$

正如我们在 [代码分离](/guides/code-splitting) 中所学到的,[`SplitChunksPlugin`](/plugins/split-chunks-plugin/) 可以用于将模块分离到单独的 bundle 中。webpack 还提供了一个优化功能,可使用 [`optimization.runtimeChunk`](/configuration/optimization/#optimizationruntimechunk) 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 `single` 来为所有 chunk 创建一个 runtime bundle:
正如我们在 [代码分离](/guides/code-splitting) 中所学到的,[`SplitChunksPlugin`](/plugins/split-chunks-plugin/) 可以用于将模块分离到单独的 bundle 中。webpack 还提供了一个优化功能,可以使用 [`optimization.runtimeChunk`](/configuration/optimization/#optimizationruntimechunk) 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 `single` 以为所有 chunk 创建一个 runtime bundle:

**webpack.config.js**

Expand All @@ -123,7 +124,7 @@ W> 输出可能会因当前的 webpack 版本而稍有差异。与旧版本相
};
```

再次构建,然后查看提取出来的 `runtime` bundle:
更改配置后再次构建,查看提取出来的 `runtime` bundle:

```bash
Hash: 82c9c385607b2150fab2
Expand All @@ -139,8 +140,8 @@ runtime.cc17ae2a94ec771e9221.js 1.42 KiB 0 [emitted] runtime
+ 1 hidden module
```

将第三方库(library)(例如 `lodash``react`)提取到单独的 `vendor` chunk 文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致
这可以通过使用 [SplitChunksPlugin 示例 2](/plugins/split-chunks-plugin/#split-chunks-example-2) 中演示的 [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) 插件的 [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunkscachegroups) 选项来实现。我们在 `optimization.splitChunks` 添加如下 `cacheGroups` 参数并构建
由于像 `lodash``react` 这样的第三方库很少像本地源代码一样频繁修改,因此通常推荐将第三方库提取到单独的 `vendor` chunk 中。这一步将减少客户端对服务器的请求,同时保证自身代码与服务器一致
可以通过使用 [SplitChunksPlugin 示例 2](/plugins/split-chunks-plugin/#split-chunks-example-2) 中演示的 [`SplitChunksPlugin`](/plugins/split-chunks-plugin/) 插件的 [`cacheGroups`](/plugins/split-chunks-plugin/#splitchunkscachegroups) 选项来实现。试试在 `optimization.splitChunks` 添加如下 `cacheGroups` 参数并执行构建

**webpack.config.js**

Expand Down Expand Up @@ -187,9 +188,9 @@ vendors.a42c3ca0d742766d7a28.js 69.4 KiB 1 [emitted] vendors
...
```

现在,我们可以看到 `main` 不再含有来自 `node_modules` 目录的 `vendor` 代码,并且体积减少到 `240 bytes`
现在,可以看到 `main` 不再含有来自 `node_modules` 目录的 `vendor` 代码,并且体积减少到 `240 bytes`

## 模块标识符(module identifier) $#module-identifiers$
## 模块标识符 $#module-identifiers$

在项目中再添加一个模块 `print.js`

Expand Down Expand Up @@ -224,7 +225,7 @@ webpack-demo
function component() {
const element = document.createElement('div');

// lodash 是由当前 script 脚本 import 进来的
// lodash 现在使用 import 引入
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+ element.onclick = Print.bind(null, 'Hello webpack!');

Expand All @@ -234,7 +235,7 @@ webpack-demo
document.body.appendChild(component());
```

再次运行构建,然后我们期望的是,只有 `main` bundle 的 hash 发生变化,然而……
通常我们会期望,当再次执行构建后,只有 `main` bundle 的哈希值会发生变化,然而……

```bash
...
Expand All @@ -246,13 +247,13 @@ webpack-demo
...
```

……我们可以看到这三个文件的 hash 都变化了。这是因为每个 [`module.id`](/api/module-variables/#moduleid-commonjs) 会默认地基于解析顺序(resolve order)进行增量。也就是说,当解析顺序发生变化,ID 也会随之改变。简要概括
可以发现,三个文件的哈希值都发生了变化。这是因为每个 [`module.id`](/api/module-variables/#moduleid-commonjs) 会默认基于解析顺序(resolve order)增量。换言之,当解析顺序发生变化,ID 也会随之改变。简要概括便是

- `main` bundle 会随着自身的新增内容的修改,而发生变化。
- `vendor` bundle 会随着自身的 `module.id` 的变化,而发生变化。
- `manifest` runtime 会因为现在包含一个新模块的引用,而发生变化。

第一个和最后一个都是符合预期的行为,`vendor` hash 发生变化是我们要修复的。我们将 [`optimization.moduleIds`](/configuration/optimization/#optimizationmoduleids) 设置为 `'deterministic'`
上面的第一点与最后一点都是符合预期的行为,而 `vendor` 的哈希值发生变化是我们要修复的。试试将 [`optimization.moduleIds`](/configuration/optimization/#optimizationmoduleids) 设置为 `'deterministic'`

**webpack.config.js**

Expand Down Expand Up @@ -288,7 +289,7 @@ webpack-demo
};
```

现在,不论是否添加任何新的本地依赖,对于前后两次构建,`vendor` hash 都应该保持一致
现在,不论是否添加任何新的本地依赖,对于前后两次构建,`vendor` 的哈希值都应保持一致

```bash
...
Expand All @@ -301,7 +302,7 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
...
```

然后,修改 `src/index.js`临时移除额外的依赖:
接下来修改 `src/index.js` 临时移除额外的依赖:

**src/index.js**

Expand All @@ -313,7 +314,7 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
function component() {
const element = document.createElement('div');

// lodash 是由当前 script 脚本 import 进来的
// lodash 现在使用 import 引入
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
- element.onclick = Print.bind(null, 'Hello webpack!');
+ // element.onclick = Print.bind(null, 'Hello webpack!');
Expand All @@ -324,7 +325,7 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
document.body.appendChild(component());
```

最后,再次运行我们的构建
最后,再次执行构建

```bash
...
Expand All @@ -337,8 +338,8 @@ Entrypoint main = runtime.725a1a51ede5ae0cfde0.js vendors.55e79e5927a639d21a1b.j
...
```

我们可以看到,这两次构建中`vendor` bundle 文件名称,都是 `55e79e5927a639d21a1b`
可以看到,在这两次构建中`vendor` bundle 的文件名称都是 `55e79e5927a639d21a1b`

## 结论 $#conclusion$
## 总结 $#conclusion$

缓存可能很复杂,但是从应用程序或站点用户可以获得的收益来看,这值得付出努力。想要了解更多信息,请查看下面 *进一步阅读* 部分。
缓存可能很复杂,但是从应用程序或站点用户可以获得的收益来看,这值得付出努力。想要了解更多信息,请查看下面 **进一步阅读** 部分。

0 comments on commit 8d9fb62

Please sign in to comment.