# React、Vue 和 MDX 想用组件时就用组件，只在需要的地方用 JavaScript。

> vagejs 是一款支持 React 和 MDX 的静态网站生成器，它把 React 和 Vue 组件渲染成纯 HTML，只为可交互的“岛屿”发送 JavaScript。

vagejs 是一款静态网站生成器，你可以用 React 和 Vue 组件搭建页面、用 MDX 编写内容，它会在构建网站时把这些全部变成纯 HTML。除非你把某个 React 组件标记为可交互，否则访客不会收到任何 JavaScript；即使标记了，也只在用到它的页面上才有。

`npm create vagejs@latest my-site`

[阅读组件文档](https://vagejs.com/docs/components/)[添加一个可交互组件](https://vagejs.com/guides/interactive-react-component-static-site/)

## 用组件能做什么

组件是搭建网站的好办法：价格卡片写一次，就能在十个页面上使用。通常的代价是每位访客都要下载 JavaScript，哪怕页面上那些部分从来不会变。我们保留了组件，去掉了这份代价。

-   ### 用 React 或 Vue 组件写布局
    
    写一个 `src/layouts/default.tsx` 或 `default.vue`。React 布局拿到的数据和 TypeScript 布局一样：页面、网站、页面列表和你的菜单。访客拿到的是纯 HTML，没有 JavaScript。
    
-   ### MDX 页面
    
    MDX 是可以使用 React 组件的 Markdown。写一个 `src/pages/pricing.mdx`，就能从 `src/components/` 导入任意组件。它同样会变成纯 HTML，没有 JavaScript。
    
-   ### 可交互的 React“岛屿”
    
    给 React 组件加上 `client:load`、`client:visible` 或 `client:idle`，它就会在浏览器里运行。JavaScript 只会发送到用到它的页面。
    

## 只在你需要的地方放“岛屿”

“岛屿”就是一个原本静态的页面上的一个可交互部分。它会先渲染成 HTML，所以访客能立刻看到组件，而且在 JavaScript 加载期间页面也能正常使用。

```
import Calculator from "../components/Calculator.tsx";

<Calculator client:load rate={4.5} />
```

| 指令 | 何时启动 |
| --- | --- |
| `client:load` | 页面一加载就启动 |
| `client:visible` | 滚动进入视野时启动 |
| `client:idle` | 浏览器空闲时启动 |

用 `client:visible` 时，从没滚动到那里的访客永远不会下载这个组件。

## MDX 和 Markdown 一样会被检查

MDX 页面和组件布局与 Markdown 页面享受同样的待遇：标题、描述、网站地图条目、结构化数据，以及 `vage check` 对失效链接、隐藏链接和指向未经你批准网站的链接的检查。

```
---
title: Pricing
description: Plans and prices.
---
import PlanCard from "../components/PlanCard.tsx";

# Pricing

<PlanCard name="Team" price="$20 a month" />
```

有一点不同：MDX 页面和布局一样，是代码。它在构建网站时运行，所以 vagejs 无法像清理 Markdown 页面里的 HTML 那样清理它。只把你放心写进布局的内容放进 MDX。

## vagejs 中的 React、Vue 和 MDX 适合谁用

-   ### 已经习惯用 React 思考的团队
    
    沿用你已有的组件和习惯，不必把内容网站做成一个应用。
    
-   ### 只需要一两个可交互部分的网站
    
    比如价格计算器、筛选器或一个简短的小测验，放在其余部分都是静态内容的网站上。
    
-   ### 从组件框架迁移过来的任何人
    
    继续把布局写成组件，同时顺便获得内置的检查和 SEO 文件。
    

## 代价是什么

不使用组件的网站不需要额外安装任何东西。需要时再添加 React、Vue 或 MDX；如果缺了某一个，构建会告诉你安装它的确切命令。

“岛屿”确实需要 JavaScript。`vage audit` 会统计每个页面上的 JavaScript，包括 React 本身（大约 215 KB），这已经超过了默认的 100 KB 预算。所以添加一个“岛屿”是你主动做出的决定，而不是无意之举。很多事情用纯 HTML 也能做到：`<details>` 元素可以展开和收起，表单不用任何脚本也能提交。

terminal

```
npm install react react-dom                  # React layouts
npm install --save-dev @mdx-js/mdx           # plus React, for MDX pages
npm install vue && npm install --save-dev @vitejs/plugin-vue   # Vue layouts
```

## 目前的限制

下面这些暂时还不支持，方便你提前做好规划。

-   可交互组件只支持 React。Vue 组件可以在布局里使用，以 HTML 形式呈现。
-   可交互组件只接收简单数据（文本、数字、列表），而且不能包含其他可交互组件。
-   组件内部导入的 CSS 不会被收集。把样式放在 `public/` 里，再从布局中引用。

如果你需要用 Vue 或 Svelte 写“岛屿”，或者网站大部分都是交互内容，可以看看 [vagejs 与其他工具的对比](https://vagejs.com/compare/)。

## 进一步了解 vagejs 中的 React、Vue 和 MDX

React 支持从 0.10 版本起用于布局和 MDX 页面，从 0.11 版本起用于可交互组件。

-   一步步来：[给静态网站添加可交互的 React 组件](https://vagejs.com/guides/interactive-react-component-static-site/)
-   所有选项和规则：[文档中的 React、Vue 和 MDX](https://vagejs.com/docs/components/)
-   其他功能：[vagejs 全部功能](https://vagejs.com/zh-CN/features/)

## 关于 React、Vue 和 MDX 的常见问题

### 使用 vagejs 必须安装 React 吗？

不必。不使用组件的网站根本不需要 React、Vue 或 MDX。开始用哪一个，再安装哪一个。如果某个页面或布局需要的包缺失了，构建会停下来，并打印出确切的安装命令。

### 为什么我组件里的 useState 或 onClick 不起作用？

只有标记了 `client:load`、`client:visible` 或 `client:idle` 的组件才会在浏览器里运行。其他组件只在构建网站时变成一次 HTML，所以状态、副作用和点击处理在那里都不起作用。如果组件需要这些，就把它标记为可交互。

### 怎样给组件加样式？

把 CSS 放在 `public/` 里，再从布局中引用。组件内部的 CSS，比如 Vue 的 `<style>` 块或 `import "./card.css"`，不会被加到网站里。

### 能在浏览器编辑器里编辑 MDX 页面吗？

暂时不能。`npm run dev` 打开的编辑器只列出 `.md` 页面，所以 `.mdx` 页面请在代码编辑器里编辑。
