静态网站生成 (SSG) 概述
静态网站生成,通常称为“SSG”,是将网站网页预渲染为静态 HTML 文件的过程。好处是,当访问者请求网页时,响应是一个预生成的 HTML 文件(静态文件),不需要网页的 HTML 在访问者的浏览器中“重建”,也不需要由您的服务器动态创建(稍后将详细介绍)。
此外,由于 Qwik 的底层架构,页面性能也受益于不需要 Javascript “水合”步骤,这可以显着降低性能并减慢用户交互速度。通过使用 SSG 预渲染静态 index.html
文件,并结合 Qwik 的 可恢复性,静态网站生成提供了比传统解决方案更多的性能优势。
SSG 与服务器端渲染 (SSR)
Qwik City 能够将 Qwik 应用程序(无论是“webapp”还是“website”)生成静态 HTML。一旦它被生成为 HTML,Qwik 能够通过使用 可恢复性 根本上跳过重建应用程序,因为应用程序已经作为 HTML 生成。静态网站生成 (SSG) 和服务器端渲染 (SSR) 使用相同的过程来生成 HTML。然而,SSG 和 SSR 之间的主要区别在于“何时”生成 HTML。
在传统设置中,SSG 在构建时预渲染每个网页,而 SSR 在每个 HTTP 请求时按需渲染每个网页。SSG 只需要在每次构建时生成一次 HTML,这对于多个访问者应该看到相同内容的网页来说非常棒。相比之下,SSR 非常适合网页内容可能因访问者而异的情况,并且需要为每个单独的 HTTP 请求渲染自定义 HTML。
例如,SSG 非常适合博客或文档网站,其中所有内容对于多个访问者来说应该都是相同的。虽然 SSR 可能适用于博客,但对于您的 HTTP 服务器来说,为每个访问者渲染博客内容可能是一种不必要的负担,即使他们最终都会看到相同的 HTML。
但是,帐户仪表板通常会为每个登录用户显示不同的内容。在这种设置中,每个用户都应该获得包含其帐户信息的自定义渲染的 HTML,而不是每个人都看到完全相同的内容。这就是 SSR 更受欢迎的地方。
理想情况下,您越能使用静态网站生成越好,因为这将减少服务器的成本并加快响应时间。
但是,使用 Qwik City,决定使用 SSG 还是 SSR 不必是二选一。相反,您自己的实现可以选择让某些路由路径使用 SSG,而其他页面使用 SSR。这完全取决于您和您的需求。
静态网站生成配置
静态网站生成是通过内置的适配器创建的,要创建适配器,请运行
npm run qwik add static
选择 适配器:静态网站(.html 文件)
。完成!
更改
运行上述命令将对您的项目进行以下更改
- 一个
build.server
脚本将自动添加到您的package.json
文件中。 - 将创建一个
adapters/static/vite.config.ts
文件。
您的构建文件将生成到 dist
文件夹中。
您可以使用以下命令构建您的静态网站
npm run build.server
SSG 配置
adapters/static/vite.config.ts
文件还包含 SSG 配置,这将针对每个实现进行自定义。
origin
URL origin
,它是方案(协议)和主机名(域名)的组合。例如,https://qwik.node.org.cn
的协议为 https://
,域名是 qwik.dev
。但是,origin
不包含 pathname
。
origin
用于在静态网站生成 (SSG) 期间提供完整的 URL,以及模拟完整的 URL 而不是仅 pathname
。例如,为了渲染正确的规范标签 URL 或 sitemap.xml
中的 URL,必须提供 origin
。
如果网站还以 /
以外的路径名开头,请在 Vite 配置选项中使用 base
选项(Qwik City 配置选项中的 basePathname
选项已弃用)。
outDir
outDir
是一个文件系统输出目录,静态文件应该写入该目录。在上面的示例中,它使用 Node 的 fileURLToPath 来创建一个绝对文件系统路径,将静态 HTML 文件写入该路径。
Javascript 运行时
对于一个 JavaScript 项目,通常构建的运行时会基于 Node.js。然而,Qwik City 静态网站生成的内核并不局限于使用 Node.js,这就是为什么 qwikCityGenerate()
函数是从 @builder.io/qwik-city/static/node
导入的原因。通过将生成函数限定在特定运行时,例如 Node.js,这使得 Qwik City 能够在未来从其他运行时(例如 Deno 或 Bun)生成 SSG。
动态 SSG 路由
到目前为止,我们只讨论了如何为单个路由路径生成静态 HTML 文件。然而,在大多数情况下,您需要为具有动态参数的多个路由路径生成 HTML 文件。例如,一个产品网站可能为每个产品提供一个路由路径,例如 /product/:id
。在这种情况下,您需要为每个产品页面生成 HTML 文件,这将需要为每个产品 ID 生成 HTML 文件。
import { component$ } from '@builder.io/qwik';
import { useLocation, type StaticGenerateHandler } from '@builder.io/qwik-city';
import { loadProductIds } from './load-product-ids';
export default component$(() => {
const { params } = useLocation();
return <p>Example: {params.id}</p>;
});
export const onStaticGenerate: StaticGenerateHandler = async ({ env }) => {
// example of loading params for this use case
// every implementation will be different
const ids = await loadProductIds({
apiKey: env.get('API_KEY'),
});
return {
params: ids.map((id) => {
return { id };
}),
};
};
在上面的示例中,onStaticGenerate()
函数通过请求一个 API(该 API 位于从环境变量中检索到的 API 密钥后面)来从 loadProductIds()
函数加载产品 ID。此函数将根据每个实现进行自定义,但总体思路是您需要加载每个产品 ID 的数据,然后为每个产品 ID 生成 HTML 文件。
onStaticGenerate
函数应该从模块的顶层导出,并应该返回一个包含 params
属性的对象。params
属性应该是一个对象数组,其中每个对象都是路由路径的一组参数。例如,如果路由路径是 /product/:id
,那么 params
数组应该是一个包含 id
属性的对象数组。
此示例的目录结构如下:
src/
└── routes/
└── product/
└── [id]/
└── index.tsx
请注意,index.tsx
文件位于名为 [id]
的目录中。这是一个特殊的目录名称,它告诉 Qwik City 为每个 id
参数生成 HTML 文件。index.tsx
文件是 Qwik City 在为路由路径生成 HTML 文件时使用的默认文件。