持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
Hi, 大家好。
上一篇文章总结了webpack基础配置,这篇文章开始总结服务端渲染配置。
0x1 在client目录里新建服务端入口文件server-entry.js
cd cliennt touch server-entry.js
0x2 在server-entry.js里面写的是导出前端代码
import React from 'react'; import App from './App.jsx'; export default <App />
0x3 因为打包时不能打包服务端文件,需要新建webpack.config.server.js来配置
1.target:node 代表运行在node环境中。
2.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') ] } ] } }
0x4 在package.json中添加build:server为打包服务端文件。build打包前后端文件
"build:server": "webpack --config build/webpack.config.server.js", "build": "build:client && build:server"
0x5 从上面打包看,每次打包的文件都没有覆盖。为了覆盖之前打包的文件,安装rimraf。同时在在package.json中配置
npm i rimraf -D
"clear": "rimraf dist",
"build": "npm run clear && npm run build:client && npm run build:server"
0x6 以上服务端配置就ok了。可以开始写服务端express代码了。创建server目录,在server目录下创建server.js
mkdir server
cd server
touch server.js
0x7 安装express
npm i express -S
0x8 在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') })
0x10 运行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重启下服务。这样在实际工作中很浪费时间。下一篇文章中,我们会解决这个问题。