【笔记】React项目实现SSR

前言

React项目实现SSR

下载依赖

1
2
npm install express react react-dom
npm install -D webpack webpack-cli webpack-node-externals webpack-merge babel-loader @babel/preset-react @babel/preset-env

定义根组件

src/App.jsx
1
2
3
4
5
6
7
8
9
const React = require("react");

const App = function () {
return (
<div></div>
);
};

export default App;

服务端渲染

定义服务器

src/server/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const express = require("express");
const path = require("path");
const React = require("react");
const ReactDOM = require("react-dom/server");
const App = require("../App.jsx");

const server = express();
server.use(express.static(path.resolve(__dirname, "../client")));
server.get("/*", function (request, response) {
const appHTML = ReactDOM.renderToString(<App />);
response.send(`
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">${appHTML}</div>
<script src="/client/bundle.js"></script>
</body>
</html>
`);
});
server.listen(3000);

定义Webpack配置

config/server/webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const path = require("path");
const nodeExternals = require("webpack-node-externals");

module.exports = {
target: "node",
mode: "development",
entry: "./src/server/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "../../build/server"),
libraryTarget: "commonjs2"
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: "babel-loader",
options: {
presets: ["@babel/preset-react", "@babel/preset-env"]
}
}
]
},
externals: [nodeExternals()]
}

通过Webpack打包服务器

1
webpack --config config/server/webpack.config.js

客户端渲染

定义客户端

src/client/index.js
1
2
3
4
5
const React = require("react");
const ReactDOM = require("react-dom/client");
const App = require("../App.jsx");

ReactDOM.hydrateRoot(document.getElementById("app"), <App />);

定义Webpack配置

config/client/webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const path = require("path");

module.exports = {
target: "web",
mode: "development",
entry: "./src/client/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "../../build/client")
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: "babel-loader",
options: {
presets: ["@babel/preset-react", "@babel/preset-env"]
}
}
]
}
}

通过Webpack打包客户端

1
webpack --config config/client/webpack.config.js

启动SSR服务器

  • 先通过Webpack依次打包客户端和服务器,再启动打包好的服务器程序
1
2
3
4
webpack --config config/client/webpack.config.js
webpack --config config/server/webpack.config.js

node build/server/bundle.js

完成