服務端渲染(SSR)主要是爲了SEO,加快首屏的加載速度等做用。利用react-dom/server提供的工具,咱們很容易進行服務端渲染。html
服務端渲染的基本原理就是讀取咱們的模板文件,而後將其中的內容替換成咱們本身的代碼,而後生成一個完整的html文件返回給前端頁面。前端
在第一篇文章中,已經進行了基礎的配置,本文是在前面的基礎上來配置的。本次配置須要安裝如下兩個依賴node
首先在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可能會遇到一些權限相關的問題,可能的解決方法點這裏