4
4
5
5
クライアントのみのコードを書くとき、コードは毎回新しいコンテキストで評価されると考えることができます。しかし、 Node.js サーバは長時間実行されるプロセスです。コードがプロセスにはじめて要求されるとき、コードは一度評価されメモリ内にとどまります。つまり、シングルトンのオブジェクトを作成すると、すべての受信リクエストの間で共有されることになり、リクエスト間での状態の汚染リスクがあるということです。
6
6
7
- よって、 ** リクエストごとに新しいルート Vue インスタンスを作成する** 必要があります。そのためには、リクエストごとに新しいアプリケーションのインスタンスを作成する、繰り返し実行可能なファクトリ関数を書く必要があります:
7
+ よって、 ** リクエストごとに新しいルート Vue インスタンスを作成する** 必要があります。そのためには、リクエストごとに新しいアプリケーションのインスタンスを作成する、繰り返し実行可能なファクトリ関数を書く必要があります。したがって、サーバコードは次のようになります :
8
8
9
9
``` js
10
- // app .js
10
+ // server .js
11
11
const { createSSRApp } = require (' vue' )
12
+ const { renderToString } = require (' @vue/server-renderer' )
13
+ const express = require (' express' )
14
+
15
+ const server = express ()
12
16
13
17
function createApp () {
14
18
return createSSRApp ({
@@ -20,15 +24,6 @@ function createApp() {
20
24
template: ` <div>Current user is: {{ user }}</div>`
21
25
})
22
26
}
23
- ```
24
-
25
- そして、サーバコードはこのようになります:
26
-
27
- ``` js
28
- // server.js
29
- const { renderToString } = require (' @vue/server-renderer' )
30
- const server = require (' express' )()
31
- const { createApp } = require (' src/app.js' )
32
27
33
28
server .get (' *' , async (req , res ) => {
34
29
const app = createApp ()
@@ -49,7 +44,7 @@ server.get('*', async (req, res) => {
49
44
server .listen (8080 )
50
45
```
51
46
52
- 同じルールが他のインスタンス(ルータやストアなど)にも当てはまります。ルータやストアをモジュールから直接エクスポートしてアプリケーション全体にインポートするのではなく、 ` createApp ` で新しいインスタンスを作成して、ルート Vue インスタンスから注入する必要があります。
47
+ 同じルールが他のインスタンス(ルータやストアなど)にも当てはまります。ルータやストアをモジュールから直接エクスポートしてアプリケーション全体にインポートするのではなく、新しいリクエストがくるたびに ` createApp ` で新しいインスタンスを作成して、ルートの Vue インスタンスから注入する必要があります。
53
48
54
49
## ビルド手順の導入
55
50
76
71
├── components
77
72
│ ├── MyUser.vue
78
73
│ └── MyTable.vue
79
- ├── App.vue
80
- ├── app.js # 共通のエントリ
74
+ ├── App.vue # アプリケーションのルート
81
75
├── entry-client.js # ブラウザでのみ実行
82
76
└── entry-server.js # サーバでのみ実行
83
77
```
84
78
85
- ### ` app.js `
79
+ ### ` App.vue `
86
80
87
- ` app.js ` は、アプリケーションの共通のエントリです。クライアント専用のアプリケーションでは、このファイルの中で Vue アプリケーションのインスタンスを作成して、 DOM に直接マウントします。しかし SSR では、その責務はクライアント専用のエントリファイルに移されます。代わりに ` app .js` でアプリケーションのインスタンスを作成して、エクスポートします :
81
+ お気づきかもしれませんが、 ` src ` フォルダのルートに ` App.vue ` というファイルがあります。このファイルにはアプリケーションのルートコンポーネントが格納されています。これでアプリケーションコードを安全に ` server .js` から ` App.vue ` ファイルに移動することができます :
88
82
89
- ``` js
90
- import { createSSRApp } from ' vue'
91
- import App from ' ./App.vue'
92
-
93
- // ルートコンポーネントを作成するためのファクトリ関数をエクスポート
94
- export default function (args ) {
95
- const app = createSSRApp (App)
83
+ ``` vue
84
+ <template>
85
+ <div>Current user is: {{ user }}</div>
86
+ </template>
96
87
97
- return {
98
- app
88
+ <script>
89
+ export default {
90
+ name: 'App',
91
+ data() {
92
+ return {
93
+ user: 'John Doe'
94
+ }
99
95
}
100
96
}
97
+ </script>
101
98
```
102
99
103
100
### ` entry-client.js `
104
101
105
- クライアント用のエントリは、ルートコンポーネントのファクトリを使ってアプリケーションを作成し、 DOM にマウントします:
102
+ クライアント用のエントリは、` App.vue ` コンポーネントを使ってアプリケーションを作成し、それを DOM にマウントします:
106
103
107
104
``` js
108
- import createApp from ' ./app'
105
+ import { createSSRApp } from ' vue'
106
+ import App from ' ./App.vue'
109
107
110
108
// クライアント固有の初回起動ロジック
111
109
112
- const { app } = createApp ({
113
- // ここでアプリケーションのファクトリに追加の引数を渡すことが可能
114
- })
110
+ const app = createSSRApp (App)
115
111
116
112
// これは App.vue テンプレートのルート要素に `id="app"` が前提
117
113
app .mount (' #app' )
@@ -122,12 +118,11 @@ app.mount('#app')
122
118
サーバ用のエントリは、レンダリングごとに繰り返し呼び出される関数を default でエクスポートします。いまのところは、アプリケーションのインスタンスを返す以外の機能はありませんが、あとでサーバサイドのルートマッチングやデータのプリフェッチのロジックをここに加えます。
123
119
124
120
``` js
125
- import createApp from ' ./app'
121
+ import { createSSRApp } from ' vue'
122
+ import App from ' ./App.vue'
126
123
127
- export default function () {
128
- const { app } = createApp ({
129
- /* ...*/
130
- })
124
+ export default function () {
125
+ const app = createSSRApp (Vue)
131
126
132
127
return {
133
128
app
0 commit comments