# React + Babel 项目规范
用HTML+React+Babel做原型时必须遵守的技术规范。不遵守会炸。
## Pinned Script Tags(必须用这些版本)
在HTML的`
`里放这三个script tag,用**固定版本+integrity hash**:
```html
```
**不要**用`react@18`或`react@latest`这种unpinned版本——会出现版本漂移/缓存问题。
**不要**省略`integrity`——CDN一旦被劫持或篡改,这是防线。
## 文件结构
```
项目名/
├── index.html # 主HTML
├── components.jsx # 组件文件(type="text/babel"加载)
├── data.js # 数据文件
└── styles.css # 额外CSS(可选)
```
HTML里加载方式:
```html
```
**不要**用`type="module"`——会和Babel冲突。
## 三条不可违反的规矩
### 规矩1:styles 对象必须用唯一命名
**错误**(多组件时必炸):
```jsx
// components.jsx
const styles = { button: {...}, card: {...} };
// pages.jsx ← 同名覆盖!
const styles = { container: {...}, header: {...} };
```
**正确**:每个组件文件的styles用唯一前缀。
```jsx
// terminal.jsx
const terminalStyles = {
screen: {...},
line: {...}
};
// sidebar.jsx
const sidebarStyles = {
container: {...},
item: {...}
};
```
**或者用inline styles**(小组件推荐):
```jsx
...
```
这条是**非协商**的。每次写`const styles = {...}`都必须replace成specific命名,否则多组件加载时全栈报错。
### 规矩2:Scope 不共享,需手动export
**关键认知**:每个`
```
**注意**:浏览器直接调Anthropic API会遇到CORS问题。如果用户给你的预览环境不支持CORS bypass,这条路不通。这时候用选项A mock,或者告诉用户需要一个proxy后端。
### 选项 C:用 agent 侧的 LLM 能力生成 mock 数据
如果只是本地演示用,可以在当前 agent 会话里临时调用该 agent 的 LLM 能力(或用户装的 multi-model 类 skill)先生成 mock 响应数据,再硬编码写进 HTML。这样 HTML 运行时完全不依赖任何 API。
## 典型 HTML 起手模板
拷贝这个模板作为React原型的骨架:
```html
Your Prototype Name
```
## 常见报错及解决
**`styles is not defined` 或 `Cannot read property 'button' of undefined`**
→ 你在一个文件里定义了`const styles`,另一个文件覆盖了。给每个改成specific命名。
**`Terminal is not defined`**
→ 跨文件引用时scope不通。在定义Terminal的文件末尾加`Object.assign(window, {Terminal})`。
**整个页面白屏,控制台没错误**
→ 多半是JSX语法错误但Babel没报在控制台。把`babel.min.js`临时换成`babel.js`非压缩版,错误信息更清晰。
**ReactDOM.createRoot is not a function**
→ 版本不对。确认用了react-dom@18.3.1(而不是17或其他)。
**`Objects are not valid as a React child`**
→ 你渲染了一个对象而不是JSX/字符串。通常是`{someObj}`写成了`{someObj.name}`。
## 大项目怎么拆文件
**>1000行的单文件**难维护。分拆思路:
```
项目/
├── index.html
├── src/
│ ├── primitives.jsx # 基础元素:Button、Card、Badge...
│ ├── components.jsx # 业务组件:UserCard、PostList...
│ ├── pages/
│ │ ├── home.jsx # 首页
│ │ ├── detail.jsx # 详情页
│ │ └── settings.jsx # 设置页
│ ├── router.jsx # 简单路由(React state切换)
│ └── app.jsx # 入口组件
└── data.js # mock data
```
HTML里按顺序加载:
```html
```
**每个文件末尾**都要`Object.assign(window, {...})`导出要共享的东西。