@k8ordo/framework

設定とファイル

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にそのまま渡します。

ts
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.ts
import { 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

ts
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の中で呼びます。

ts
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を読みます。
ts
cookies().get('session');
cookies().set('session', token, { maxAge: 60 * 60 * 24 });
cookies().delete('session');

import元 @k8ordo/framework/server

cookies().set()の3つ目の引数で渡すCookieの属性です。既定値は、セッションのCookieに向いた値です。

ts
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の中で呼びます。

ts
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で、ヘッダーを読むのに使います。

ts
requestHeaders(): Headers

注意

  • リクエストの外で呼ぶとrequestHeaders() needs a request、ページの描画の中で呼ぶとrequestHeaders() belongs to what answers the requestのエラーになります。

redirect

import元 @k8ordo/framework/server

serverモードだけ。Server Actionを終え、別のURLへリダイレクトします。

ts
redirect(to: string): never

引数

tostring
行き先のURLです。書いたまま送られるので、href()で作ります。

戻り値

never — 値を返しません。呼んだ行より後は実行されません。

注意

  • 内部で例外を使って処理を終えるので、tryの中では呼びません。
  • JavaScriptが読み込まれる前に送られたフォームには303を返します。クライアントのランタイムからの呼び出しには、ルーターに行き先を伝えるペイロードを返します。

nonce

import元 @k8ordo/framework/server

serverモードだけ。この応答のインラインスクリプトに付けるnonceを返します。リクエストごとに新しい値です。

ts
nonce(): string

注意

  • リクエストを処理している間なら、描画の中でも同じ値を返します。
  • リクエストの外で呼ぶと、nonce() needs a requestのエラーになります。

Guard

import元 @k8ordo/framework/server

serverモードだけ。guard.tsがdefault exportする関数の型です。そのディレクトリのパターンを型引数に渡します。

ts
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の型です。どちらのフィールドも読むだけです。

ts
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モードでも使えます。

ts
type RedirectTarget =
  | string
  | { to: string; permanent?: boolean };

serve

import元 @k8ordo/framework/serve

ビルドをNode.jsのHTTPサーバーで動かします。待ち受けを始めると、URLと止める関数を返します。

ts
serve(options?: ServeOptions): Promise<Server>

引数

options.diststring
ビルドの出力ディレクトリです。既定はdistで、今の作業ディレクトリから解決します。
options.portnumber
待ち受けるポートです。既定は3000で、0を渡すと空いているポートをシステムが選びます。
options.hoststring
待ち受けるホストです。既定のlocalhostには同じマシンからしか接続できないので、コンテナの中などでは0.0.0.0を渡します。

戻り値

Promise<Server> — 待ち受けを始めたサーバー。

フィールド

portnumber
実際に待ち受けているポートです。
urlstring
http://<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.js
import { 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()の隣に置きます。どちらのモードでも使えます。

ts
vercel(): Plugin

戻り値

Plugin — Viteのプラグイン。

注意

  • serverモードでは、依存をすべてバンドルしたハンドラが関数になります。resolve.externalでバンドルから外した依存は関数に入らないので、Vercelでは動きません。
  • staticモードでは関数を作りません。書き出したファイルと、ビルドしていない値をシェルに書き換えるルートだけを書きます。Vercelは_redirectsを読みません。
vite.config.ts
import { framework } from '@k8ordo/framework/vite';
import { vercel } from '@k8ordo/framework/vercel';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [framework({ mode: 'server' }), vercel()],
});
k8ordo

Baselineに入った機能を、制限なく使うReactのライブラリ群。

© 2026 k8o — MIT License

組版:Noto Sans JP / M PLUS 2