You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Express路由渲染React组件实现SSR并解决JSX报错

问题根因

报错本质是JSX未被正确转译,来自两个配置错误:

  • 原dev命令参数顺序错误,nodemon未正确将执行权交给babel-node,JSX代码直接被Node.js原生解析,Node不识别<开头的JSX标签直接抛出语法错误。
  • 开启"type": "module"ES模块模式后,命令行直接传--presets env,react的简写写法,和当前babel版本、ESM模式不兼容,转译预设根本没加载。
    另外直接返回renderToString的输出也不规范,这只是组件的HTML片段,没有完整文档结构,浏览器拿到后会触发怪异模式渲染。
最简实现方案

全程不需要引入额外路由框架,所有路由完全由Express管控,页面路由、API路由可自由定义,不会出现路由逻辑碎片化问题。

1. 修正Babel配置

在项目根目录新建babel.config.json,替代命令行传presets的不稳定写法:

{
  "presets": [
    "@babel/preset-env",
    ["@babel/preset-react", { "runtime": "automatic" }]
  ]
}

配置runtime: "automatic"后,组件文件不需要手动写import React from 'react',可以简化代码。

2. 修正package.json启动脚本

把dev命令改成正确的参数格式,--是nodemon传递后续执行参数的分隔符:

{
    "name": "project",
    "version": "1.0.0",
    "main": "index.js",
    "type": "module",
    "scripts": {
        "dev": "nodemon --exec babel-node index.js"
    },
    "license": "MIT",
    "dependencies": {
        "@babel/node": "^7.18.6",
        "@babel/preset-env": "^7.18.6",
        "@babel/preset-react": "^7.18.6",
        "express": "^4.18.1",
        "nodemon": "^2.0.19",
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

3. 改造服务入口逻辑

修改index.js,把组件渲染结果包裹在完整HTML文档中返回,API路由和页面路由平级编写即可,完全由Express统一调度。注意ESM模式下导入本地文件必须写全后缀:

import express from "express";
import ReactDOMServer from "react-dom/server";
import Home from "./Home.js";

const app = express();
const port = 3000;

// 页面路由
app.get("/", (req, res) => {
  const pageContent = ReactDOMServer.renderToString(<Home />);
  res.send(`
    <!DOCTYPE html>
    <html lang="zh-CN">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>首页</title>
      </head>
      <body>
        <div id="root">${pageContent}</div>
      </body>
    </html>
  `);
});

// 后续API路由直接按Express常规写法添加即可,和页面路由互不干扰
// 示例API
app.get("/api/info", (req, res) => {
  res.json({ code: 0, data: "hello api" });
});

app.listen(port, () => {
  console.log(`服务运行在 http://localhost:${port}`);
});

4. 组件文件无需额外修改

Home.js保留原有代码即可正常运行:

export default function Home() {
  return (
    <div>
      <h1>home</h1>
      <p>hello world</p>
    </div>
  );
}
补充说明
  • 该配置为开发环境最简实现,执行npm run dev即可正常访问,JSX修改后nodemon会自动重启服务。
  • 如果后续需要给页面加客户端交互(比如绑定事件、响应组件状态),再额外补充客户端hydrate逻辑即可,当前配置已经可以实现纯展示类页面的SSR渲染。
  • 生产环境建议把服务端代码用babel提前编译成普通JS再启动,不要用babel-node跑生产服务,性能表现更好。

内容的提问来源于stack exchange,提问作者jaxramus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:18:41