You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// This is the plugin that turns the entire output of the server build
@@ -62,9 +62,13 @@ The client config can remain largely the same with the base config. Obviously yo
62
62
63
63
> requires version 2.3.0+
64
64
65
-
In addition to the server bundle, we can also generate a client build manifest. With the client manifest and the server bundle, the renderer now has information of both the server *and* client builds, so it can automatically infer and inject [preload / prefetch directives](https://css-tricks.com/prefetching-preloading-prebrowsing/) and script tags into the rendered HTML.
65
+
In addition to the server bundle, we can also generate a client build manifest. With the client manifest and the server bundle, the renderer now has information of both the server *and* client builds, so it can automatically infer and inject [preload / prefetch directives](https://css-tricks.com/prefetching-preloading-prebrowsing/) and css links / script tags into the rendered HTML.
66
66
67
-
This is particularly useful when rendering a bundle that leverages webpack's on-demand code splitting features: we can ensure the optimal chunks are preloaded / prefetched, and also directly embed `<script>` tags for needed async chunks in the HTML to avoid waterfall requests on the client, thus improving TTI (time-to-interactive).
67
+
The benefits is two-fold:
68
+
69
+
1. It can replace `html-webpack-plugin` for injecting the correct asset URLs when there are hashes in your generated filenames.
70
+
71
+
2. When rendering a bundle that leverages webpack's on-demand code splitting features, we can ensure the optimal chunks are preloaded / prefetched, and also intelligently inject `<script>` tags for needed async chunks to avoid waterfall requests on the client, thus improving TTI (time-to-interactive).
68
72
69
73
To make use of the client manifest, the client config would look something like this:
70
74
@@ -97,7 +101,7 @@ You can then use the generated client manifest, together with a page template:
@@ -130,13 +134,71 @@ With this setup, your server-rendered HTML for a build with code-splitting will
130
134
</html>`
131
135
```
132
136
133
-
## More About Asset Injection
137
+
### Manual Asset Injection
138
+
139
+
Sometimes you might want finer-grained control over how assets are injected into the template, or maybe you are not using a template at all. In the `renderToString` callback, the `context` object you passed in will expose the following methods:
140
+
141
+
-`context.renderStyles()`
142
+
143
+
This will return inline `<style>` tags containing all the critical CSS collected from the `*.vue` components used during the render. See [CSS Management](./css.md) for more details.
144
+
145
+
If a `clientManifest` is provided, the returned string will also contain `<link rel="stylesheet">` tags for webpack-emitted CSS files (e.g. CSS extracted with `extract-text-webpack-plugin` or imported with `file-loader`)
146
+
147
+
-`context.renderState(options?: Object)`
148
+
149
+
This method serializes `context.state` and returns an inline script that embeds the state as `window.__INITIAL_STATE__`.
150
+
151
+
The context state key and window state key can both be customized by passing an options object:
152
+
153
+
```js
154
+
context.renderState({
155
+
contextKey:'myCustomState',
156
+
windowKey:'__MY_STATE__'
157
+
})
158
+
159
+
// -> <script>window.__MY_STATE__={...}</script>
160
+
```
161
+
162
+
-`context.renderScripts()`
163
+
164
+
- requires `clientManifest`
165
+
166
+
This method returns the `<script>` tags needed for the client application to boot. When using async code-splitting in the app code, this method will intelligently infer the correct async chunks to include.
167
+
168
+
-`context.renderResourceHints()`
169
+
170
+
- requires `clientManifest`
171
+
172
+
This method returns the `<link rel="preload/prefetch">` resource hints needed for the current rendered page. By default it will:
173
+
174
+
- Preload the JavaScript and CSS files needed by the page
175
+
- Prefetch async JavaScript chunks that might be needed later
176
+
177
+
Preloaded files can be further customized with the `shouldPreload` option.
178
+
179
+
Since the `template` passed to `createBundleRenderer` will be interpolated using `context`, you can make use of these methods inside the template (make sure to use triple-mustaches):
180
+
181
+
```html
182
+
<html>
183
+
<head>
184
+
{{{ renderResourceHints() }}}
185
+
{{{ renderStyles() }}}
186
+
</head>
187
+
<body>
188
+
<!--vue-ssr-outlet-->
189
+
{{{ renderState() }}}
190
+
{{{ renderScripts() }}}
191
+
</body>
192
+
</html>
193
+
```
194
+
195
+
If you are not using `template` at all, you can concatenate the strings yourself.
134
196
135
197
### `shouldPreload`
136
198
137
-
By default, only JavaScript chunks used during the server-side render will be preloaded, as they are absolutely needed for your application to boot.
199
+
By default, only JavaScript and CSS files will be preloaded, as they are absolutely needed for your application to boot.
138
200
139
-
For other types of assets such as images or fonts, how much and what to preload will be scenario-dependent. You can control precisely what to preload using the `shouldPreload` option:
201
+
For other types of assets such as images or fonts, preloading too much may waste bandwidth and even hurt performance, so what to preload will be scenario-dependent. You can control precisely what to preload using the `shouldPreload` option:
Copy file name to clipboardExpand all lines: en/bundle-renderer.md
+15-22Lines changed: 15 additions & 22 deletions
Original file line number
Diff line number
Diff line change
@@ -2,30 +2,22 @@
2
2
3
3
## Problems with Basic SSR
4
4
5
-
In our basic usage example, we directly required Vue and created an app instance in our Node.js server code. This is straightforward, however has quite a few issues in practice:
5
+
Up to this point, we have assumed that the bundled server-side code will be directly used by the server via `require`:
6
6
7
-
- Typical Vue apps are built with webpack and `vue-loader`, and many webpack-specific features such as importing files via `file-loader`, importing CSS via `css-loader` would not work directly in Node.js.
8
-
9
-
- Although the latest version of Node.js fully supports ES2015 features, we still need to transpile client-side code to cater to older browsers. This again involves a build step.
10
-
11
-
- Getting source maps to work with Node.js can be tricky.
- Directly requiring Vue app code in the server process means whenever you edit your app source code, you would have to stop and restart the server. Ideally, we want our server-rendering logic to be hot-reloadable too!
11
+
This is straightforward, however whenever you edit your app source code, you would have to stop and restart the server. This hurts productivity quite a bit during development. In addition, Node.js doesn't support source maps natively.
`vue-server-renderer` provides an API called `createBundleRenderer` to deal with these problems. The basic idea is that we use the same Vue app source code to generate two bundles - one for the client and one for the server. With a custom webpack plugin, the server bundle is generated as a special JSON file that can be passed to the bundle renderer. Once the bundle renderer is created, usage is the same as the normal renderer, however the bundle renderer provides the following benefits:
15
+
`vue-server-renderer` provides an API called `createBundleRenderer` to deal with this problem. With a custom webpack plugin, the server bundle is generated as a special JSON file that can be passed to the bundle renderer. Once the bundle renderer is created, usage is the same as the normal renderer, however the bundle renderer provides the following benefits:
20
16
21
-
- Reuse the vast majority of the app source code and build configuration for both server and client
22
-
23
-
- Built-in source map support for runtime errors
17
+
- Built-in source map support (with `devtool: 'source-map'`)
24
18
25
19
- Hot-reload during development and even deployment (by simply reading the updated bundle and re-creating the renderer instance)
- Critical CSS injection (when using `*.vue` files): automatically inlines the CSS needed by components used during the render. See the [CSS](./css.md) section for more details.
30
22
31
23
- Asset injection with [clientManifest](./client-manifest.md): automatically infers the optimal preload and prefetch directives, and the code-split chunks needed for the initial render.
@@ -35,13 +27,12 @@ In our basic usage example, we directly required Vue and created an app instance
35
27
We will discuss how to configure webpack to generate the build artifacts needed by the bundle renderer in the next section, but for now let's assume we already have what we need, and this is how to create a use a bundle renderer:
When `rendertoString` is called on a bundle renderer, it will automatically execute the function exported by the bundle to create an app instance (passing `context` as the argument) , and then render it.
Copy file name to clipboardExpand all lines: en/data.md
+12Lines changed: 12 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -148,6 +148,18 @@ export default context => {
148
148
}
149
149
```
150
150
151
+
When using `template`, `context.state` will automatically be embedded in the final HTML as `window.__INITIAL__` state. On the client, the store should pick up the state before mounting the application:
152
+
153
+
```js
154
+
// entry-client.js
155
+
156
+
const { app, router, store } =createApp()
157
+
158
+
if (window.__INITIAL_STATE__) {
159
+
store.replaceState(window.__INITIAL_STATE__)
160
+
}
161
+
```
162
+
151
163
## Client Data Fetching
152
164
153
165
On the client, there are two different approaches for handling data fetching:
Copy file name to clipboardExpand all lines: en/structure.md
+2Lines changed: 2 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -53,6 +53,8 @@ So far, we haven't discussed how to deliver the same Vue app to the client yet.
53
53
54
54
So the basic idea is we will be using webpack to bundle our app for both client and server - the server bundle will be required by the server and used for SSR, while the client bundle is sent to the browser to hydrate the static markup.
We will discuss the details of the setup in later sections - for now, let's just assume we've got the build setup figured out and we can write our Vue app code with webpack enabled.
0 commit comments