> For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt.

# 静态站点生成（SSG）

SSG（Static Site Generation）是一种基于数据与模板，在构建时渲染完整静态网页的技术解决方案。这意味着在生产环境中，页面默认就是有内容的，并且可以被 CDN 缓存。对于无需数据的页面，SSG 可以提供更好的性能和更高的安全性。

## 启用 SSG

要在 Modern.js 项目中启用 SSG 功能，请按照以下步骤修改代码：

1. 安装 SSG 插件依赖

如果项目尚未安装 SSG 插件，请先安装：

```bash
pnpm add @modern-js/plugin-ssg
```

:::tip 版本一致性

请确保 `@modern-js/plugin-ssg` 的版本与项目中 `@modern-js/app-tools` 的版本保持一致。Modern.js 的所有官方包使用统一版本号发布，版本不一致可能导致兼容性问题。

请先查看 `@modern-js/app-tools` 的版本，然后安装相同版本的 `@modern-js/plugin-ssg`：

```bash
# 查看当前 @modern-js/app-tools 的版本
pnpm list @modern-js/app-tools

# 安装相同版本的 @modern-js/plugin-ssg
pnpm add @modern-js/plugin-ssg@<版本号>
```

:::

2. 配置 modern.config.ts

在 `modern.config.ts` 文件中导入并添加 SSG 插件，同时配置 `output.ssg`：

```ts title="modern.config.ts"
import { defineConfig, appTools } from '@modern-js/app-tools';
import { ssgPlugin } from '@modern-js/plugin-ssg';

export default defineConfig({
  plugins: [appTools(), ssgPlugin()],
  output: {
    ssg: true,
  },
});
```

:::info 适用范围

- 单入口请使用 `output.ssg`。
- 多入口请使用 `output.ssgByEntries`。
- 当仅设置 `output.ssg: true` 且未配置 `output.ssgByEntries` 时，所有入口下的所有路由都会作为 SSG 路由处理。

:::

## 开发环境调试

SSG 也是在 Node.js 环境渲染页面，因此我们可以在**开发阶段开启 SSR**，提前暴露代码问题，验证 SSG 渲染效果：

```ts title="modern.config.ts"
export default defineConfig({
  server: {
    ssr: process.env.NODE_ENV === 'development',
  }
}
```

## 在约定式路由中使用

**约定式路由**中，Modern.js 根据入口下的文件结构生成路由，因此框架能够收集完整的路由信息。

### 基本用法

例如，以下是一个使用约定式路由的项目目录结构：

```bash
.
└── routes
    ├── layout.tsx
    ├── page.tsx
    └── user
        ├── layout.tsx
        ├── page.tsx
        └── profile
            └── page.tsx
```

上述文件目录将会生成以下三条路由：

- `/`
- `/user`
- `/user/profile`

:::tip
如果还不了解约定式路由的规则，可以先查看[路由方案](/zh/guides/basic-features/routes/routes.md)。

:::

在 `src/routes/page.tsx` 中添加组件代码：

```jsx title="src/routes/page.tsx"
export default () => {
  return <div>Index Page</div>;
};
```

在项目根路径下执行 `pnpm run dev` 命令，查看 `dist/` 目录，此时只生成一个 HTML 文件 `main/index.html`。

在项目根路径下执行 `pnpm run build` 命令，构建完成后，查看 `dist/` 目录，此时生成 `main/index.html`、`main/user/index.html` 和 `main/user/profile/index.html` 三个 HTML 文件，内容分别对应上述三条路由。

**约定式路由**中的每一条路由，都会生成一个单独的 HTML 文件。查看 `main/index.html`，可以发现包含 `Index Page` 的文本内容，这正是 SSG 的效果。

执行 `pnpm run serve` 启动项目后，访问页面，在浏览器我们工具的 Network 窗口，查看请求返回的文档，文档包含组件渲染后的完整页面内容。

## 在自控式路由中使用

**自控式路由**是通过组件代码定义路由，需要应用运行起来才能获取准确的路由信息。因此，无法开箱即用的使用 SSG 功能。开发者需要通过配置告知 Modern.js 框架，哪些路由需要开启 SSG 功能。

例如有以下代码，包含多条路由，设置 `output.ssg` 为 `true` 时，默认只会渲染入口路由即 `/`：

```tsx title="src/App.tsx"
import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
import { StaticRouter } from '@modern-js/runtime/router/server';
import { use } from 'react';
import { RuntimeContext } from '@modern-js/runtime';

const Router = typeof window === 'undefined' ? StaticRouter : BrowserRouter;

export default () => {
  const context = use(RuntimeContext);
  const pathname = context?.request?.pathname;
  return (
    <Router location={pathname}>
      <Routes>
        <Route index element={<div>index</div>} />
        <Route path="about" element={<div>about</div>} />
      </Routes>
    </Router>
  );
};
```

如果我们希望同时开启 `/about` 的 SSG 功能，可以配置 `output.ssg`：

```ts title="modern.config.ts"
export default defineConfig({
  output: {
    ssg: {
      routes: ['/', '/about'],
    },
  },
});
```

执行 `pnpm run build` 后，可以看到 `dist/` 目录中，新增了一个 `main/about/index.html` 文件。

执行 `pnpm run serve` 启动项目后，访问页面，在浏览器我们工具的 Network 窗口，查看请求返回的文档，文档包含组件渲染后的完整页面内容。

:::info
以上仅介绍了单入口的情况，更多相关内容可以查看 [API 文档](/zh/configure/app/output/ssg.md)。
:::

## 添加动态路由

在自控式路由或包含动态段的约定式路由（如 `/user/[id]`）中，直接在 `routes` 中写入具体路径。

```js
export default defineConfig({
  output: {
    ssg: {
      routes: ['/', '/about', '/user/modernjs'],
    },
  },
});
```

## 多入口

多入口应用请通过 `output.ssgByEntries` 按入口分别配置：

```js
export default defineConfig({
  output: {
    ssgByEntries: {
      home: {
        routes: ['/', '/about', '/user/modernjs'],
      },
      admin: false,
    },
  },
});
```

:::info
详细配置请参考：[output.ssgByEntries](/zh/configure/app/output/ssgByEntries.md)
:::

## 配置渲染请求头

Modern.js 支持为具体入口或路由配置请求头，例如：

```js
export default defineConfig({
  output: {
    ssg: {
      headers: {
        'x-tt-env': 'ppe_modernjs',
      },
      routes: [
        '/',
        {
          url: '/about',
          headers: {
            from: 'modern-website',
          },
        },
      ],
    },
  },
});
```

上述配置中，为所有路由设置了 `x-tt-env` 请求头，单独为 `/about` 路由设置了 `from` 请求头。

:::tip
路由中设置的 `headers` 会覆盖入口中设置的 `headers`。
:::
