天天看點

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

繼前段時間西安電面之後順利拿到了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的服務端渲染裡面能幫助我們處理一些很複雜的邏輯。

原文釋出時間為:2018年05月05日

原文作者:

閏土大叔

本文來源: 

掘金 https://juejin.im/entry/5b3a29f95188256228041f46

如需轉載請聯系原作者

繼續閱讀