logo
  • 指南
  • 配置
  • 插件
  • API
  • 示例
  • 社区
  • Modern.js 2.x 文档
  • 简体中文
    • 简体中文
    • English
    • 开始
      介绍
      快速上手
      版本升级
      名词解释
      技术栈
      核心概念
      页面入口
      构建工具
      Web 服务器
      基础功能
      路由
      路由基础
      配置式路由
      数据管理
      数据获取
      数据写入
      数据缓存
      渲染
      服务端渲染(SSR)
      服务端流式渲染(Streaming SSR)
      渲染缓存
      静态站点生成(SSG)
      渲染预处理 (Render Preprocessing)
      样式开发
      引入 CSS
      使用 CSS Modules
      使用 CSS-in-JS
      使用 Tailwind CSS
      HTML 模板
      引用静态资源
      引用 JSON 文件
      引用 SVG 资源
      引用 Wasm 资源
      调试
      数据模拟(Mock)
      网络代理
      使用 Rsdoctor
      使用 Storybook
      测试
      Playwright
      Vitest
      Jest
      Cypress
      路径别名
      环境变量
      构建产物目录
      部署应用
      进阶功能
      使用 Rspack
      使用 BFF
      基础用法
      运行时框架
      扩展 BFF Server
      扩展一体化调用 SDK
      文件上传
      跨项目调用
      优化页面性能
      代码分割
      静态资源内联
      产物体积优化
      React Compiler
      提升构建性能
      浏览器兼容性
      配置底层工具
      源码构建模式
      服务端监控
      Monitors
      日志事件
      指标事件
      国际化
      基础概念
      快速开始
      配置说明
      语言检测
      资源加载
      路由集成
      API 参考
      高级用法
      最佳实践
      自定义 Web Server
      专题详解
      模块联邦
      简介
      开始使用
      应用级别模块
      服务端渲染
      部署
      集成国际化能力
      常见问题
      依赖安装问题
      命令行问题
      构建相关问题
      热更新问题
      已下线功能
      📝 编辑此页面
      上一页渲染缓存下一页渲染预处理 (Render Preprocessing)

      #静态站点生成(SSG)

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

      #启用 SSG

      我们首先需要执行 pnpm run new 启用 SSG 功能:

      ? 请选择你想要的操作 启用可选功能
      ? 请选择功能名称 启用「SSG」功能

      执行命令后,在 modern.config.ts 中注册 SSG 插件:

      modern.config.ts
      import { ssgPlugin } from '@modern-js/plugin-ssg';
      
      export default defineConfig({
        output: {
          ssg: true,
        },
        plugins: [..., ssgPlugin()],
      });

      ::::info 适用范围

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

      #开发环境调试

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

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

      #在约定式路由中使用

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

      #基本用法

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

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

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

      • /
      • /user
      • /user/profile
      Tip

      如果还不了解约定式路由的规则,可以先查看路由方案。

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

      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 行为。

      例如以下目录结构,/、/user、/user/profle 三条路由都开启 SSG:

      .
      ├── src
      │   └── routes
      │       ├── layout.tsx
      │       ├── page.tsx
      │       └── user
      │           ├── layout.tsx
      │           ├── page.tsx
      │           └── profile
      │               └── page.tsx

      可以通过配置 preventDefault 来禁用某些路由的默认行为。进行下面配置后,最终只会生成 /、/user/profle 两条路由的 SSG 页面:

      export default defineConfig({
        output: {
          ssg: {
            preventDefault: ['/user'],
          },
        },
      });

      #在自控式路由中使用

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

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

      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:

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

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

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

      Info

      以上仅介绍了单入口的情况,更多相关内容可以查看 API 文档。

      #添加动态路由

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

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

      #多入口

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

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

      详细配置请参考:output.ssgByEntries

      #配置渲染请求头

      Modern.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。