實(shí)現(xiàn)時(shí)間為2020年7月
這部分網(wǎng)上資料較少,而且用戶庫(kù)比較舊,沒(méi)有特別好的解決方案,決定從頭開(kāi)始自己實(shí)現(xiàn)一套方案,express做服務(wù)端,前端為主流的 react + react router + redux;
首先用npx create-react-app app創(chuàng)建基本站點(diǎn),不加入router和redux;
package.json里面的script加入:
"server": "nodemon --exec babel-node server/index.js",
用于啟動(dòng)服務(wù)器,同時(shí)配置babel,創(chuàng)建.babelrc代碼:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
[
"@babel/preset-react"
]
],
"plugins": [
"@babel/plugin-proposal-class-properties"
],
"ignore":[
"./src/public/"
]
}
babel-node是babel新版本提供的一個(gè)命令,用于node代碼編譯支持,這樣通過(guò)import導(dǎo)入代碼就不會(huì)出錯(cuò),很多老的文章教程沒(méi)有提到這個(gè)。
代碼目錄為:
主要實(shí)現(xiàn)server/index.js的內(nèi)容
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 }`);
});
另外還有一個(gè)renderReact.js,為什么要分成兩個(gè),因?yàn)?code>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解析出來(lái)的dom代碼。
<div id="root">#body</div>
源碼地址:https://github.com/liuxiaocong/react-ssr-2020
但是目前的操作只支持到j(luò)s層面,其他資源類像css,image的都不支持,只能算閹割版的SSR,最近花了幾天時(shí)間,終于實(shí)現(xiàn)了一個(gè)完整版的,可以看下這里的記錄:http://www.lxweimin.com/p/40654743a387