
本文详解如何在纯 html 环境中零配置接入 react 18,解决 `createroot` 使用错误、babel 加载时机不当及脚本执行顺序问题,并提供可直接运行的完整示例。
在现有静态 HTML 中集成 React 18 与旧版(如 React 17)有本质区别:React 18 引入了并发渲染(Concurrent Rendering),废弃了 ReactDOM.render(),必须使用 ReactDOM.createRoot() 并配合 可挂载的 DOM 容器节点 才能正确启动应用。常见失败原因包括:
- createRoot 调用过早(DOM 节点尚未存在);
- Babel 没有在 <script type="text/babel"> 中启用 JSX 编译;
- react-dom 全局变量未正确暴露(CDN 版本下需通过 ReactDOM 访问,而非解构导入);
- 混淆模块语法(如 import { createRoot } from 'react-dom/client' 在浏览器端不可用,因无原生 ESM 支持且缺少打包器)。
✅ 正确做法是:全部使用 CDN + UMD 全局变量 + type="text/babel" 脚本标签,确保执行时环境就绪。
✅ 完整可运行 HTML 示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>React 18 + HTML 集成</title>
<!-- Bootstrap CSS(可选) -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
>
<!-- React 18 UMD 开发版(含严格模式警告) -->
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<!-- ReactDOM 18 UMD 开发版 -->
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel Standalone:实时编译 JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div class="container mt-4">
<h1>Hi, React 18 is here! ✅</h1>
<div id="app"></div> <!-- 渲染容器:必须提前声明 -->
</div>
<!-- 关键:type="text/babel" 启用 JSX 编译,且置于 DOM 节点之后 -->
<script type="text/babel">
// 数据源
const myArr = [
{ Heading: "第一项标题", Body: "这里是第一段内容" },
{ Heading: "第二项标题", Body: "这里是第二段内容" },
{ Heading: "第三项标题", Body: "这里是第三段内容" }
];
// 可复用组件
const Reuse = ({ Heading, Body }) => (
<div className="card mb-3">
<div className="card-header fw-bold">{Heading}</div>
<div className="card-body">{Body}</div>
</div>
);
// 根组件
const MyDisplay = () => {
return (
<div>
{myArr.map((item, index) => (
<Reuse key={index} {...item} />
))}
</div>
);
};
// ✅ 正确挂载:先获取容器,再 createRoot,最后 render
const container = document.getElementById('app');
const root = ReactDOM.createRoot(container);
root.render(<MyDisplay />);
</script>
</body>
</html>⚠️ 关键注意事项
- <script type="text/babel"> 必须放在 <div id="app"> 之后:确保 DOM 节点已存在,否则 getElementById 返回 null;
- 不要使用 import 语法:CDN 提供的是 UMD 全局变量(React, ReactDOM),解构导入(如 import { createRoot })仅适用于 ES 模块环境(需 Vite/Webpack);
- key 属性不可省略:在 map 渲染列表时,务必为每个元素添加唯一 key(推荐使用 index 仅限原型开发;真实项目请用稳定 ID);
-
生产环境替换为生产版 CDN:
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
(移除开发警告,体积更小,性能更优)
✅ 总结
React 18 的 createRoot 是强制升级路径,但在 HTML 原生环境中无需构建工具也能轻松落地——核心就是三步:
1️⃣ 引入 react、react-dom、@babel/standalone 三个 CDN;
2️⃣ 将 JSX 代码包裹在 <script type="text/babel"> 中并置于目标 DOM 节点之后;
3️⃣ 使用 ReactDOM.createRoot(container).render(<App />) 启动应用。
此方式适合快速原型、文档嵌入、CMS 页面增强等轻量场景,兼顾现代 React 特性与极简集成成本。
立即学习“前端免费学习笔记(深入)”;











