上一篇文章总结了webpack基础配置,这篇文章开始总结服务端渲染配置。
服务端渲染配置
1.在client目录里新建服务端入口文件server-entry.js
cd cliennt
touch server-entry.js
2.在server-entry.js里面写的是导出前端代码
import React from 'react';
import App from './App.jsx';
export default <App />
3.因为打包时不能打包服务端文件,需要新建webpack.config.server.js来配置
- target:node 代表运行在node环境中。
- libraryTarget: 'commonjs2' 代表遵循common.js规范
const path = require('path');
module.exports = {
target:'node',
entry: {
app: path.join(__dirname,'../client/server-entry.js')
},
output: {
filename: 'server-entry.js',
path: path.join(__dirname,'../dist'),
publicPath: '',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /.jsx$/,
loader: 'babel-loader'
},
{
test: /.js$/,
loader: 'babel-loader',
exclude: [
path.join(__dirname,'../node_modules')
]
}
]
}
}
4.在package.json中添加build:server为打包服务端文件。build打包前后端文件。
"build:server": "webpack --config build/webpack.config.server.js",
"build": "build:client && build:server"
5.从上面打包看,每次打包的文件都没有覆盖。为了覆盖之前打包的文件,安装rimraf。同时在在package.json中配置。
npm i rimraf -D
...省略
"clear": "rimraf dist",
"build": "npm run clear && npm run build:client && npm run build:server"
6.以上服务端配置就ok了。可以开始写服务端express代码了。创建server目录,在server目录下创建server.js
mkdir server
cd server
touch server.js
7.安装express
npm i express -S
8.在server.js中写express代码
const express = require('express')
const ReactSSR = require('react-dom/server')
const serverEntry = require('../dist/server-entry').default
const app = express()
app.get('*',(req,res)=>{
const data = ReactSSR.renderToString(serverEntry)
res.send(data)
})
app.listen('3333',()=>{
console.log('server is listening on 3333')
})
9.运行npm run build 和 npm start ,在127.0.0.1:3333上就能看到显示在页面上的内容了。但是这只是在js中输出的,并没有放到html的body里面。下面操作来将内容放到body。
- 1.在client目录下创建template.html
<!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="root">
<app></app>
</div>
</body>
</html>
- 2.修改client目录下app.js。将document.body改为document.getElementById('root')。这样是将html渲染到id为root的div下面。
- 3.将template.html整体渲染,在webpack.config.client.js指定到template.html
plugins:[
new HTMlPlugin({
template:path.join(__dirname,'../client/template.html')
})
]
- 4.在server/server.js里面读取打包后的dist/index.html。用fs模块去读index.html,把读取的内容send出去。
const express = require('express')
const ReactSSR = require('react-dom/server')
const serverEntry = require('../dist/server-entry').default
const fs = require('fs')
const path = require('path')
//新增
const template = fs.readFileSync(path.join(__dirname,'../dist/index.html'),'utf8')
//新增,为了不让打包后的js文件返回html内容。
需要同时将webpack.config.client.js和
webpack.config.server.js里面的publicPath设置为public
const app = express()
app.use('/public',express.static(path.join(__dirname,'../dist')))
app.get('*',(req,res)=>{
const data = ReactSSR.renderToString(serverEntry)
//新增
res.send(template.replace('<app></app>',data))
})
app.listen('3333',()=>{
console.log('server is listening on 3333')
})
以上就配置好服务端渲染了。但是有个问题,每次修改都需要npm run build打包一下,npm start重启下服务。这样在实际工作中很浪费时间。下一篇文章中,我们会解决这个问题。