vue ssr 從認識到構建一個工程項目(一)

vue ssr入門

前言

近期需要接手一個vue ssr項目,由於本人之前沒有寫過ssr,只是稍微瞭解了點。所以跟着官網學了下,並整理出了這篇學習筆記。方便自己以後對vue ssr知識的回顧。好記性不如爛筆頭。

介紹

相信大家在看到這篇文章之前,都知道ssr是什麼了。SSR,英文全稱叫 Server(服務) side(端) rendering (渲染)哈哈☺

那麼究竟什麼是服務器端渲染?

Vue.js 是構建客戶端應用程序的框架。默認情況下,可以在瀏覽器中輸出 Vue 組件,進行生成 DOM 和操作 DOM。然而,也可以將同一個組件渲染爲服務器端的 HTML 字符串,將它們直接發送到瀏覽器,最後將這些靜態標記"激活"爲客戶端上完全可交互的應用程序。

服務器渲染的 Vue.js 應用程序也可以被認爲是"同構"或"通用",因爲應用程序的大部分代碼都可以在服務器客戶端上運行。

如果你問我爲什麼使用ssr呢?(具體可參考官網)

  • 有利於seo。
  • 更快的內容到達時間 (time-to-content),特別是對於緩慢的網絡情況或運行緩慢的設備。大體可以理解爲渲染出頁面時間,csr比ssr多了個js下載時間。因爲ssr一開始加載下來就渲染出來了,然後在下載激活html的js。csr是下載完在渲染。

正文

基本用法

ssr主要依靠兩個包vue-server-renderervue(兩個版本必須匹配)

安裝: npm install vue vue-server-renderer --save

入門配置

ssr最簡易配置
// server.js
const server = require('express')()
const Vue = require('vue');
const renderer = require('vue-server-renderer').createRenderer();

server.get('*', (req, res) => {
    const context = {
        url: req.url
    }
    const app = new Vue({
        template: `<div>${context.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)

node server.js 瀏覽器輸入localhost:8080訪問該ssr頁面

這時候你可以看到,無論你輸入什麼路徑,頁面文本都會顯示出你的路徑

clipboard.png

ssr使用模板

當你在渲染 Vue 應用程序時,renderer 只從應用程序生成 HTML 標記 (markup)。在這個示例中,我們必須用一個額外的 HTML 頁面包裹容器,來包裹生成的 HTML 標記。純客戶端渲染的時候,會有一個模板,會插入你打包後的一些文件等。那麼ssr會不會也有這種模板呢?當然會有。

  • 首先在根目錄下新建一個index.template.html文件

    <!DOCTYPE html>
    <html lang="en">
      <head><title>Hello</title></head>
      <body>
        <!--vue-ssr-outlet-->
      </body>
    </html>

    注意了 --跟vue或者outlet跟--之間不能用空格。註釋 -- 這裏將是應用程序 HTML 標記注入的地方。

  • 接下來,修改下剛纔的server.js文件後如下

    const server = require('express')()
    const Vue = require('vue');
    const renderer = require('vue-server-renderer').createRenderer({
        template: require('fs').readFileSync('./index.template.html', 'utf-8')
    });
    server.get('*', (req, res) => {
        const context = {
            url: req.url
        }
        const app = new Vue({
            template: `<div>${context.url}</div>`
        })
        renderer.renderToString(app, (err, html) => {
            if (err) {
                res.status(500).end('Internal Server Error')
                return
            }
            res.end(html)
        })
    })
    
    server.listen(8080)

    就是在createRenderer中多加一個參數 template(讀取模板文件),並傳遞給createRenderer方法

    模板還支持插值

    <html>
      <head>
        <!-- 使用雙花括號(double-mustache)進行 HTML 轉義插值(HTML-escaped interpolation) -->
        <title>{{ title }}</title>
    
        <!-- 使用三花括號(triple-mustache)進行 HTML 不轉義插值(non-HTML-escaped interpolation) -->
        {{{ meta }}}
      </head>
      <body>
        <!--vue-ssr-outlet-->
      </body>
    </html>

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

    const context = {
      title: 'hello',
      meta: `
        <meta ...>
        <meta ...>
      `
    }
    
    renderer.renderToString(app, context, (err, html) => {
      // 頁面 title 將會是 "Hello"
      // meta 標籤也會注入
    })
編寫通用代碼

我們以往的純瀏覽器渲染都是把js下載到本地執行的。上述代碼你會發現都是用的同一個Vue構造函數,但是想對該構造函數做特殊處理時,就會對其他用戶造成污染。因此,我們不應該直接創建一個應用程序實例,而是應該暴露一個可以重複執行的工廠函數,爲每個請求創建新的應用程序實例:

// 修改原先代碼如下
-const Vue = require('vue');
+const createApp = require('./app.js')

-    const app = new Vue({
-        template: `<div>${context.url}</div>`
-    })
+    const { app } = createApp(context)

// 新增app.js
const Vue = require('vue');

module.exports = function createApp(context) {
    const app = new Vue({
        template: `<div>${context.url}</div>`
    })
    return { app }
}

這樣,每次訪問該服務器的時候,都會生成一個新的vue實例。同樣的規則也適用於 router、store 和 event bus 實例。你不應該直接從模塊導出並將其導入到應用程序中,而是需要在 createApp 中創建一個新的實例,並從根 Vue 實例注入。

參考

Vue SSR 指南

vue 服務端渲染ssr

帶你五步學會Vue SSR

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章