SolidjsでSSRとかSSGとかできるフレームワーク、SolidStartをざっくり紹介
SolidjsとSolidStartが個人的にかなり来てるので、今回はSolidStartでSSGだったりSSRだったりをする方法を紹介します。
👇SolidStart
👇Solidjs
とりあえず動かしてみる
まずはとりあえずで動かします。
超ざっくり解説です。
Create Solid !!
Solidjsプロジェクトをつくります。
パッケージマネージャーはお好きなものを。今回はpnpmで行きます
pnpm create solid
テンプレートを選択します。今回はとりあえずbareで。
そのほかのオプションはこんな感じで行きます。
Server Side Rendering?... はSSRするかどうか。
Use TypeScript?... はTypeScriptを利用するかどうか。
ファイルが生成されて入れば成功です。
Run SolidStart !!
とりあえず開発サーバーを立ち上げてみます。
pnpm install
pnpm dev
こんな感じになれば成功です。
アクセスするとこんな感じに。
Build SolidStart !!
とりあえずビルドしてみます。
pnpm build
ログが流れて...
.solid
ディレクトリと、dist
ディレクトリが生成されます。
Start SolidStart !!
とりあえず動かしてみます。
pnpm start
動きました。
くわしく
ちょこっと詳しく説明します。
SolidStartって?
This is the home of the Solid app framework. This is still a work in progress. Many features are missing or incomplete. Experimental status does not even mean beta status. Patch releases will break everything.
Solidjsのアプリケーションフレームワークです。まだまだ開発段階のもので、足りない機能だったり不完全な機能だったりがあります。めちゃめちゃ頻繁に更新されています。
👇主な機能はこんな感じ
- ファイルシステムベースのルーティング
- すべてのレンダリング モードをサポート(SSR, SSG, CSR)
- すべての一般的なプラットフォームに展開するためのアダプター
- CSS モジュール、SASS/SCSS サポート
- TypeScriptファースト
もちろんCloudflareWorkersでもSSRできます。
アダプター
SolidStartは一般的なプラットフォーム(Vercel, Cloudflare Pages/Workers, ...)をサポートするアダプターを持っています。
アダプターの変更はvite.config.ts
から
import solid from "solid-start/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [solid({
adapter: 'solid-start-node', // ここにアダプターの名前を
})],
});
何も指定していない場合はインストールされているアダプターを検出して自動的に選択されます。
複数アダプタがある場合に何も指定されていない場合は...
気になる方は実験してみてください(?)
👇現在公開されているアダプタ
- solid-start-cloudflare-pages
- solid-start-cloudflare-workers
- solid-start-deno
- solid-start-netlify
- solid-start-node
- solid-start-static
- solid-start-vercel
ちなみにSSGはsolid-start-static
を使えば簡単にできます。
root.tsx
next.jsでいう_document.tsx
みたいな?
SolidStartはHtml
, Head
, Link
, Meta
... 等のコンポーネントを持っていて、それらを使ってHtmlを構築していきます。
// @refresh reload
import { Suspense } from "solid-js";
import {
Body,
ErrorBoundary,
FileRoutes,
Head,
Html,
Meta,
Routes,
Scripts,
Title
} from "solid-start";
import "./root.css";
export default function Root() {
return (
<Html lang="en">
<Head>
<Title>SolidStart - Bare</Title>
<Meta charset="utf-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<Body>
<Suspense>
<ErrorBoundary>
<a href="/">Index</a>
<a href="/about">About</a>
<Routes>
<FileRoutes />
</Routes>
</ErrorBoundary>
</Suspense>
<Scripts />
</Body>
</Html>
);
}
デフォルトだとこんな感じです。
<Scripts />
はHydration用のスクリプト、<FileRoutes />
はnextjsの_document.tsx
でいう<Main />
ですね。src/routes
配下の各ページのコンポーネントです。
おまけ
ちなみにstyled-component
のような、サーバー側でcssをあらかじめ書き出しておく必要がある場合、solid-js/web
の<Assets />
を使うと便利です。
export default function Root() {
return (
<Html lang="en">
<Head>
<Title>SolidStart - Bare</Title>
<Meta charset="utf-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1" />
+ <Assets>
+ {/* この時点では`extractCss`は呼び出されない */}
+ <style id="_goober" innerHTML={extractCss()} />
+ </Assets>
</Head>
<Body>
<Suspense>
<ErrorBoundary>
<a href="/">Index</a>
<a href="/about">About</a>
<Routes>
<FileRoutes />
</Routes>
</ErrorBoundary>
</Suspense>
<Scripts />
</Body>
</Html>
);
}
<Assets />
のドキュメントが見当たらなかったので正しい仕様は理解できていないのですが、これを使用するとHtml内のコンポーネントがすべてレンダリングされてから一番最後に<Assets />
の内部がレンダリングされます。
どなたか詳しい方いたら教えてほしいです;;
routeData
nextjsでいうgetServerSideProps
的な奴です。サーバー側で処理されます。
import { useRouteData } from "@solidjs/router";
import { createServerAction$, createServerData$, redirect } from "solid-start/server";
import { getUser, logout } from "~/db/session";
export function routeData() {
return createServerData$(async (_, { request }) => {
const user = await getUser(request);
if (!user) {
throw redirect("/login");
}
return user;
});
}
export default function Home() {
const user = useRouteData<typeof routeData>();
const [, { Form }] = createServerAction$((f: FormData, { request }) => logout(request));
return (
<main class="w-full p-4 space-y-2">
<h1 class="font-bold text-3xl">Hello {user()?.username}</h1>
<h3 class="font-bold text-xl">Message board</h3>
<Form>
<button name="logout" type="submit">
Logout
</button>
</Form>
</main>
);
}
routeData
関数内はサーバー側で実行され、useRouteData
を使って返り値を取得できます。
Dynamic Routes
nextjsのDynamic Routesとほぼ同じです。
たとえば
import { useParams } from "solid-start";
const Post = () => {
const params = useParams()
return <p>Post: {params.pid}</p>
}
export default Post
こんなのを作って、/pid/1
にアクセスすると...
みたいになります。
まとめ
先日0.1.0がリリースされたので、ちょっとまとめてみました。
まだまだ開発段階ですので、今後もっと良くなっていく思うと、とても楽しみです。
Solidjsたのしい!!!!!
Discussion