服务端渲染(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可能会遇到一些权限相关的问题,可能的解决方法点这里