React ssr 服务器渲染
2020-07-04 本文已影响0人
不懂量化的吃货不是好前端
实现时间为2020年7月
这部分网上资料较少,而且用户库比较旧,没有特别好的解决方案,决定从头开始自己实现一套方案,express做服务端,前端为主流的 react + react router + redux;
首先用npx create-react-app app创建基本站点,不加入router和redux;
package.json里面的script加入:
"server": "nodemon --exec babel-node server/index.js",
用于启动服务器,同时配置babel,创建.babelrc代码:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
[
"@babel/preset-react"
]
],
"plugins": [
"@babel/plugin-proposal-class-properties"
],
"ignore":[
"./src/public/"
]
}
babel-node是babel新版本提供的一个命令,用于node代码编译支持,这样通过import导入代码就不会出错,很多老的文章教程没有提到这个。
代码目录为:

主要实现server/index.js的内容
import express from 'express';
import compression from 'compression';
import { renderToString } from "react-dom/server";
require('@babel/register')();
require('@babel/polyfill')
require.extensions['.less'] = () => {
return;
};
require.extensions['.css'] = () => {
return;
};
const renderReact = require('./renderReact.js');
const router = express.Router();
import path from 'path';
const app = express();
app.use(compression());
renderReact(app);
app.use(express.static(path.resolve(__dirname, '../build/')))
const port = process.env.PORT || 4000;
app.listen(port, function listenHandler() {
console.info(`Running on ${ port }`);
});
另外还有一个renderReact.js,为什么要分成两个,因为babel-register
doesn't process the file it is called from, see https://stackoverflow.com/a/29425761/1795821
renderReact.js:
import React from 'react';
import fs from 'fs';
const reactDomServer = require('react-dom/server');
import App from "../src/App";
const renderPage = function(reactHtml){
return reactHtml;
}
let buildHtml;
module.exports = function(app) {
app.get('/', (req, res) => {
const appHtml = reactDomServer.renderToString(<App/>);
if(!buildHtml){
buildHtml = fs.readFileSync('./build/index.html','utf8');
}
let result = buildHtml.replace('#body', appHtml);
console.log(buildHtml);
console.log(appHtml);
res.send(result)
})
}
基本大功告成,最后在public的index.html里面加上#body方便替换成renderToString解析出来的dom代码。
<div id="root">#body</div>
源码地址:https://github.com/liuxiaocong/react-ssr-2020
但是目前的操作只支持到js层面,其他资源类像css,image的都不支持,只能算阉割版的SSR,最近花了几天时间,终于实现了一个完整版的,可以看下这里的记录:https://www.jianshu.com/p/40654743a387