1. 服务端渲染的好处
SEO和首屏时间
2. 热替换
react-hot-reload(react-hot-reload不用刷新浏览器), (webpack-dev-server还是需要刷新浏览器)
3. 速成的代码
1). 分成client端, 借用webpack打包到dist下面。 将用于生成string的html加入替换的标记<!--app-->
2). 服务端node, 借助webpack(target:node), 生成压缩版的组件,读取导出的客户端组件; 然后读取index.html, 替换<!--app-->
3).。 调用renderToString(App), 返回string.
server.js
const express = require("express"); const path = require("path"); const React = require("react"); const { renderToString } = require("react-dom/server"); const { readFile: rf } = require("fs"); const { promisify } = require("util"); // const App = require("../client/app").default; const App = require('../../dist/serverapp.js').default const app = express(); const readFile = promisify(rf); app.use(express.json()); app.use(express.urlencoded({ extended: false })); const text = renderToString(App); console.log(text); app.get("/",async (req,res) => { const content = renderToString(App); // 读取打包出来的 HTML 文件 const str = await readFile(path.join(__dirname, "../../dist/index.html")); // 把内容替换掉 const html = str.toString().replace("<!--app-->",content); // 将页面发到前端 res.send(html); }); // 打包生成的文件夹作为静态服务路径,这样静态文件就可以请求到了 app.use("/test",express.static(path.join(__dirname, "../../dist"))); app.listen(8001,() => { console.log("Server is running: http://localhost:8001"); });
server->webpack.js
1 const path = require("path"); 2 3 module.exports = { 4 target:"node", 5 entry: path.join(__dirname, "./src/client/server-app.js"), 6 output: { 7 path: path.join(__dirname, "./dist"), 8 filename: "serverapp.js", 9 libraryTarget: "commonjs2" 10 }, 11 mode: "development", //production慢 12 module: { 13 rules: [ 14 { 15 test: /.jsx?$/, 16 exclude: /node_modules/, 17 use: { 18 loader: "babel-loader", 19 }, 20 }, 21 ], 22 }, 23 resolve: { 24 extensions: [".js", ".jsx", ".mjs"], 25 }, 26 plugins: [] 27 };
client: webpackl
const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); module.exports = { entry: path.join(__dirname, "./src/client/index.js"), output: { path: path.join(__dirname, "./dist"), filename: "bundle.js", }, mode: "development", //production慢 module: { rules: [ { test: /.jsx?$/, exclude: /node_modules/, use: { loader: "babel-loader", }, }, ], }, resolve: { extensions: [".js", ".jsx", ".mjs"], }, plugins: [ new HtmlWebpackPlugin({ template: path.join(__dirname, "./src/client/index.html"), }), new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: ["./dist"], dry: false, dangerouslyAllowCleanPatternsOutsideProject: true, }), ], devServer: { hot:true, host: 'localhost', compress: true, port: 8080 } };