Skip to content

Commit d3bf1a5

Browse files
committed
update async component and hydration sections
1 parent 2b0ce74 commit d3bf1a5

File tree

4 files changed

+16
-12
lines changed

4 files changed

+16
-12
lines changed

en/hydration.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Client Side Hydration
22

3+
Hydration refers to the client-side process during which Vue takes over the static HTML sent by the server and turns it into dynamic DOM that can react to client-side data changes.
4+
35
In `entry-client.js`, we are simply mounting the app with this line:
46

57
``` js

en/routing.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ import Foo from './Foo.vue'
116116
const Foo = () => import('./Foo.vue')
117117
```
118118

119-
This would work under any scenario if you are building a pure client-side Vue app. However, there are some limitations when using this in SSR. First, you need to resolve all the async components upfront on the server before starting the render, because otherwise you will just get an empty placeholder in the markup. On the client, you also need to do this before starting the hydration, otherwise the client will run into content mismatch errors.
119+
Prior to Vue 2.5, this only worked for route-level components. However, with improvements to the core hydration algorithm in 2.5+, this now works seamlessly anywhere in your app.
120120

121-
This makes it a bit tricky to use async components at arbitrary locations in your app (we will likely improve this in the future). However, **it works seamlessly if you do it at the route level** - i.e. use async components in your route configuration - because `vue-router` will automatically resolve matched async components when resolving a route. What you need to do is make sure to use `router.onReady` on both server and client. We already did that in our server entry, and now we just need to update the client entry:
121+
Note that it is still necessary to use `router.onReady` on both server and client before returning / mounting the app, because the router must resolve async route components ahead of time in order to properly invoke in-component hooks. We already did that in our server entry, and now we just need to update the client entry:
122122

123123
``` js
124124
// entry-client.js

zh/hydration.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
1-
# 客户端混合
1+
# 客户端激活 (Client-side Hydration)
22

3-
`entry-client.js` 中,我们用下面这行挂载(mount)应用程序:
3+
所谓客户端激活,指的是 Vue 在浏览器端接管由服务端发送的静态 HTML,使其变为由 Vue 管理的动态 DOM 的过程。
4+
5+
`entry-client.js` 中,我们用下面这行挂载 (mount) 应用程序:
46

57
```js
68
// 这里假定 App.vue template 根元素的 `id="app"`
79
app.$mount('#app')
810
```
911

10-
由于服务器已经渲染好标记(markup),我们显然无需将其丢弃,然后重新创建所有的 DOM 元素。相反,我们需要"混合"静态标记,然后将它们变为响应式
12+
由于服务器已经渲染好了 HTML,我们显然无需将其丢弃再重新创建所有的 DOM 元素。相反,我们需要"激活"这些静态的 HTML,然后使他们成为动态的(能够响应后续的数据变化)
1113

1214
如果你检查服务器渲染的输出结果,你会注意到应用程序的根元素有一个特殊的属性:
1315

1416
```js
1517
<div id="app" data-server-rendered="true">
1618
```
1719

18-
`data-server-rendered` 特殊属性,让客户端 Vue 知道标记是由服务器渲染,并且应该以混合模式进行挂载
20+
`data-server-rendered` 特殊属性,让客户端 Vue 知道这部分 HTML 是由 Vue 在服务端渲染的,并且应该以激活模式进行挂载
1921

20-
在开发模式下,Vue 将推断客户端生成的虚拟 DOM 树(virtual DOM tree),是否与从服务器渲染的 DOM 结构(DOM structure)匹配。如果无法匹配,它将退出混合模式,丢弃现有的 DOM 并从头开始渲染。**在生产模式下,可以禁用此推断,以获得最佳性能**
22+
在开发模式下,Vue 将推断客户端生成的虚拟 DOM 树 (virtual DOM tree),是否与从服务器渲染的 DOM 结构 (DOM structure)匹配。如果无法匹配,它将退出混合模式,丢弃现有的 DOM 并从头开始渲染。**在生产模式下,此检测会被跳过,以避免性能损耗**
2123

22-
### 混合说明(Hydration Caveats)
24+
### 一些需要注意的坑
2325

2426
使用「SSR + 客户端混合」时,需要了解的一件事是,浏览器可能会更改的一些特殊的 HTML 结构。例如,当你在 Vue 模板中写入:
2527

@@ -29,4 +31,4 @@ app.$mount('#app')
2931
</table>
3032
```
3133

32-
浏览器会在 `<table>` 内部自动注入 `<tbody>`,然而,由于 Vue 生成的虚拟 DOM(virtual DOM) 不包含 `<tbody>`,所以会导致无法匹配。为能够正确匹配,请确保在模板中写入有效的 HTML。
34+
浏览器会在 `<table>` 内部自动注入 `<tbody>`,然而,由于 Vue 生成的虚拟 DOM (virtual DOM) 不包含 `<tbody>`,所以会导致无法匹配。为能够正确匹配,请确保在模板中写入有效的 HTML。

zh/routing.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ server.get('*', (req, res) => {
9393

9494
## 代码分割
9595

96-
应用程序的代码分割或惰性加载,有助于减少浏览器在初始渲染中下载的资源体积,可以极大地改善大体积 bundle 的可交互时间(TTI - time-to-interactive)。这里的关键在于,对初始首屏而言,"只加载所需"。
96+
应用程序的代码分割或惰性加载,有助于减少浏览器在初始渲染中下载的资源体积,可以极大地改善大体积 bundle 的可交互时间 (TTI - time-to-interactive)。这里的关键在于,对初始首屏而言,"只加载所需"。
9797

9898
Vue 提供异步组件作为第一类的概念,将其与 [webpack 2 所支持的使用动态导入作为代码分割点](https://webpack.js.org/guides/code-splitting-async/)相结合,你需要做的是:
9999

@@ -104,9 +104,9 @@ import Foo from './Foo.vue'
104104
const Foo = () => import('./Foo.vue')
105105
```
106106

107-
如果你正在构建纯客户端 Vue 应用程序,这将在任何情况下运行。但是,在 SSR 中使用时有一些限制。首先,你需要在启动渲染之前先在服务器上解析所有的异步组件,否则你将在标记中获得一个空的占位符。在客户端,你还需要在开始混合之前执行此操作,否则客户端将遇到内容不匹配错误
107+
Vue 2.5 以下的版本中,服务端渲染时异步组件只能用在路由组件上。然而在 2.5+ 的版本中,得益于核心算法的升级,异步组件现在可以在应用中的任何地方使用
108108

109-
这使得在应用程序中的任意位置使用异步组件变得有点棘手(我们将来可能会改进这一点)。但是,**如果你在路由级别完成以上,可以实现无缝运行**(即在路由配置中使用异步组件),因为在解析路由时,`vue-router` 将自动解析匹配的异步组件。你需要做的是确保在服务器和客户端上都使用 `router.onReady`。我们已经在我们的服务器入口(server entry)中实现过了,现在我们只需要更新客户端入口(client entry):
109+
需要注意的是,你任然需要在挂载 app 之前调用 `router.onReady`,因为路由器必须要提前解析路由配置中的异步组件,才能正确地调用组件中可能存在的路由钩子。这一步我们已经在我们的服务器入口 (server entry) 中实现过了,现在我们只需要更新客户端入口 (client entry):
110110

111111
```js
112112
// entry-client.js

0 commit comments

Comments
 (0)