Beta · server functions · alpha

Next.js のような、フルスタック。Astro のような、Islands。

layout・middleware・server loader・action・SSR・API routes。ページは HTML に描画され、マークした島だけがハイドレートします。ツールチェーン全体が Rust(oxc)なので、dev 起動は約90ミリ秒、再ビルドは数ミリ秒で完了します。

npm で入ります。Rust ツールチェーンは不要で、CLI はプリビルドのネイティブバイナリとして配布します。

alpha 版。まだ本番向けではありませんが、実在し、実際に速く、npm と crates.io で公開済みです。

Show, don't claim

このページが送る JavaScript は 12 KB。

このサイトで動く部分すべて、風のアニメーション・コピーボタン・スクロール演出を合わせて、Preact 込みで gzip 後 12 KB です。島の無いページは 0 KB。参考までに、React と ReactDOM だけで gzip 後およそ 45 KB。まだ自分のコードを 1 行も書いていない段階で、です。

このページ(島3つ + 風 + モーション)12 KB
コンテンツだけのページ(島なし)0 KB
React + ReactDOM の土台だけ約45 KB

このサイト自身の本番ビルドで実測(このサイトは Nowaki 製です)。同一のカウンタ1個アプリで直接比較すると、Nowaki ページの first-load は約 10 KB(gzip)。Astro と同等で、Next の app-router 基準(約 103 KB)のおよそ 1/5 です。benchmarks/head-to-head.mjs で再現できます。

打鍵ごとに感じる速さ。

多くの JavaScript フレームワークは、起動・変換・再ビルドを JavaScript ツールチェーンの上で行います。Nowaki はそのパイプライン全体を Rust(oxc)で動かすので、JavaScript バンドラーが温まりきる前に dev サーバーは応答しています。

~90 ms

サンプルアプリで実測した dev サーバー起動。

数ミリ秒

oxc による変更ファイルの再変換。JS バンドラーのウォームアップなし。

scope-hoisted

本番出力: モジュールを1スコープへ連結、ツリーシェイク、content-hash、ソースマップ付き。

何もない状態から、Rust なしで動くアプリへ。

npm create nowaki@latest

雛形作成

file-based の routes/islands/ を生成。CLI はプリビルドのバイナリなので、Rust を入れる必要はありません。

npm run dev

開発

Rust の oxc パイプラインがオンデマンドで変換。島はハイドレートし、それ以外は HTML のまま。エラーは全画面オーバーレイで表示。

npm run build · start

公開

scope-hoisting 済み・content-hash 付きの ESM と SSR モジュールを本番配信。あるいは静的に prerender して CDN へ。

ルートを書き、島をマークし、フォームを処理する。

ルートは、サーバーでのみ走る任意の loader を持つコンポーネント。非 GET リクエストはルートの action が処理します。ブラウザでハイドレートするのは islands/ のものだけです。

loader 付きルート

// routes/blog/[slug].tsx
import Comments from "../../islands/Comments.tsx";

// runs on the server only
export const loader = async ({ params }) => ({
  post: await db.post(params.slug),
});

export default function Post({ data }) {
  return (
    <article>
      <h1>{data.post.title}</h1>
      <Comments postId={data.post.id} /> // only this hydrates
    </article>
  );
}

action 付きフォーム

// routes/guestbook.tsx
export const loader = (ctx) => ({ entries: read(ctx) });

// a non-GET request runs the action
export async function action(ctx) {
  const form = await ctx.formData();
  ctx.setCookie("guestbook", add(form.get("msg")));
  return ctx.redirect("/guestbook"); // PRG
}

ファイル規約

routes/_layout.tsx共有レイアウト、ディレクトリ単位でネスト
routes/_middleware.tsルート前に実行。認証・リダイレクト・ヘッダ
routes/blog/[slug].tsx動的ルート + server loader
routes/api/posts.tsGET / POST ハンドラ、streaming Response
routes/_404.tsx · _500.tsx未一致ページとエラーページ
islands/Counter.tsxブラウザでハイドレート。それ以外はしない。

Next・Astro と並べて、正直に。

どのアイデアも単体では新しくありません。Nowaki の賭けはその組み合わせです。誇張なしで、実際にどこが違うかを示します。

.NowakiNext.jsAstro
サーバーリアクティブ島(クライアントJSゼロ)Only NowakiJetstream — 状態はサーバー、HTML パッチを WebSocket で push、コンポーネントJSゼロRSC 再描画は React ランタイムを積むServer Islands は SSR を遅延(一発・生更新ではない)
ツールチェーンRust (oxc) を自作 — 本番リクエストパスも RustTurbopack (SWC)、本番はJSVite → Rolldown、本番はJS
デフォルトの JavaScriptゼロ、島だけReact を送り hydrateゼロ、島だけ
フルスタックなアプリ DXrouting・loader・action・middleware・API・サーバー関数あり、成熟成長中・コンテンツ寄り
ツールチェーンの言語なしで入るnpm、Rust 不要npmnpm
成熟度alpha成熟・巨大なエコシステム成熟

ここだけ: 状態を持ち生更新するのに、コンポーネントJSをゼロで送る島。状態はサーバーが持ち、HTML パッチを WebSocket で押し出します — LiveView の発想を島に融合。RSC 再描画は React を積み、Astro の Server Islands は初期描画を遅延するだけで生更新はしません。これが両者にない一点です。

サーバー関数・ストリーミングSSR・プラグイン・デプロイアダプタは parity(同等)で差別化ではありません — Astro/Next にもあります。本当の強みは Jetstream、Rust の本番ランタイム、そして「フルスタック+JSゼロ+npmインストール」を同時に満たすこと。Next と Astro は成熟し実戦で揉まれていますが、Nowaki は alpha です。

どんなアプリに向くか。

Nowaki が向くのは、コンテンツ主体だが動的なアプリです。認証付きのマーケ、対話ウィジェット入りのドキュメント、本物のサーバーデータを持つ管理画面、EC。本文とサーバーデータが大半なのに、全 hydrate のフレームワークだと1ページに数百 KB の JavaScript を送ってしまう、その層です。

向いている

  • Next.js 風にアプリを書くが、各ページの大半は静的コンテンツとサーバーデータ。
  • フォーム・認証・動的ルートが欲しいが、全ページにクライアントランタイムの代金は払いたくない。
  • Remix 風の loader / action モデルが好きで、それを使う所にだけ JS を送りたい。

まだ得意でない

  • ほぼ全部が状態を持つ、全面インタラクティブな SPA。島はそこでは窮屈で、全 hydrate や RSC の方が合います。
  • 今日の本番クリティカルな用途。Nowaki は alpha で、API はまだ動きます。

静的サイトジェネレータではない、本物のフレームワーク。

Next.js / Remix 系譜の動的なアプリ向けに作られ、実際にプロダクトを載せられる部品が揃っています。

フルスタックなルーティング

file-based の routes/ に、ネスト可能な _layout_middleware・server loader・フォーム用の action、そしてメソッド分岐と streaming に対応した api/ ハンドラ。

デフォルトで島・JS ゼロ

ページはサーバーで HTML に描画。islands/ 配下のコンポーネントだけが配信・ハイドレートされ、ページが払うのは実際に使う分だけ。

サーバー関数("use server")

"use server" ディレクティブを持つモジュールは RPC 境界になります。export はサーバーにだけ残り、クライアントには fetch する極小プロキシだけ(実装もサーバー専用依存も出ません)。dispatch は allowlist 制で、getContext() からリクエストの cookie/ヘッダを読めます。

Jetstream island(サーバーリアクティブ)

島を export const live にするとコンポーネント JS をクライアントに送りません。状態はサーバーに置き、クリックは WebSocket で届き、Rust サーバーが再描画して HTML パッチを push、~2 KB のランタイムが morph で当てます。presence・ハートビート・接続スケールも内蔵。クライアント島(楽観UI)と同一ページで共存します。

Rust ツールチェーン (oxc)

パース・変換・解決・バンドル・minify・スコープホイスティングが Rust で動作。高速なコールドスタート、数ミリ秒の再ビルド、再起動をまたぐ永続ディスクキャッシュ。

npm で入る、Rust 不要

CLI は npm の optionalDependencies でプリビルドのネイティブバイナリとして配布。cargo もツールチェーンも postinstall も不要。

島間 SPA ルーター

島のあるページ間の遷移はクライアント側で即時、prefetch とスクロール復元つき。島の無いページは JS ゼロのまま通常遷移。

CSS Modules・アセット・ソースマップ

クラス名をスコープ化する *.module.css、画像やフォントのハッシュ付き import、dev/prod 両方の end-to-end ソースマップ。

npm エコシステムそのまま

SSR は Rust が管理する Preact の Node サイドカーで動くので、既存のパッケージがそのまま使えます。

正直な開発体験

全画面エラーオーバーレイ、コードフレーム診断、ホットリロード、保存時の島ホットスワップ。

alpha について正直に。

Nowaki はまだ若いですが、コアは実在し、ヘッドレス Chrome まで含めて端から端まで検証済みです。現在地を正確に示します。

今できること

  • dev / build / start / prerender
  • レイアウト・ミドルウェア・action・API ルート
  • Islands + 島間 SPA ルーター
  • サーバー関数("use server")RPC
  • Jetstream island: サーバーリアクティブ・クライアント JS ゼロ
  • Jetstream の presence・接続スケール(ハートビート・上限)
  • プラグイン仮想モジュール(resolveId / load)+ transform フック
  • CSS Modules・アセット import・ソースマップ
  • スコープホイスティング済みの本番バンドル
  • デプロイアダプタ: Node・静的・Bun・Deno・Cloudflare edge
  • ストリーミング SSR・設定プラグイン・TSRX(.tsrx)島
  • Next・Astro との直接ベンチ
  • Rust 本番ホットパス + npm 経由の Rust 不要インストール

ロードマップ

  • 状態保持(prefresh)HMR
  • TSRX 島の scoped CSS
  • RSC 風のストリーミング境界
  • 公開 API の安定化(1.0 へ)

ロードマップ全文を読む →