diff --git a/src/guide/ssr/routing.md b/src/guide/ssr/routing.md index 05fe4575f9..e52fd982ec 100644 --- a/src/guide/ssr/routing.md +++ b/src/guide/ssr/routing.md @@ -8,34 +8,50 @@ It is recommended to use the official [vue-router](https://github.com/vuejs/vue- ```js // router.js -import { createRouter, createMemoryHistory, createWebHistory } from 'vue-router' +import { createRouter } from 'vue-router' import MyUser from './components/MyUser.vue' -const isServer = typeof window === 'undefined' - -const createHistory = isServer ? createMemoryHistory : createWebHistory - const routes = [{ path: '/user', component: MyUser }] -export default function() { +export default function (history) { return createRouter({ - history: createHistory(), + history, routes }) } ``` -And update our `app.js`, client and server entries: +And update our client and server entries: + +```js +// entry-client.js +import { createApp } from 'vue' +import { createWebHistory } from 'vue-router' +import createRouter from './router.js' +import App from './App.vue' + +// ... + +const app = createApp(App) + +const router = createRouter(createWebHistory()) + +app.use(router) + +// ... +``` ```js -// app.js +// entry-server.js import { createSSRApp } from 'vue' +// server router uses a different history from the client one +import { createMemoryHistory } from 'vue-router' +import createRouter from './router.js' import App from './App.vue' -import createRouter from './router' -export default function(args) { - const app = createSSRApp(App) - const router = createRouter() +export default function () { + const app = createSSRApp(Vue) + const router = createRouter(createMemoryHistory()) app.use(router) @@ -46,20 +62,6 @@ export default function(args) { } ``` -```js -// entry-client.js -const { app, router } = createApp({ - /*...*/ -}) -``` - -```js -// entry-server.js -const { app, router } = createApp({ - /*...*/ -}) -``` - ## Code-Splitting Code-splitting, or lazy-loading part of your app, helps reduce the size of assets that need to be downloaded by the browser for the initial render, and can greatly improve TTI (time-to-interactive) for apps with large bundles. The key is "loading just what is needed" for the initial screen. @@ -77,15 +79,20 @@ const routes = [ ] ``` -On both client and server we need to wait for router to resolve async route components ahead of time in order to properly invoke in-component hooks. For this we will be using [router.isReady](https://next.router.vuejs.org/api/#isready) method Let's update our client entry: +On both client and server we need to wait for the router to resolve async route components ahead of time in order to properly invoke in-component hooks. For this we will be using [router.isReady](https://next.router.vuejs.org/api/#isready) method Let's update our client entry: ```js // entry-client.js -import createApp from './app' +import { createApp } from 'vue' +import { createWebHistory } from 'vue-router' +import createRouter from './router.js' +import App from './App.vue' -const { app, router } = createApp({ - /* ... */ -}) +const app = createApp(App) + +const router = createRouter(createWebHistory()) + +app.use(router) router.isReady().then(() => { app.mount('#app') diff --git a/src/guide/ssr/server.md b/src/guide/ssr/server.md index 0a8b304c04..8f38e7d4ce 100644 --- a/src/guide/ssr/server.md +++ b/src/guide/ssr/server.md @@ -2,13 +2,14 @@ The [code structure](./structure.html) and [webpack configuration](./build-config.html) we've described also require some changes to our Express server code. -- we need to create an application with a built `app.js` from the resulting bundle. A path to it can be found using the webpack manifest: +- we need to create an application with a built `entry-server.js` from the resulting bundle. A path to it can be found using the webpack manifest: ```js // server.js const path = require('path') const manifest = require('./dist/server/ssr-manifest.json') + // the 'app.js' name is taken from the name of the entrypoint with an added `.js` postfix const appPath = path.join(__dirname, './dist', 'server', manifest['app.js']) const createApp = require(appPath).default ``` @@ -78,7 +79,7 @@ server.use( ) server.get('*', async (req, res) => { - const { app } = await createApp() + const { app } = createApp() const appContent = await renderToString(app) diff --git a/src/guide/ssr/structure.md b/src/guide/ssr/structure.md index 1fe86d676a..7c1095be20 100644 --- a/src/guide/ssr/structure.md +++ b/src/guide/ssr/structure.md @@ -4,11 +4,15 @@ When writing client-only code, we can assume that our code will be evaluated in a fresh context every time. However, a Node.js server is a long-running process. When our code is first imported by the process, it will be evaluated once and then stay in memory. This means that if you create a singleton object, it will be shared between every incoming request, with the risk of cross-request state pollution. -Therefore, we need to **create a new root Vue instance for each request.** In order to do that, we need to write a factory function that can be repeatedly executed to create fresh app instances for each request: +Therefore, we need to **create a new root Vue instance for each request.** In order to do that, we need to write a factory function that can be repeatedly executed to create fresh app instances for each request, so our server code now becomes: ```js -// app.js +// server.js const { createSSRApp } = require('vue') +const { renderToString } = require('@vue/server-renderer') +const express = require('express') + +const server = express() function createApp() { return createSSRApp({ @@ -20,15 +24,6 @@ function createApp() { template: `