webpack+babel工具,如何编译ReactSSR的服务器端代码?
发布于 作者:苏南大叔 来源:程序如此灵动~本文的主角依然是react ssr
系列文章中的server.jsx
,它启动了个express
进程,然后给react
项目进行脱水处理。并且使用renderToPipeableStream()
输出到浏览器端,然后利用另外打包的内置hydrateRoot()
的.js
文件,来完成注水的过程。那么,问题来了:这个基于express
的程序,如何使用原生的node
,而不是esno
来启动呢?这就是本文要讨论的问题。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验。本文测试环境:nodejs@20.18.0
,create-react-app@5.0.1
,react-router-dom@6.27.0
,react@18.3.1
,express@4.21.1
,webpack-cli@5.1.4
。
前文回顾
在前面的文章里面,都是使用esno
执行server.jsx
文件的。参考文章:
本文的思路中,需求是把通过esno
执行的文件,改成直接node
执行。其实和下面这篇文章的思路,基本一致。目前的思路依旧是webpack
打包,babel
编译。
但是,由于要转换的程序是运行在服务器端的node
,而不是运行在浏览器端的普通.js
代码,因此在编译转换的时候,还是有些许区别的。主要体现在webpack.config.server.js
文件上。
webpack配置文件
基于create-react-app
的cra
模版,新建一个webpack
的配置文件。内容如下:
webpack.config.server.js
:
const path = require("path");
// const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: "./server.jsx",
output: {
filename: "server.prod.js",
path: path.resolve("./"),
},
target: "node",
// devtool: 'source-map',
externals: [
// nodeExternals(),
],
resolve: {
extensions: [".js", ".jsx", ".ts", ".tsx", ".json"],
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"react-app",
"@babel/preset-env",
],
},
},
},
],
},
};
安装编译
可能需要新安装webpack-cli
和@babel/plugin-proposal-private-property-in-object
,安装方式:
npm i webpack-cli --save-dev
npm i @babel/plugin-proposal-private-property-in-object --save-dev
配置新的package.json
里面的命令:
//...
"scripts": {
"build2": "cross-env NODE_ENV=production webpack --mode production --config webpack.config.server.js"
},
//...
执行命令,获得server.prod.js
文件。
npm run build2
cross-env
命令,参考文章:
执行文件
这个文件可单独放置于任何其它的node
环境下,通过node
的方式执行。
node server.prod.js
也可以配合nodemon
伺服器执行。
nodemon --exec node server.prod.js
配置关键点
这个配置中,代码不长。但是,这里有两个关键点。
关键点之target
能编译成功,关键配置就是target
设置为node
。webpack
默认的target
是浏览器端的.js
文件构建,并不是为express
这种运行在服务器端的.js
文件,而准备的。
webpack
的target
参数,参考官方的文档说明:
在本文中,需要对express
相关代码进行编译合并。如果不设置target
为node
,就可能会得到大量一系列的错误提示信息。可以参考下面的文章:
- https://newsn.net/say/webpack-react-render.html
- https://newsn.net/say/webpack-express-expression.html
- https://newsn.net/say/webpack-property-in-object.html
- https://newsn.net/say/webpack-express-fallback.html
关键点之jsx
server.jsx
文件,在使用webpack
进行编译的时候,文件改名为server.js
,也是完全没有问题的。这主要归功于webpack.config.js
文件中,babel
对于.jsx?$
文件的处理。
module.exports = {
//...
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"react-app",
"@babel/preset-env",
],
},
},
},
],
},
};
以正则角度来说的话,它指的就是.js
和.jsx
两种文件。
配置优化点
下面属于配置优化点,非必须的修改。
优化之babel
从优化角度来说,.babelrc
文件也可以移动到webpack.config.js
文件中,这样更加明确一些。
options: {
presets: [
"react-app",
"@babel/preset-env",
],
},
优化之mode
mode
也可以移动到package.json
里面的scripts
命令里面。也可以和@babel/core
所强加的NODE_ENV
都放在一起,看起来更加明了。
webpack --mode production
对待第三方库
在上面的配置中,express
/react
/react-dom
/react-router
等等都统一打包到server.prod.js
里面了。苏南大叔比较喜欢这种文件打包结果。
但是,正常来说,express
/react-dom
/react-router
等,不应该被打包到可执行文件里面去。可以通过npm i
再次安装。如果需求是这样的话,可以配置webpack.config.js
里面的externals
选项。
module.exports = {
externals: [
"express","react","react-dom","react-router"
],
}
还可以安装一个插件webpack-node-externals
,直接大一统的进行设置。
//...
const nodeExternals = require('webpack-node-externals');
module.exports = {
//...
externals: [
nodeExternals(),
],
}
结束语
本文的目的是,构建获得直接通过node
执行的server.js
。苏南大叔的react
相关经验文章,可以参考下面的链接:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。