入職第一天:前端leader手把手教我入門Vue伺服器端渲染(SSR)

碼農土哥發表於2018-05-04

繼前段時間西安電面之後順利拿到了OFFER,今天(5月2號)是我入職第一天,在簡短的內部培訓了一上午後,前端leader讓我先了解下什麼是vue的伺服器端渲染(SSR)

入職第一天:前端leader手把手教我入門Vue伺服器端渲染(SSR)

SSR,英文全稱叫 Server side rendering ,國人叫它伺服器端渲染。

首先聽到這個名詞,我頭腦就有點眩暈。我們們還是先去官網瞭解下SSR的定義:

Vue.js 可以將同一個元件渲染為伺服器端的 HTML 字串,將它們直接傳送到瀏覽器,最後將靜態標記"混合"為客戶端上完全互動的應用程式。這種在伺服器和客戶端都可以執行的程式碼程式,也可以叫做“同構”。

我弱弱地問了leader一句,我們們公司為什麼要使用服務端渲染

leader冷冷地回覆,有兩點原因,第一點,因為我們公司的站點很注重SEO,頁面又是非同步獲取內容;第二點,同時也希望使用者更快速地看到完整渲染的頁面,從而提高使用者體驗。基於這兩點,所以需要伺服器端渲染(SSR)來解決這些問題。

那服務端渲染的流程究竟是怎樣的呢?話不多說,先上圖:

入職第一天:前端leader手把手教我入門Vue伺服器端渲染(SSR)

在使用服務端渲染的時候,首先要有個server端。因為在開發vue專案時,需要起一個webpack-dev-server的服務,埠8000。因為我們要使用它的熱更替,這樣能加快開發效率。

由於webpack是一個自主的server,我們沒有辦法在裡面新增服務端渲染的程式碼,而這段程式碼是需要自己去寫的,所以需要再起一個node server,去執行服務端渲染的邏輯。我們會用到vue-server-renderer這個包來幫我們在node.js環境裡面去渲染出vue程式碼生成的HTML程式碼,這部分程式碼是直接返回給使用者的,使用者可以在瀏覽器裡直接看到HTML的內容。

以圖為例,我們看到兩個渲染的過程,兩種server。如果直接訪問webpack-dev-server,就跟我們之前開發的過程一樣,它是一個純前端渲染的過程。如果我們要走服務端渲染的流程,就要走node server服務,埠3333以示區別。而且需要打包一個邏輯到node端執行,通過webpack-server-compiler去生成一個server bundle,也就是服務端的app.js。 當node server 獲取到server bundle之後,就可以執行vue-server-renderer,去渲染出HTML的程式碼,直接返回給使用者,這樣的話就不需要通過js再去渲染出頁面內容,減少了使用者的等待時間。

今天這篇文章的主要任務是,先用webpack建立一個配置檔案來打包server端的程式碼。

入門第一步,如何編寫伺服器端渲染的配置檔案?

首先我們需要在專案根目錄裡面找到build資料夾,然後在其下面新建一個webpack.config.server.js檔案,具體配置程式碼,我先擼為敬:

const path = require('path')
const ExtractPlugin = require('extract-text-webpack-plugin')
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseConfig = require('./webpack.config.base')
const VueServerPlugin = require('vue-server-renderer/server-plugin')

let config

config = merge(baseConfig, {
  target: 'node',
  entry: path.join(__dirname, '../client/server-entry.js'),
  devtool: 'source-map',
  output: {
    libraryTarget: 'commonjs2',
    filename: 'server-entry.js',
    path: path.join(__dirname, '../server-build')
  },
  externals: Object.keys(require('../package.json').dependencies),
  module: {
    rules: [
      {
        test: /\.styl/,
        use: ExtractPlugin.extract({
          fallback: 'vue-style-loader',
          use: [
            'css-loader',
            {
              loader: 'postcss-loader',
              options: {
                sourceMap: true
              }
            },
            'stylus-loader'
          ]
        })
      }
    ]
  },
  plugins: [
    new ExtractPlugin('styles.[contentHash:8].css'),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
      'process.env.VUE_ENV': '"server"'
    }),
    new VueServerPlugin()
  ]
})

module.exports = config

複製程式碼

剛接觸SSR的童鞋,看完以上程式碼是不是感覺有點暈?彆著急,我來帶大家一一分析下。

target: 'node',
複製程式碼

target需要指定為node,因為打包出來的程式是在node端執行的,不是在瀏覽器端執行,所以要指定打包的目標是node環境。

entry: path.join(__dirname, '../client/server-entry.js'),
複製程式碼

entry需要提供一個單獨的入口檔案,所以需要在client資料夾下新建一個server-entry.js檔案。

devtool: 'source-map',
複製程式碼

devtool需要指定source-map,因為vue-server-renderer有個webpack外掛,它能提供程式碼除錯的功能,不過只能提示到出錯的檔案出在哪一行。

libraryTarget: 'commonjs2',
複製程式碼

指定libraryTarget的型別為commonjs2,用來指定程式碼export出去的入口的形式。在node.js中模組是module.exports = {...},commonjs2打包出來的程式碼出口形式就類似於此。

externals: Object.keys(require('../package.json').dependencies),
複製程式碼

externals是外部因素的意思,首先我們可以開啟package.json檔案看看dependencies

入職第一天:前端leader手把手教我入門Vue伺服器端渲染(SSR)

我們用Object.keys()得到的就是一個陣列。externals就是告訴webpack不要去打包node_modules裡面的js程式碼。devDependencies裡面是一些工具型的東西,在應用真正跑起來的時候是不需要的。只有在執行一些打包,工具化操作的時候才會需要它。

'process.env.VUE_ENV': '"server"'
複製程式碼

這是vue服務端官方建議我們這麼去做的,在vue-server-renderer裡面可能會用到這個屬性。

const VueServerPlugin = require('vue-server-renderer/server-plugin')
複製程式碼

這個外掛能幫我們單獨地生成一個json檔案,用於在vue的服務端渲染裡面能幫助我們處理一些很複雜的邏輯。

最後

文章寫到這兒,Vue的服務端渲染的入門工作就算完成了(先用webpack建立一個配置檔案來打包server端的程式碼),下一篇文章將介紹如何使用koa這個node服務端框架去實現node server,最新文章都會第一時間更新在我的公眾號<閏土大叔>裡面,歡迎關注。

入職第一天:前端leader手把手教我入門Vue伺服器端渲染(SSR)

相關文章