2022-07-01 16:47:25 +08:00
|
|
|
|
---
|
|
|
|
|
title: 构建时渲染 SSG
|
|
|
|
|
order: 10
|
|
|
|
|
---
|
2022-11-17 19:51:12 +08:00
|
|
|
|
|
2022-11-23 20:10:17 +08:00
|
|
|
|
:::tip
|
2022-11-15 15:03:30 +08:00
|
|
|
|
小程序端不支持该能力。
|
|
|
|
|
:::
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
|
|
|
|
构建时渲染,简称 SSG (Static Site Generation),是指在构建时提前生成内容 HTML 的渲染模式。
|
|
|
|
|
|
2022-11-11 11:02:51 +08:00
|
|
|
|
ice.js 默认开启 SSG 能力。SSG 不仅适用于静态站点,也适用于为普通 CSR 应用提前生成静态内容。
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
若有如下页面,内容为:
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
```tsx title="src/pages/home.tsx"
|
2022-07-01 16:47:25 +08:00
|
|
|
|
import { useData } from 'ice';
|
|
|
|
|
|
|
|
|
|
export default function Home() {
|
|
|
|
|
const data = useData();
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div>Hello ICE</div>
|
|
|
|
|
<div>stars: {data?.stars}</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
其中,第一个 `div` 中的内容是不依赖于数据。在传统的 CSR 应用中,`<Home />` 组件内容,无论是否依赖数据,都需要等待 JS 加载、解析后渲染。
|
|
|
|
|
|
|
|
|
|
利用 SSG,则可以在构建时,就将不依赖于动态数据的部分提前生成到 HTML 中。示例:
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
...
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div id="ice-container">
|
|
|
|
|
<div>Hello ICE</div>
|
|
|
|
|
<div>stars: </div>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 注意事项
|
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
- 在消费 `data` 时,需要做好空值判断,避免 `data` 为 `undefined` 或 `null` 时,产生渲染异常,无法正常构建。
|
|
|
|
|
- 代码需要兼容 Node.js 端。SSG 会在构建时进行,因此代码会运行在 Node.js 侧,因此在消费一些浏览器特有的环境变量时,要做好环境判断。
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
### SSG 的数据请求
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
通常在 SSG 时,我们不能使用后端接口获取当前的数据,因为这通常与用户访问时不一致。这时我们可以为 SSG 定义特定的数据请求方法,通过为路由组件定义 `staticDataLoader` 来实现。这样在 SSG 时,组件通过 `useData()` 获取的数据为 `staticDataLoader` 的返回值。
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
```tsx title="src/pages/index.tsx"
|
2022-11-10 16:40:39 +08:00
|
|
|
|
import { useData, defineDataLoader, defineStaticDataLoader } from 'ice';
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
|
|
|
|
export default function Home() {
|
|
|
|
|
const data = useData();
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div>Hello ICE</div>
|
|
|
|
|
<div>stars: {data?.stars}</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 浏览器侧的常规数据请求
|
2022-11-10 16:40:39 +08:00
|
|
|
|
export const dataLoader = defineDataLoader(() => {
|
2022-11-17 19:51:12 +08:00
|
|
|
|
return fetch('https://example.com/stars');
|
2022-11-10 16:40:39 +08:00
|
|
|
|
});
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
// 返回用于 SSG 的兜底数据
|
2022-11-10 16:40:39 +08:00
|
|
|
|
export const staticDataLoader = defineStaticDataLoader(() => {
|
2022-07-01 16:47:25 +08:00
|
|
|
|
return {
|
|
|
|
|
stars: 0,
|
|
|
|
|
};
|
2022-11-10 16:40:39 +08:00
|
|
|
|
});
|
2022-07-01 16:47:25 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-11-23 20:10:17 +08:00
|
|
|
|
:::tip
|
2022-11-10 16:40:39 +08:00
|
|
|
|
当 `defineDataLoader` 接受入参为数组时(定义了多个数据请求),`defineStaticDataLoader` 也需要与其一一对应。
|
2022-11-17 19:51:12 +08:00
|
|
|
|
:::
|
2022-11-10 16:40:39 +08:00
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
构建 Client 端的产物时,会移除 `staticDataLoader` 及其相关依赖。
|
2022-07-01 16:47:25 +08:00
|
|
|
|
|
|
|
|
|
## 关闭 SSG
|
|
|
|
|
|
|
|
|
|
在 `ice.config.mts` 下,按如下配置修改
|
|
|
|
|
|
2022-11-17 19:51:12 +08:00
|
|
|
|
```tsx title="ice.config.mts"
|
2022-07-01 16:47:25 +08:00
|
|
|
|
import { defineConfig } from '@ice/app';
|
|
|
|
|
|
2022-11-11 11:02:51 +08:00
|
|
|
|
export default defineConfig(() => ({
|
2022-11-17 19:51:12 +08:00
|
|
|
|
// ...
|
2022-07-01 16:47:25 +08:00
|
|
|
|
ssg: false,
|
2022-11-11 11:02:51 +08:00
|
|
|
|
}));
|
2022-07-01 16:47:25 +08:00
|
|
|
|
```
|