設定とファイル
framework()のオプションと、src/routes/に置けるファイル、@k8ordo/frameworkの各エントリポイントがexportするものの一覧です。それぞれの使い方は、ガイドの各ページにあります。
このページの内容
エントリポイント
@k8ordo/frameworkは、コードが動く場所ごとにエントリポイントを分けています。デプロイしたアプリが読み込むエントリポイントは、どれもViteを読み込みません。
@k8ordo/framework:アプリのコードがimportする型と関数です。@k8ordo/framework/vite:vite.config.tsで使うプラグインframework()です。Viteを読み込みます。@k8ordo/framework/server:serverモードだけ。ハンドラの中で動くコードがimportする関数と型です。staticモードで値をimportするとビルドがエラーになります。Node.jsから使うのはAsyncLocalStorageだけなので、ハンドラが動くランタイムならどこでも動きます。@k8ordo/framework/serve:ビルドをNode.jsで動かすserve()です。serverモードのdist/server.jsが呼ぶ関数で、自前のサーバーからも使えます。staticモードのビルドは、静的ホスティングと同じように配信します。@k8ordo/framework/vercel:ビルドをVercel向けに書き出すプラグインvercel()です。どちらのモードでも使えます。@k8ordo/framework/generated:生成される.k8ordo/のファイルだけがimportする型と関数です。手で書くコードからはimportしません。
framework
import元 @k8ordo/framework/vite
アプリをビルドするViteのプラグインです。ReactのプラグインとRSCのパイプラインを含む配列を返すので、pluginsにそのまま渡します。
framework(options: FrameworkOptions): PluginOption[]引数
options.mode'static' | 'server''static'か'server'です。省略できません。'static'はページをビルド時に描画し、サーバーなしで動くアプリにします。'server'はページをリクエストごとに描画し、サーバーで動くアプリにします。options.routesDirstring- ルートのディレクトリです。プロジェクトのルートからの相対パスで、既定は
src/routesです。変えても、生成されるファイルは.k8ordo/に書かれます。 options.paths(patterns: readonly string[]) => readonly string[] | Promise<readonly string[]>- staticモードだけ。パラメータを持つルートのパス名を返す関数です。値の要るパターンの一覧を受け取り、パス名の配列かそのPromiseを返します。パス名にViteの
baseは含めません。fallback.tsxのあるページには、/ja/posts/:idのように値を残したシェルの場所も返せます。 options.sitestring- staticモードだけ。サイトの配信元です(
https://example.com)。渡すと、ビルドがsitemap.xmlも書きます。route.tsが受け取るrequest.urlのoriginにもなります。 options.cspReadonly<Record<string, readonly string[]>>- staticモードだけ。各ページに書くContent-Security-Policyです。ディレクティブごとにソースの配列を渡します。ビルドがフレームワークのスクリプトのハッシュを足して、
<meta>に書きます。
戻り値
PluginOption[] — Viteのプラグインの配列。
注意
pathsとsite、cspは、どれか1つでもmode: 'server'と一緒に書くと型エラーになります。cspに<meta>では効かないディレクティブか'strict-dynamic'を渡すと、framework()を呼んだ時点でthe "csp" option cannot go into a page's <meta> as it isのエラーになります。
vite.config.tsimport { framework } from '@k8ordo/framework/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
framework({
mode: 'static',
paths: () => ['/products/1', '/products/2'],
site: 'https://example.com',
}),
],
});ルートのファイル
src/routes/の下に置けるファイルと、それぞれがexportするものと受け取るものの一覧です。これ以外のファイルは、部品ならsrc/components/に、それ以外のモジュールならsrc/lib/に置きます。
page.tsx
- default export:そのディレクトリのURLで表示するページのコンポーネントです。
paramsとpathnameを受け取ります。 - serverモードでは
request(RouteRequest)も受け取ります。 paramsSchema:パラメータを検証するスキーマです。Standard Schemaを実装したものを渡します。省略できます。search:serverモードだけ。ページが読むクエリのスキーマで、@k8ordo/stateの定義のurlを渡します。exportしたページは、読んだ値をsearchとして受け取ります。
layout.tsx
- default export:その下に描画されるものを
childrenとして受け取って包むコンポーネントです。paramsとpathnameも受け取ります。paramsの型は文字列のままです。 - serverモードでは
request(RouteRequest)も受け取ります。 paramsSchema:その下のすべてのページで、ページ自身のスキーマより先に実行されます。
not-found.tsx
- default export:その下でどのルートにも当たらなかったURLで表示するコンポーネントです。
paramsとpathnameを受け取ります。paramsの値は検証されていない文字列です。 - serverモードでは
request(RouteRequest)も受け取ります。 - staticモードでは
404.htmlとして書き出されるので、アプリに1つだけ置けます。serverモードでは404のステータスで返し、ディレクトリごとに置けます。
error.tsx
'use client'のファイルにします。- default export:
errorとresetを受け取るコンポーネントです。その下でエラーが起きたとき、代わりに描画されます。paramsは受け取りません。
loading.tsx
- default export:propsを受け取らないコンポーネントです。その下のページを待つ間、
<Suspense>のfallbackとして描画されます。
fallback.tsx
- default export:propsを受け取らないコンポーネントです。staticモードで、
pathsに無い値のURLに横のpage.tsxの代わりに描かれます。 - パラメータを持つ
page.tsxの横に置きます。同じディレクトリにlayout.tsxは置けません。 - serverモードでは使われず、
page.tsxがどの値もリクエストごとに描きます。
redirect.ts
- default export:行き先の文字列か、
{ to, permanent }です。toはルート表のパターンで書きます。toのパラメータには、リクエストのURLから取り出した値が入ります。 - staticモードでは、行き先へ送るページとして書き出されます。serverモードでは、
GETとHEADに307を返し、permanentなら308を返します。
route.ts
GETやPOSTなどのメソッド名のexport:{ request, params }を受け取り、Responseを返す関数です。paramsSchema:ページと同じく、パラメータを検証します。- staticモードでは
GETだけをexportでき、その応答がそのURLのファイルとして書き出されます。serverモードでは7つのメソッドのどれでもexportできます。
guard.ts
- serverモードだけ。default export:
Guard型の関数です。その下のURLに応答する前に実行されます。Responseを返すとそこで応答し、何も返さなければページやroute.tsの処理に進みます。
アプリ向けのAPI
import {
bindParams,
href,
isNotFound,
matchPath,
navigateTo,
normalizePathname,
notFound,
useMatch,
usePathname,
usePendingPathname,
withBase,
} from '@k8ordo/framework';
import type {
BoundLinks,
BoundParams,
ErrorProps,
LayoutProps,
MatchablePattern,
MatchOptions,
NavigateToOptions,
PageProps,
RegisteredNavigablePattern,
RegisteredPageParams,
RegisteredParams,
RegisteredPattern,
RouteContext,
} from '@k8ordo/framework';どれも@k8ordo/routerのexportを、名前で再exportしています。どちらもフレームワークが描画しない<Router>を読むので、useParamsとuseRouteは含みません。ページはparamsをpropsで受け取ります。それぞれの説明は@k8ordo/routerのAPIにあります。
cookies
import元 @k8ordo/framework/server
serverモードだけ。リクエストのCookieを読み書きします。guard.tsとroute.ts、Server Actionの中で呼びます。
cookies(): Cookiesフィールド
get(name: string) => string | undefined- 名前で値を読みます。無ければ
undefinedです。 has(name: string) => boolean- その名前のCookieがあるかどうかを返します。
set(name: string, value: string, options?: CookieOptions) => void- 値を書きます。3つ目の引数で
CookieOptionsの属性を渡します。 delete(name: string, scope?: CookieScope) => void- Cookieを消します。書いたときと同じ
pathとdomainを渡します。
注意
- 読み取りには、同じリクエストの中で先に書いた値が反映されます。書いていない名前は、リクエストのCookieの値を返します。
- 書いた値は、どの応答でも
Set-Cookieヘッダーでブラウザに送られます。 - ページの描画の中で呼ぶと、
cookies() belongs to what answers the requestのエラーになります。ページはrequest.cookiesを読みます。
cookies().get('session');
cookies().set('session', token, { maxAge: 60 * 60 * 24 });
cookies().delete('session');CookieOptions
import元 @k8ordo/framework/server
cookies().set()の3つ目の引数で渡すCookieの属性です。既定値は、セッションのCookieに向いた値です。
type CookieOptions = {
readonly path?: string;
readonly domain?: string;
readonly maxAge?: number;
readonly expires?: Date;
readonly httpOnly?: boolean;
readonly secure?: boolean;
readonly sameSite?: 'strict' | 'lax' | 'none';
};フィールド
pathstring- 既定は
/です。 domainstring- 既定では付けません。
maxAgenumber- 有効期間を秒で渡します。
0を渡すと、すぐに切れます。 expiresDate- 期限を
Dateで渡します。 httpOnlyboolean- 既定は
trueで、ページのスクリプトからは読めません。 secureboolean- 既定は
trueで、HTTPSでしか送られません。localhostと127.0.0.1、[::1]へのHTTPのリクエストでは、既定がfalseになります。 sameSite'strict' | 'lax' | 'none'- 既定は
'lax'です。'none'は常にsecureで、既定でもそうなります。secure: falseと一緒に渡すとエラーになります。
responseHeaders
import元 @k8ordo/framework/server
serverモードだけ。最終的な応答が持つHeadersを返します。guard.tsとroute.ts、Server Actionの中で呼びます。
responseHeaders(): Headers注意
- ここに書いたヘッダーは、ページのHTMLとRSCのペイロード、
guard.tsが返したResponseのどれにも付きます。応答がすでに持っているヘッダーは置き換えます。 - リクエストの外で呼ぶと
responseHeaders() needs a request、ページの描画の中で呼ぶとresponseHeaders() belongs to what answers the requestのエラーになります。
requestHeaders
import元 @k8ordo/framework/server
serverモードだけ。リクエストのヘッダーを返します。guard.tsとroute.ts、Server Actionの中で呼びます。引数しか受け取らないServer Actionで、ヘッダーを読むのに使います。
requestHeaders(): Headers注意
- リクエストの外で呼ぶと
requestHeaders() needs a request、ページの描画の中で呼ぶとrequestHeaders() belongs to what answers the requestのエラーになります。
redirect
import元 @k8ordo/framework/server
serverモードだけ。Server Actionを終え、別のURLへリダイレクトします。
redirect(to: string): never引数
tostring- 行き先のURLです。書いたまま送られるので、
href()で作ります。
戻り値
never — 値を返しません。呼んだ行より後は実行されません。
注意
- 内部で例外を使って処理を終えるので、
tryの中では呼びません。 - JavaScriptが読み込まれる前に送られたフォームには
303を返します。クライアントのランタイムからの呼び出しには、ルーターに行き先を伝えるペイロードを返します。
nonce
import元 @k8ordo/framework/server
serverモードだけ。この応答のインラインスクリプトに付けるnonceを返します。リクエストごとに新しい値です。
nonce(): string注意
- リクエストを処理している間なら、描画の中でも同じ値を返します。
- リクエストの外で呼ぶと、
nonce() needs a requestのエラーになります。
Guard
import元 @k8ordo/framework/server
serverモードだけ。guard.tsがdefault exportする関数の型です。そのディレクトリのパターンを型引数に渡します。
type Guard<P extends string = string> = (
context: GuardContext<P>,
) => Response | void | Promise<Response | void>;フィールド
requestRequest- 受け取ったままの
Requestです。 paramsParamsOf<P>- そのディレクトリのパターンのパラメータです。
guard.tsはスキーマより前に実行されるので、URLの文字列のままです。
RouteRequest
import元 @k8ordo/framework/server
serverモードだけ。ページとレイアウト、not-found.tsxが受け取るrequestの型です。どちらのフィールドも読むだけです。
type RouteRequest = {
readonly headers: Headers;
readonly cookies: ReadonlyMap<string, string>;
};フィールド
headersHeaders- リクエストのヘッダーです。
cookiesReadonlyMap<string, string>Cookieヘッダーを名前ごとに読み取ったMapです。同じ名前が2回あれば、最初の値を使います。
RedirectTarget
import元 @k8ordo/framework/server
redirect.tsがdefault exportする値の型です。satisfies RedirectTargetと書くと、書いたその場で形を検査できます。型だけのimportなので、staticモードでも使えます。
type RedirectTarget =
| string
| { to: string; permanent?: boolean };serve
import元 @k8ordo/framework/serve
ビルドをNode.jsのHTTPサーバーで動かします。待ち受けを始めると、URLと止める関数を返します。
serve(options?: ServeOptions): Promise<Server>引数
options.diststring- ビルドの出力ディレクトリです。既定は
distで、今の作業ディレクトリから解決します。 options.portnumber- 待ち受けるポートです。既定は
3000で、0を渡すと空いているポートをシステムが選びます。 options.hoststring- 待ち受けるホストです。既定の
localhostには同じマシンからしか接続できないので、コンテナの中などでは0.0.0.0を渡します。
戻り値
Promise<Server> — 待ち受けを始めたサーバー。
フィールド
portnumber- 実際に待ち受けているポートです。
urlstringhttp://<host>:<port>の形のURLです。close() => Promise<void>- サーバーを止めます。止まると解決するPromiseを返します。
注意
- 自前のサーバーから呼ぶときは、
@k8ordo/frameworkをdependenciesに入れ、実行時にもインストールします。serverモードのビルドが書くdist/server.jsは、この関数をバンドル済みで持っています。 - serverモードのビルドでは、
GETとHEADのうち、dist/client/の中のファイルを指すものにはそのファイルを返します。それ以外はハンドラに渡します。 - ハンドラでエラーが起きたときは、
500と本文internal errorだけを返し、内容はサーバーのログに出します。 - staticモードのビルドでは、ハンドラを呼びません。ファイルと
_redirectsの書き換え、404.htmlの順に探して返します。GETとHEADのほかには405を返します。
serve.jsimport { serve } from '@k8ordo/framework/serve';
const server = await serve({ port: 3000 });
console.log(server.url);vercel
import元 @k8ordo/framework/vercel
vite buildに、VercelのBuild Output API(v3)の形で.vercel/output/も書かせるプラグインです。framework()の隣に置きます。どちらのモードでも使えます。
vercel(): Plugin戻り値
Plugin — Viteのプラグイン。
注意
- serverモードでは、依存をすべてバンドルしたハンドラが関数になります。
resolve.externalでバンドルから外した依存は関数に入らないので、Vercelでは動きません。 - staticモードでは関数を作りません。書き出したファイルと、ビルドしていない値をシェルに書き換えるルートだけを書きます。Vercelは
_redirectsを読みません。
vite.config.tsimport { framework } from '@k8ordo/framework/vite';
import { vercel } from '@k8ordo/framework/vercel';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [framework({ mode: 'server' }), vercel()],
});