2.React服務端渲染基礎配置

服務端渲染

服務端渲染(SSR)主要是爲了SEO,加快首屏的加載速度等做用。利用react-dom/server提供的工具,咱們很容易進行服務端渲染。html

基本原理

服務端渲染的基本原理就是讀取咱們的模板文件,而後將其中的內容替換成咱們本身的代碼,而後生成一個完整的html文件返回給前端頁面。前端

webpack配置

第一篇文章中,已經進行了基礎的配置,本文是在前面的基礎上來配置的。本次配置須要安裝如下兩個依賴node

  1. express, 涉及到服務端代碼,用到express包
  2. rimraf, 看着名字就知道是刪庫跑路的包。每次咱們運行build命令時,都會生成新的文件。咱們能夠用這個包先刪除dist目錄,而後在從新生成新的dist目錄。

首先在client目錄下新增template.html和server-entry.js兩個文件。前面的html時模板文件,後面的js做爲服務端的入口文件。react

// template文件很簡單,只有一個id爲app的div,後面咱們將會把<!-- <app /> -->替換爲咱們本身的內容。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"><!-- <app /> --></div>
</body>
</html>
// 入口文件目前也很簡單,只是導入App組件
import React from 'react'
import App from './App.jsx'

export default <App />

在build目錄下新增webpack.config.server.js文件,做爲服務端打包的配置文件。同時爲了區分客戶端,將客戶端的配置文件改成webpack.config.client.js。服務端與客戶端的配置基本同樣,主要時入口文件和出口文件的配置不一樣。webpack

entry: {
    app: resolvePath('../client/server-entry.js')  // 服務端入口文件
  },
  output: {
    filename: 'server-entry.js',  // 輸出文件名
    path: resolvePath('../dist'), // 輸出路勁
    publicPath: '', // 
    libraryTarget: 'commonjs2' // 模塊化的方式
  },

在項目目錄下新建server文件夾,新建一個server.js文件,該文件主要爲服務端邏輯。git

const express = require('express')
const ReactSSR = require('react-dom/server')
const fs = require('fs')
const path = require('path')
const serverEntry = require('../dist/server-entry').default  // 打包好的服務端文件

const app =express()

const template = fs.readFileSync(path.join(__dirname, '../dist/index.html'), 'utf-8')  // 讀取模板文件

app.get('*', function(req, res) {
  const appString = ReactSSR.renderToString(serverEntry)  
  res.send(template.replace('<!-- <app /> -->', appString)) // 將模板文件中的註釋替換爲咱們本身的內容,而後返回到客戶端
})

app.listen(3333, function() {
  console.log('server is listen on 3333')
})

服務端渲染的基本邏輯就已經完成。接下來咱們在package.json文件中新增一些命令。github

"scripts": {
    "build:client": "webpack --config build/webpack.config.client.js", // 編譯客戶端代碼
    "build:server": "webpack --config build/webpack.config.server.js",
    // 編譯服務端代碼
    "clear": "rimraf dist", // 每次build前,先自動刪除dist目錄
    "build": "npm run clear && npm run build:client && npm run build:server",// build客戶端和服務端的代碼
    "start": "node server/server.js" // 啓動服務器
  },

先運行build命令,而後運行start命令,訪問localhost:3333,就能夠看到內容了。並且在network窗口中能夠看到返回的時完整的html頁面,而不是一個空頁面。web

但時目前請求js文件,返回的也是html文件。由於在server.js中,任意的請求都是返回html文件。能夠經過express來配置靜態文件目錄。express

// 以/public開頭的請求都會去dist目錄中找。
app.use('/public', express.static(path.join(__dirname, '../dist')))

同時須要修改客戶端和服務端的webpack配置。npm

// 會在路徑前加上/public前綴
  output: {
    publicPath: '/public',
  },

從新運行build和start命令,訪問3333端口,就會返現請求都是正常的。從返回的html文件中,script標籤的src屬性中的路徑會帶有/public前綴,這就是publicPath屬性的做用。

至此,服務端渲染的基礎配置就已經完成。本次的代碼位於倉庫的2-5分支。

在使用rimraf時,window可能會遇到一些權限相關的問題,可能的解決方法點這裏

相關文章
相關標籤/搜索