繼前段時間西安電面之後順利拿到了OFFER,今天(5月2號)是我入職第一天,在簡短的內部培訓了一上午後,前端leader讓我先了解下什麼是vue的伺服器端渲染(SSR)。
SSR,英文全稱叫 Server side rendering ,國人叫它伺服器端渲染。
首先聽到這個名詞,我頭腦就有點眩暈。我們們還是先去官網瞭解下SSR的定義:
Vue.js 可以將同一個元件渲染為伺服器端的 HTML 字串,將它們直接傳送到瀏覽器,最後將靜態標記"混合"為客戶端上完全互動的應用程式。這種在伺服器和客戶端都可以執行的程式碼程式,也可以叫做“同構”。
我弱弱地問了leader一句,我們們公司為什麼要使用服務端渲染?
leader冷冷地回覆,有兩點原因,第一點,因為我們公司的站點很注重SEO,頁面又是非同步獲取內容;第二點,同時也希望使用者更快速地看到完整渲染的頁面,從而提高使用者體驗。基於這兩點,所以需要伺服器端渲染(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
我們用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,最新文章都會第一時間更新在我的公眾號<閏土大叔>裡面,歡迎關注。