Skip to content

Commit 8c73728

Browse files
committed
Merge remote-tracking branch 'upstream/master' into working
# Conflicts: # en/hydration.md # en/routing.md # en/universal.md
2 parents 01654b2 + 74fe9b4 commit 8c73728

File tree

8 files changed

+22
-16
lines changed

8 files changed

+22
-16
lines changed

en/hydration.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Hydratation côté client
22

3+
L'hydratation fait référence au processus côté client pendant lequel Vue va prendre la main sur le HTML statique envoyé par le serveur et le transformer en un DOM capable de réagir aux changements réactifs des données côté client.
4+
35
Dans `entry-client.js`, nous montons simplement l'application avec cette ligne :
46

57
``` js

en/routing.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ import Foo from './Foo.vue'
119119
const Foo = () => import('./Foo.vue')
120120
```
121121

122-
Cela fonctionnera dans n'importe quel scénario si vous êtes en train de faire une application Vue uniquement pour le côté client. Toutefois, il y aura certaines limitations en l'utilisant avec du SSR. Premièrement, il faut résoudre tous les composants asynchrones à l'avance sur le serveur avant de faire le rendu, car sinon il y aura juste un emplacement vide dans le code HTML. Pour le côté client, il faut aussi faire cela avant de commencer l'hydratation des données, sinon il y aurait des erreurs d'incompatibilités sur le contenu.
122+
Jusqu'en Vue 2.5, cela fonctionnait pour les composants au niveau des routes. Cependant, avec les améliorations des algorithmes en 2.5+, cela fonctionne maintenant parfaitement partout dans votre application.
123123

124-
Tout cela rend un peu compliquée l'utilisation des composants asynchrones à des endroits spécifiques dans votre application (nous allons probablement améliorer cela dans le futur). Toutefois, **cela fonctionne parfaitement si vous le faites au niveau de la route** - c.-à-d. d'utiliser les composants asynchrones dans la configuration des routes - car `vue-router` ira automatiquement résoudre les composants asynchrones nécessaires au bon fonctionnement de la route. Vous devez être sûr d'utiliser `router.onReady` sur le serveur et le client. Nous l'avons déjà fait pour le fichier d'entrée du serveur, il ne nous reste plus maintenant qu'à faire de même pour le fichier d'entrée du client :
124+
Notez qu'il est toujours nécessaire d'utiliser `router.onReady` côté client et côté serveur avant le renvoi / le montage de l'application, car le routeur doit résoudre les composants de route asynchrones à l'avance pour correctement déclencher les hooks des composants. Nous avons déjà fait cela dans notre entrée serveur et maintenant nous allons faire de même pour l'entrée cliente :
125125

126126
``` js
127127
// entry-client.js

en/universal.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Une autre chose à noter est que vous devriez éviter la création d'effets de b
1818

1919
Le code universel ne peut pas accéder aux APIs spécifiques à une plateforme. Ainsi, si votre code utilise directement les variables globales exclusives au navigateur comme `window` ou `document`, elles lèveront des erreurs si elles sont exécutées sur Node.js, et vice-versa.
2020

21-
Pour les tâches partagées entre le serveur et le client, mais qui utilisent des APIs différentes selon la plateforme, il est recommandé d'encapsuler le code spécifique à la plateforme dans une API universelle, ou d'utiliser des bibliothèques qui le font pour vous. Par exemple, [axios](https://github.com/mzabriskie/axios) est un client HTTP qui présente la même API côté serveur et côté client.
21+
Pour les tâches partagées entre le serveur et le client, mais qui utilisent des APIs différentes selon la plateforme, il est recommandé d'encapsuler le code spécifique à la plateforme dans une API universelle, ou d'utiliser des bibliothèques qui le font pour vous. Par exemple, [axios](https://github.com/axios/axios) est un client HTTP qui présente la même API côté serveur et côté client.
2222

2323
Pour les APIs exclusives au navigateur, l'approche habituelle est de les utiliser dans les hooks de cycle de vie exclusifs au client.
2424

ru/hydration.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Гидратация клиентской части
22

3+
Гидратация относится к процессу на стороне клиента, в течение которого Vue берёт статический HTML, отправленный сервером, и превращает его в динамический DOM, который может реагировать на изменения данных на стороне клиента.
4+
35
В файле `entry-client.js`, мы просто монтируем приложение такой строкой:
46

57
``` js

ru/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-
Это будет работать в любом сценарии, если вы создаёте чисто клиентское приложение Vue. Однако есть некоторые ограничения при использовании серверного рендеринга. Во-первых, вам нужно разрешить все асинхронные компоненты на сервере перед началом рендеринга, потому что иначе вы просто получите пустое место в разметке. На клиенте вам также нужно сделать это перед началом гидратации, иначе клиент столкнётся с ошибками несоответствующего содержимого.
119+
До версии Vue 2.5 это работало только для компонентов уровня маршрута. Однако, с улучшением алгоритма гидратации в ядре, с версии 2.5.0+ теперь это работает без проблем в любом месте вашего приложения.
120120

121-
Это делает использование асинхронных компонентов в произвольных местах вашего приложения непростой задачей (в скором времени мы планируем исправить эту ситуацию). Однако, **это будет работать без сбоев, если вы делаете это на уровне маршрутов** — т.е. используете асинхронные компоненты в конфигурации ваших маршрутов — потому что `vue-router` автоматически будет разрешать требуемые асинхронные компоненты при разрешении маршрута. Что вам нужно сделать, это убедиться что используете `router.onReady` и на сервере и на клиенте. Мы уже сделали это в серверной точке входа, и теперь нам нужно обновить клиентскую точку входа:
121+
Обратите внимание, что по-прежнему необходимо использовать `router.onReady` как на сервере, так и на клиенте перед возвратом / монтированием приложения, потому что маршрутизатор должен заранее разрешить все асинхронные компоненты маршрутов для правильного вызова хуков компонентов. Мы уже сделали это в серверной точке входа, и теперь нам нужно обновить клиентскую точку входа:
122122

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

zh/build-config.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const renderer = createBundleRenderer('/path/to/vue-ssr-server-bundle.json', {
5252
})
5353
```
5454

55-
又或者,你还可以将 bundle 作为对象传递给 `createBundleRenderer`这对开发过程中的热重新是很有用的 - 具体请查看 HackerNews demo 的[参考设置](https://github.com/vuejs/vue-hackernews-2.0/blob/master/build/setup-dev-server.js)
55+
又或者,你还可以将 bundle 作为对象传递给 `createBundleRenderer`这对开发过程中的热重载是很有用的 - 具体请查看 HackerNews demo 的[参考设置](https://github.com/vuejs/vue-hackernews-2.0/blob/master/build/setup-dev-server.js)
5656

5757
### 扩展说明(Externals Caveats)
5858

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)