サーバーのコードでは、リクエストに対して * ハンドラーを使い、任意の URL を受け取ります。
このURLをVueに渡せば、Vueのルーティングを操作できます。
これを行うには、公式のvue-routerを使用することをお勧めします。
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export function createRouter () {
return new Router({
mode: 'history',
routes: [
// ...
]
})
}
// app.js
import Vue from 'vue'
import App from './App.vue'
import { createRouter } from './router'
export function createApp () {
// ルーターのインスタンスを作成する
const router = createRouter()
const app = new Vue({
router, //
render: h => h(App)
})
// アプリとルーターを返す
return { app, router }
}
サーバー内のjsバンドルは次のようになります。
// entry-server.js
import { createApp } from './app'
export default context => {
// 非同期のルーティングフック関数やコンポーネントになる可能性があるので、Promiseを返す。,
// というのも、コンポーネント内に存在する可能性のあるルーティングフックを正しく呼び出すために、ルーターはルーティング設定内の非同期コンポーネントを前もって解析しておく必要があるからだ。,
// オンレディ。
return new Promise((resolve, reject) => {
const { app, router } = createApp()
// サーバー側ルーターの場所を設定する
router.push(context.url)
// ルーターが可能性のある非同期コンポーネントとフック関数を解析し終わるまでに、不活性ロードされたコンポーネントも解析できる。
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
// マッチしないルートに対しては、reject関数が実行され、404が返される。
if (!matchedComponents.length) {
return reject({ code: 404 })
}
// Promise をレンダリングできるように、アプリのインスタンスを解決する必要がある。
resolve(app)
}, reject)
})
}
このアプリは
// server.js
const createApp = require('/path/to/built-server-bundle.js')
server.get('*', (req, res) => {
const context = { url: req.url }
createApp(context).then(app => {
renderer.renderToString(app, (err, html) => {
if (err) {
if (err.code === 404) {
res.status(404).end('Page not found')
} else {
res.status(500).end('Internal Server Error')
}
} else {
res.end(html)
}
})
})
})
コンポーネント内に存在する可能性のあるルーティングフックを正しく呼び出すために、ルータは前もってルーティング設定内の非同期コンポーネントを解析する必要があるからです。
// entry-client.js
import { createApp } from './app'
const { app, router } = createApp()
router.onReady(() => {
app.$mount('#app')
})





