Appearance
SSG 助手
¥SSG Helper
SSG Helper 从你的 Hono 应用生成静态站点。它将检索已注册路由的内容并将其保存为静态文件。
¥SSG Helper generates a static site from your Hono application. It will retrieve the contents of registered routes and save them as static files.
用法
¥Usage
手动
¥Manual
如果你有一个简单的 Hono 应用,如下所示:
¥If you have a simple Hono application like the following:
tsx
// index.tsx
const app = new Hono()
app.get('/', (c) => c.html('Hello, World!'))
app.use('/about', async (c, next) => {
c.setRenderer((content, head) => {
return c.html(
<html>
<head>
<title>{head.title ?? ''}</title>
</head>
<body>
<p>{content}</p>
</body>
</html>
)
})
await next()
})
app.get('/about', (c) => {
return c.render('Hello!', { title: 'Hono SSG Page' })
})
export default app
对于 Node.js,创建如下构建脚本:
¥For Node.js, create a build script like this:
ts
// build.ts
import app from './index'
import { toSSG } from 'hono/ssg'
import fs from 'fs/promises'
toSSG(app, fs)
通过执行脚本,文件将输出如下:
¥By executing the script, the files will be output as follows:
bash
ls ./static
about.html index.html
Vite 插件
¥Vite Plugin
使用 @hono/vite-ssg
Vite 插件,你可以轻松处理该过程。
¥Using the @hono/vite-ssg
Vite Plugin, you can easily handle the process.
有关更多详细信息,请参见此处:
¥For more details, see here:
https://github.com/honojs/vite-plugins/tree/main/packages/ssg
toSSG
toSSG
是生成静态站点的主要函数,以应用和文件系统模块作为参数。它基于以下内容:
¥toSSG
is the main function for generating static sites, taking an application and a filesystem module as arguments. It is based on the following:
输入
¥Input
toSSG 的参数在 ToSSGInterface 中指定。
¥The arguments for toSSG are specified in ToSSGInterface.
ts
export interface ToSSGInterface {
(
app: Hono,
fsModule: FileSystemModule,
options?: ToSSGOptions
): Promise<ToSSGResult>
}
app
指定已注册路由的new Hono()
。¥
app
specifiesnew Hono()
with registered routes.fs
指定以下对象,假设node:fs/promise
。¥
fs
specifies the following object, assumingnode:fs/promise
.
ts
export interface FileSystemModule {
writeFile(path: string, data: string | Uint8Array): Promise<void>
mkdir(
path: string,
options: { recursive: boolean }
): Promise<void | string>
}
使用 Deno 和 Bun 的适配器
¥Using adapters for Deno and Bun
如果要在 Deno 或 Bun 上使用 SSG,则每个文件系统都提供了一个 toSSG
函数。
¥If you want to use SSG on Deno or Bun, a toSSG
function is provided for each file system.
对于 Deno:
¥For Deno:
ts
import { toSSG } from 'hono/deno'
toSSG(app) // The second argument is an option typed `ToSSGOptions`.
对于 Bun:
¥For Bun:
ts
import { toSSG } from 'hono/bun'
toSSG(app) // The second argument is an option typed `ToSSGOptions`.
选项
¥Options
选项在 ToSSGOptions 接口中指定。
¥Options are specified in the ToSSGOptions interface.
ts
export interface ToSSGOptions {
dir?: string
concurrency?: number
beforeRequestHook?: BeforeRequestHook
afterResponseHook?: AfterResponseHook
afterGenerateHook?: AfterGenerateHook
extensionMap?: Record<string, string>
}
dir
是静态文件的输出目标。默认值为./static
。¥
dir
is the output destination for Static files. The default value is./static
.concurrency
是同时生成的文件数。默认值为2
。¥
concurrency
is the concurrent number of files to be generated at the same time. The default value is2
.extensionMap
是一个映射,其中包含Content-Type
作为键和扩展字符串作为值。这用于确定输出文件的文件扩展名。¥
extensionMap
is a map containing theContent-Type
as a key and the string of the extension as a value. This is used to determine the file extension of the output file.
稍后将描述每个 Hook。
¥Each Hook will be described later.
输出
¥Output
toSSG
以以下 Result 类型返回结果。
¥toSSG
returns the result in the following Result type.
ts
export interface ToSSGResult {
success: boolean
files: string[]
error?: Error
}
Hook
你可以通过在选项中指定以下自定义钩子来自定义 toSSG
的流程。
¥You can customize the process of toSSG
by specifying the following custom hooks in options.
ts
export type BeforeRequestHook = (req: Request) => Request | false
export type AfterResponseHook = (res: Response) => Response | false
export type AfterGenerateHook = (
result: ToSSGResult
) => void | Promise<void>
BeforeRequestHook/AfterResponseHook
toSSG
针对应用中注册的所有路由,但如果你想要排除某些路由,则可以通过指定 Hook 来过滤它们。
¥toSSG
targets all routes registered in app, but if there are routes you want to exclude, you can filter them by specifying a Hook.
例如,如果你只想输出 GET 请求,请在 beforeRequestHook
中过滤 req.method
。
¥For example, if you want to output only GET requests, filter req.method
in beforeRequestHook
.
ts
toSSG(app, fs, {
beforeRequestHook: (req) => {
if (req.method === 'GET') {
return req
}
return false
},
})
例如,如果你只想在 StatusCode 为 200 或 500 时输出,请在 afterResponseHook
中过滤 res.status
。
¥For example, if you want to output only when StatusCode is 200 or 500, filter res.status
in afterResponseHook
.
ts
toSSG(app, fs, {
afterResponseHook: (res) => {
if (res.status === 200 || res.status === 500) {
return res
}
return false
},
})
AfterGenerateHook
如果你想钩子 toSSG
的结果,请使用 afterGenerateHook
。
¥Use afterGenerateHook
if you want to hook the result of toSSG
.
ts
toSSG(app, fs, {
afterGenerateHook: (result) => {
if (result.files) {
result.files.forEach((file) => console.log(file))
}
})
})
生成文件
¥Generate File
路由和文件名
¥Route and Filename
以下规则适用于注册的路由信息和生成的文件名。默认 ./static
的行为如下:
¥The following rules apply to the registered route information and the generated file name. The default ./static
behaves as follows:
/
->./static/index.html
/path
->./static/path.html
/path/
->./static/path/index.html
文件扩展名
¥File Extension
文件扩展名取决于每个路由返回的 Content-Type
。例如,来自 c.html
的响应保存为 .html
。
¥The file extension depends on the Content-Type
returned by each route. For example, responses from c.html
are saved as .html
.
如果你想要自定义文件扩展名,请设置 extensionMap
选项。
¥If you want to customize the file extensions, set the extensionMap
option.
ts
import { toSSG, defaultExtensionMap } from 'hono/ssg'
// Save `application/x-html` content with `.html`
toSSG(app, fs, {
extensionMap: {
'application/x-html': 'html',
...defaultExtensionMap,
},
})
请注意,无论扩展名是什么,以斜杠结尾的路径都会保存为 index.ext。
¥Note that paths ending with a slash are saved as index.ext regardless of the extension.
ts
// save to ./static/html/index.html
app.get('/html/', (c) => c.html('html'))
// save to ./static/text/index.txt
app.get('/text/', (c) => c.text('text'))
中间件
¥Middleware
引入支持 SSG 的内置中间件。
¥Introducing built-in middleware that supports SSG.
ssgParams
你可以使用 Next.js 的 generateStaticParams
之类的 API。
¥You can use an API like generateStaticParams
of Next.js.
示例:
¥Example:
ts
app.get(
'/shops/:id',
ssgParams(async () => {
const shops = await getShops()
return shops.map((shop) => ({ id: shop.id }))
}),
async (c) => {
const shop = await getShop(c.req.param('id'))
if (!shop) {
return c.notFound()
}
return c.render(
<div>
<h1>{shop.name}</h1>
</div>
)
}
)
disableSSG
具有 disableSSG
中间件集的路由被 toSSG
排除在静态文件生成之外。
¥Routes with the disableSSG
middleware set are excluded from static file generation by toSSG
.
ts
app.get('/api', disableSSG(), (c) => c.text('an-api'))
onlySSG
具有 onlySSG
中间件集的路由将在 toSSG
执行后被 c.notFound()
覆盖。
¥Routes with the onlySSG
middleware set will be overridden by c.notFound()
after toSSG
execution.
ts
app.get('/static-page', onlySSG(), (c) => c.html(<h1>Welcome to my site</h1>))