npm install vue vue-server-renderer --save
我們將在整個(gè)指南中使用 NPM,但你也可以使用 Yarn 。
vue-server-renderer
和 vue
必須匹配版本。vue-server-renderer
依賴一些 Node.js 原生模塊,因此只能在 Node.js 中使用。我們可能會提供一個(gè)更簡單的構(gòu)建,可以在將來在其他「JavaScript 運(yùn)行時(shí)(runtime)」運(yùn)行。// 第 1 步:創(chuàng)建一個(gè) Vue 實(shí)例
const Vue = require('vue')
const app = new Vue({
template: `<div>Hello World</div>`
})
// 第 2 步:創(chuàng)建一個(gè) renderer
const renderer = require('vue-server-renderer').createRenderer()
// 第 3 步:將 Vue 實(shí)例渲染為 HTML
renderer.renderToString(app, (err, html) => {
if (err) throw err
console.log(html)
// => <div data-server-rendered="true">Hello World</div>
})
// 在 2.5.0+,如果沒有傳入回調(diào)函數(shù),則會返回 Promise:
renderer.renderToString(app).then(html => {
console.log(html)
}).catch(err => {
console.error(err)
})
在 Node.js 服務(wù)器中使用時(shí)相當(dāng)簡單直接,例如 Express :
npm install express --save
const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer()
server.get('*', (req, res) => {
const app = new Vue({
data: {
url: req.url
},
template: `<div>訪問的 URL 是: {{ url }}</div>`
})
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
res.end(`
<!DOCTYPE html>
<html lang="en">
<head><title>Hello</title></head>
<body>${html}</body>
</html>
`)
})
})
server.listen(8080)
當(dāng)你在渲染 Vue 應(yīng)用程序時(shí),renderer 只從應(yīng)用程序生成 HTML 標(biāo)記 (markup)。在這個(gè)示例中,我們必須用一個(gè)額外的 HTML 頁面包裹容器,來包裹生成的 HTML 標(biāo)記。
為了簡化這些,你可以直接在創(chuàng)建 renderer 時(shí)提供一個(gè)頁面模板。多數(shù)時(shí)候,我們會將頁面模板放在特有的文件中,例如 index.template.html
:
<!DOCTYPE html>
<html lang="en">
<head><title>Hello</title></head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
注意 <!--vue-ssr-outlet-->
注釋 -- 這里將是應(yīng)用程序 HTML 標(biāo)記注入的地方。
然后,我們可以讀取和傳輸文件到 Vue renderer 中:
const renderer = require('vue-server-renderer').createRenderer({
template: require('fs').readFileSync('./index.template.html', 'utf-8')
})
renderer.renderToString(app, (err, html) => {
console.log(html) // html 將是注入應(yīng)用程序內(nèi)容的完整頁面
})
模板還支持簡單插值。給定如下模板:
<html>
<head>
<!-- 使用雙花括號(double-mustache)進(jìn)行 HTML 轉(zhuǎn)義插值(HTML-escaped interpolation) -->
<title>{{ title }}</title>
<!-- 使用三花括號(triple-mustache)進(jìn)行 HTML 不轉(zhuǎn)義插值(non-HTML-escaped interpolation) -->
{{{ meta }}}
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
我們可以通過傳入一個(gè)"渲染上下文對象",作為 renderToString
函數(shù)的第二個(gè)參數(shù),來提供插值數(shù)據(jù):
const context = {
title: 'hello',
meta: `
<meta ...>
<meta ...>
`
}
renderer.renderToString(app, context, (err, html) => {
// 頁面 title 將會是 "Hello"
// meta 標(biāo)簽也會注入
})
也可以與 Vue 應(yīng)用程序?qū)嵗蚕?context
對象,允許模板插值中的組件動態(tài)地注冊數(shù)據(jù)。
此外,模板支持一些高級特性,例如:
*.vue
組件時(shí),自動注入「關(guān)鍵的 CSS(critical CSS)」;clientManifest
時(shí),自動注入「資源鏈接(asset links)和資源預(yù)加載提示(resource hints)」;在之后的指南中介紹相關(guān)概念時(shí),我們將詳細(xì)討論這些。
const Vue = require('vue');
const server = require('express')();
const template = require('fs').readFileSync('./index.template.html', 'utf-8');
const renderer = require('vue-server-renderer').createRenderer({
template,
});
const context = {
title: 'vue ssr',
metas: `
<meta name="keyword" content="vue,ssr">
<meta name="description" content="vue srr demo">
`,
};
server.get('*', (req, res) => {
const app = new Vue({
data: {
url: req.url
},
template: `<div>訪問的 URL 是: {{ url }}</div>`,
});
renderer
.renderToString(app, context, (err, html) => {
console.log(html);
if (err) {
res.status(500).end('Internal Server Error')
return;
}
res.end(html);
});
})
server.listen(8080);
更多建議: