🧊

SolidStart Beta 2と、NitroとVinxi

先日、ここ1年くらい?ずっと音沙汰がなかったSolidStartに動きがあり。

Release v0.4.0 - Beta 2 · solidjs/solid-start https://github.com/solidjs/solid-start/releases/tag/v0.4.0

何が変わったかなーって見てたら、ほぼ全部書き直して150ファイル10000行から32ファイル1400行になったと。 (もちろん外部ライブラリに逃しただけなので、総量はそんなに変わってないとは思うけど)

一番の変更点として、NitroとVinxiを採用したらしいので、そのあたりどう棲み分けしてるのかをまとめておこうかと。

Nitro

unjs/nitro: Create, build and deploy universal web servers. The open engine powering Nuxt and open to everyone. https://github.com/unjs/nitro

Nuxtのベースになってるやつでもありつつ、他のフレームワークも載せたければ載せられるよっていうやつ。

Nitroそれ自体は、どっちかというとユニバーサルなWebサーバーが書けるフレームワークで、

  • ファイルベースのルーティング
  • プリレンダリング
  • プラグイン機構、ランタイムのHooks
  • HMR、Auto import、Tree shaking
  • デプロイ先ごとのアダプター

みたいな機能がある。

単体でも使えて、nitro devとかnitro buildとかできるし、CLIから何から何までフル実装されてる。(ビルドはrollupに投げてるけど)

実装はUnJSの総力が結集!みたいな感じになっていて、それぞれすごい読み応えがある。

ほんとにめちゃめちゃいっぱいあるし、全部が粒ぞろいでパワーを感じる。

https://unjs.io/packages

ちなみに、npm上でnitropackっていうネームスペースになってるのは、nitroっていうモジュールが既に存在してるからっぽい。

Vinxi

で、SolidStartは、Nitroを直接使ってるわけではなく、このVinxiっていうレイヤーを介してる。

nksaraf/vinxi: The JavaScript Server SDK https://github.com/nksaraf/vinxi

@nksaraf氏は、前々からずーっとSolidStartをやってる人。

Vinxiは、NitroとViteをベースにしたフルスタックなサーバー用SDKで、各UIフレームワークとNitroをつなげる自称ルーター、実態はバンドラー相当という感じ。

BunのBun.Appに着想を得て実装されてるとのことで、これはざっくり書くとこういう設定ファイルでアプリがビルドできるぜってアイデア。

// See also https://github.com/oven-sh/bun/pull/2551
[
  {
    name: "public",
    mode: "static",
    dir: "./public",
  },
  {
    name: "client",
    mode: "build",
    handler: "./app/client.tsx",
    target: "browser",
    plugins: () => [solid({ ssr: true })],
    base: "/_build",
  },
  {
    name: "ssr",
    mode: "handler",
    handler: "./app/server.tsx",
    target: "server",
    plugins: () => [solid({ ssr: true })],
  },
];

各ルートごとのmodeによって、どのURLをどうハンドルするかを自在にできる。

  • ただの静的アセット用のルート
  • 単なるAPIのルート
  • SPAとして動作するルート
  • SSRするルート

もしくは、自作したモードも選べて、どんなサイトでもアプリでも作れるぜっていう。

つまり、

  • DXとしてViteは使いたい
  • もちろん特定のUIフレームワークも動かしたい
  • メタフレームワークとして、SSRとかSPAとかあらゆるモードをサポートしたい
  • それをどこにでもデプロイしたい

みたいな、昨今のみんなの夢をのせた新進気鋭の実装という感じ。

ほやほやなのでドキュメントサイトが壊れてるのはご愛嬌やけど、このサイトもVinxiでできてる。

Vinxi https://vinxi.vercel.app

コードにあるapp.config.jsを見ると、その雰囲気がわかるはず。

https://github.com/nksaraf/vinxi/blob/12e560d57f4cfc31a81cffd6ea276229d3304577/docs/app.config.js

Vinxi自体はNitroと同じで、特定のフレームワーク向けではない実装でありつつ、RSCみたいな固有な仕組みも載せられるようになってるとのこと。

なので、いま流行りのuse serverも使える・・・!(ただし中身はただのJSONをやり取りできるだけ)

https://github.com/nksaraf/vinxi/blob/12e560d57f4cfc31a81cffd6ea276229d3304577/packages/vinxi-server-functions/client-runtime.js

SolidStart

というわけで、そんなNitroとVinxiのさらに上で作られたメタフレームワークがSolidStartというわけ。

solidjs/solid-start: SolidStart, the Solid app framework https://github.com/solidjs/solid-start

(Vinxiのリポジトリにもframeworks/solid-startってのがあるけど、これはたぶん古そう)

足回りとしては、

あと、VinxiのServer functionsを拡張して、JSONだけでなくJavaScript界にあるものなんでも送れるようにしてあったり。

これは@lxsmnsyc氏のSerovalを使ってるから。氏も昔からSolidをやってる人で、いろんなSolid関連ライブラリを生み出してるお方。

lxsmnsyc/seroval: Stringify JS values https://github.com/lxsmnsyc/seroval

devalueよりも後発で、対応してるフォーマットが多い・・・!

https://github.com/lxsmnsyc/seroval/blob/42d0f185260ef90d0bbdeaa3c7b1c847b487cacd/docs/compatibility.md

そのほかには、SolidStart自体がめちゃめちゃ薄くなって、@solidjs/router@solidjs/metaのAPIをre-exportしてたのもなくなった。

  • ファイルベースルーティング
  • Server functionsとかビルドが絡む機能
  • デプロイ先を選ぶアダプター

のように、メタフレームワークという立ち位置でなければできないことだけやるようにしてる、ってスタンス。

たとえばServer actionsも、

  • @solidjs/routeractionsを使って、ナビゲーションごとに動かすけど
  • どこで実行するかは、SolidStartでuse serverしてサーバー側でやるようにできる

みたいな合わせ技になる。

それぞれが薄いがゆえに、それを組み合わせる層がユーザーランドに露出してるのが特徴かな〜。 カスタマイズ性は高いけど、どのレイヤーでやるの?ってのを考える必要があったり、その道具を正しく使う必要があったり。

そういう面も含めて、すごくSolidっぽいなって思った。(だからこその知る人ぞ知るポジションなんやろう)

現状コードの全体感を眺めるには、このexamplesが良かった。(experimentsて)

https://github.com/solidjs/solid-start/tree/main/examples/experiments

というわけで

  • Nitro+Vinxiによる既存OSSとの調和
  • もともとJSXなSolidで、use serverによるReact方面とのさらなる親和性

このあたりをヨシととるか、引き続き自作路線で一枚岩でいくべきかみたいなのが、メタフレームワーク界隈の関心事って感じなんかね。