Vue.js SSR 基本用法

2021-01-07 15:34 更新

安裝

  1. npm install vue vue-server-renderer --save

我們將在整個指南中使用 NPM,但你也可以使用 Yarn 。

注意

  • 推薦使用 Node.js 版本 6+。
  • vue-server-renderervue 必須匹配版本。
  • vue-server-renderer 依賴一些 Node.js 原生模塊,因此只能在 Node.js 中使用。我們可能會提供一個更簡單的構(gòu)建,可以在將來在其他「JavaScript 運(yùn)行時(runtime)」運(yùn)行。

渲染一個 Vue 實(shí)例

  1. // 第 1 步:創(chuàng)建一個 Vue 實(shí)例
  2. const Vue = require('vue')
  3. const app = new Vue({
  4. template: `<div>Hello World</div>`
  5. })
  6. // 第 2 步:創(chuàng)建一個 renderer
  7. const renderer = require('vue-server-renderer').createRenderer()
  8. // 第 3 步:將 Vue 實(shí)例渲染為 HTML
  9. renderer.renderToString(app, (err, html) => {
  10. if (err) throw err
  11. console.log(html)
  12. // => <div data-server-rendered="true">Hello World</div>
  13. })
  14. // 在 2.5.0+,如果沒有傳入回調(diào)函數(shù),則會返回 Promise:
  15. renderer.renderToString(app).then(html => {
  16. console.log(html)
  17. }).catch(err => {
  18. console.error(err)
  19. })

與服務(wù)器集成

在 Node.js 服務(wù)器中使用時相當(dāng)簡單直接,例如 Express

  1. npm install express --save

  1. const Vue = require('vue')
  2. const server = require('express')()
  3. const renderer = require('vue-server-renderer').createRenderer()
  4. server.get('*', (req, res) => {
  5. const app = new Vue({
  6. data: {
  7. url: req.url
  8. },
  9. template: `<div>訪問的 URL 是: {{ url }}</div>`
  10. })
  11. renderer.renderToString(app, (err, html) => {
  12. if (err) {
  13. res.status(500).end('Internal Server Error')
  14. return
  15. }
  16. res.end(`
  17. <!DOCTYPE html>
  18. <html lang="en">
  19. <head><title>Hello</title></head>
  20. <body>${html}</body>
  21. </html>
  22. `)
  23. })
  24. })
  25. server.listen(8080)

使用一個頁面模板

當(dāng)你在渲染 Vue 應(yīng)用程序時,renderer 只從應(yīng)用程序生成 HTML 標(biāo)記 (markup)。在這個示例中,我們必須用一個額外的 HTML 頁面包裹容器,來包裹生成的 HTML 標(biāo)記。

為了簡化這些,你可以直接在創(chuàng)建 renderer 時提供一個頁面模板。多數(shù)時候,我們會將頁面模板放在特有的文件中,例如 index.template.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head><title>Hello</title></head>
  4. <body>
  5. <!--vue-ssr-outlet-->
  6. </body>
  7. </html>

注意 <!--vue-ssr-outlet--> 注釋 -- 這里將是應(yīng)用程序 HTML 標(biāo)記注入的地方。

然后,我們可以讀取和傳輸文件到 Vue renderer 中:

  1. const renderer = require('vue-server-renderer').createRenderer({
  2. template: require('fs').readFileSync('./index.template.html', 'utf-8')
  3. })
  4. renderer.renderToString(app, (err, html) => {
  5. console.log(html) // html 將是注入應(yīng)用程序內(nèi)容的完整頁面
  6. })

模板插值

模板還支持簡單插值。給定如下模板:

  1. <html>
  2. <head>
  3. <!-- 使用雙花括號(double-mustache)進(jìn)行 HTML 轉(zhuǎn)義插值(HTML-escaped interpolation) -->
  4. <title>{{ title }}</title>
  5. <!-- 使用三花括號(triple-mustache)進(jìn)行 HTML 不轉(zhuǎn)義插值(non-HTML-escaped interpolation) -->
  6. {{{ meta }}}
  7. </head>
  8. <body>
  9. <!--vue-ssr-outlet-->
  10. </body>
  11. </html>

我們可以通過傳入一個"渲染上下文對象",作為 renderToString 函數(shù)的第二個參數(shù),來提供插值數(shù)據(jù):

  1. const context = {
  2. title: 'hello',
  3. meta: `
  4. <meta ...>
  5. <meta ...>
  6. `
  7. }
  8. renderer.renderToString(app, context, (err, html) => {
  9. // 頁面 title 將會是 "Hello"
  10. // meta 標(biāo)簽也會注入
  11. })

也可以與 Vue 應(yīng)用程序?qū)嵗蚕?context 對象,允許模板插值中的組件動態(tài)地注冊數(shù)據(jù)。

此外,模板支持一些高級特性,例如:

  • 在使用 *.vue 組件時,自動注入「關(guān)鍵的 CSS(critical CSS)」;
  • 在使用 clientManifest 時,自動注入「資源鏈接(asset links)和資源預(yù)加載提示(resource hints)」;
  • 在嵌入 Vuex 狀態(tài)進(jìn)行客戶端融合(client-side hydration)時,自動注入以及 XSS 防御。

在之后的指南中介紹相關(guān)概念時,我們將詳細(xì)討論這些。

完整實(shí)例代碼

  1. const Vue = require('vue');
  2. const server = require('express')();
  3. const template = require('fs').readFileSync('./index.template.html', 'utf-8');
  4. const renderer = require('vue-server-renderer').createRenderer({
  5. template,
  6. });
  7. const context = {
  8. title: 'vue ssr',
  9. metas: `
  10. <meta name="keyword" content="vue,ssr">
  11. <meta name="description" content="vue srr demo">
  12. `,
  13. };
  14. server.get('*', (req, res) => {
  15. const app = new Vue({
  16. data: {
  17. url: req.url
  18. },
  19. template: `<div>訪問的 URL 是: {{ url }}</div>`,
  20. });
  21. renderer
  22. .renderToString(app, context, (err, html) => {
  23. console.log(html);
  24. if (err) {
  25. res.status(500).end('Internal Server Error')
  26. return;
  27. }
  28. res.end(html);
  29. });
  30. })
  31. server.listen(8080);
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號