6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SolidStart v1.0】ついにSolidJSでフルスタック開発!

Last updated at Posted at 2024-07-01

はじめに

待ちに待ったSolidJSのレンダリングフレームワークであるSolidStartのバージョン1.0がリリースされました!
SolidStart 1.0: The Shape of Frameworks to Come
本記事では実際に使ってみた感じから、SolidStartの特徴や使い方について紹介します。

SolidJSとは

SolidJSは、Reactに似た書き方で、Reactよりも高速なレンダリングを実現するフレームワークです。SolidJSは過去にも記事で取り上げたのでこちらを参考にしてください。

ポイントとしては、以下の通りです。

  • Reactに近い書き方
  • Reactに近い標準機能(lazy, ref, Portal, Suspenseなど)
  • 状態に応じて直接DOMを更新することによる高パフォーマンス

SolidStartとは

ReactでいうNext.jsのような、SolidJSにサーバーサイドレンダリングやファイルベースルーティングを提供するためのメタフレームワークがSolidStartです。SolidJSの開発者でもあるRyan Carniato氏が開発したフレームワークです。長らくベータ版として開発がされてきましたが、この度晴れて正式版(v1.0)がリリースされました。SolidJS単体での開発と違って、どんなことができるのかをここでは紹介できればと思います。

SolidStartメリット

フルスタック開発

SolidStartの最大の利点はSolidJSを使ってフルスタックな開発が可能になったことです。SolidJSはReactと比較してもパフォーマンスなどの点で様々なメリットがありますが、メタフレームワークが存在しないことがSolidJSを採用しない一つの理由になっていました。SolidJS単体でWEBアプリを作る際には、

  • バックエンドの開発には別途ExpressやFastifyなどのフレームワークが必要
  • SPA(シングルページアプリケーション)しか作れない(※)

などのデメリットがあります。SolidStartの登場により、SolidJSでフルスタック開発が可能になり、フロントエンドとバックエンドの統合が容易になり、レンダリングについてもCSR/SSR/SSGという選択肢が増えました。

※本筋からは少し脱線しますが、SolidJS単体でもhydrate APIを使うことでSSRっぽいものを作ることは可能です。

import { hydrate } from 'solid-js/web';
import App from './App';

import './index.css';

// entry point for browser
hydrate(() => <App />, document);

ただし、この方法ではHMRができなかったり設定が複雑になったりするため、SolidStartの登場の意味は大きいです。

開発体験とパフォーマンスの良さ

SolidStartSolidJS単体や他のフレームワークよりも開発体験やパフォーマンスが良くなるように設計されています。

ファイルベースルーティング

これはNext.jsなどでもお馴染みですが、SolidStartではファイルベースルーティングを行うことが可能です。これはページを追加するたびにルーティングの処理を追加しなくても、routes配下のファイルが自動的にページとして認識される仕組みです。ページをネストしたり、[id].tsxとすることでIDなどのパラメータとして扱う動的なルーティングも可能です。

バックエンド処理についてもファイルベースルーティングを採用しており、routes/api配下に以下のようなファイルを記述することでAPIを簡単に作成することが可能です。

export function GET() {
  // ...
}

export function POST() {
  // ...
}

export function PATCH() {
  // ...
}

export function DELETE() {
  // ...
}

参照元: SolidStart公式ドキュメント

Single-Flight Mutations

これはページのHTMLとデータを同時に配信する機能です。例えば、一覧ページから詳細ページに移動する際に、コード分割したSPAでは、

  • 新しいページのHTML(JavaScript、CSS)
  • ページの詳細情報

の二つのリクエストがサーバーから返却される必要があります。SolidStartでは、これを一つのリクエストにまとめて返却してくれます。これにより通信量が最小限で済み、ページが表示されるまでの時間も短縮されます。

Data Loading

フルスタック開発の利点の一つとして、SolidStartでは本来サーバーで処理するような内容も同じコンポーネントのファイルに記述することが可能です。以下の例ではサーバーからユーザーの一覧を取得し、その情報を画面に反映するという処理が一つのファイルでなされています。ここで重要なのが、use serverというコメントで、この記述がある関数はクライアントサイドのソースには展開されません。これにより安全に、バックエンドとフロントエンドの処理を同時に記述することが可能になり開発体験が良くなります。

import { For } from "solid-js";
import { createAsync, cache } from "@solidjs/router";

type User = { name: string; email: string };

const getUsers = cache(async () => {
  "use server";
  return store.users.list();
}, "users");

export const route = {
  load: () => getUsers(),
};

export default function Page() {
  const users = createAsync(() => getUsers());

  return <For each={users()}>{(user) => <li>{user.name}</li>}</For>;
}

参照元: SolidStart公式ドキュメント

またClientOnlyというコンポーネントを使うことで、クライアントサイドのみで処理を行うことも可能です。DOM操作などを行う際にはこちらを使います。

import { clientOnly } from "@solidjs/start";

const ClientOnlyComp = clientOnly(() => import("../ClientOnlyComp"));

function IsomorphicComp() {
  return <ClientOnlyComp />;
}

参照元: SolidStart公式ドキュメント

テンプレート

SolidStartでは簡単に開発が始められるように、テンプレートを複数提供しています。
image.png
参照元: SolidStart公式ドキュメント

TailwindやVitestなどのモジュールが既に組み込まれた状態で開発を始めることができます。(欲を言うと、このテンプレートが複数選択できるようになるともっと良いかもしれません。)

その他

これ以外にもHMR(ホットモジュールリプレースメント)やPreloadなど、メタフレームワークとして基礎的な機能も備わっています。

柔軟性

SolidStartはパフォーマンスが良いだけでなく、柔軟な設定が可能になります。SolidStartは以下のモジュールを組み合わせて構成されています。

image.png
参照元: SolidStart公式ドキュメント

  • Vinxi: Viteを基盤としたバンドラーおよびサーバーランタイムで、開発環境とビルドプロセスをシンプルにします。
  • Vite: 高速な開発サーバーとビルドツールで、リアルタイムのホットモジュールリプレースメント(HMR)を提供します。
  • Nitro: サーバーAPIおよびプリセットを提供し、Cloudflare、Netlify、Vercelなどのプラットフォームに簡単にデプロイできます。
  • Solid Router: 公式ルーターで、簡単にルーティングを設定できます。

SolidStartではこれらのモジュールに対して設定を行うことで、開発環境やビルドプロセスをカスタマイズすることが可能です。

Vite

以下の方法でビルド時にプラグインなどを読み込ませることが可能です。

import { defineConfig } from "@solidjs/start/config";

export default defineConfig({
  vite: {
    // Vite options
    plugins: [],
  },
});

参照元: SolidStart公式ドキュメント

Nitro

任意のデプロイ先にデプロイすることが可能です。SolidStartからは標準で、Netlify、Vercel、Cloudflareなどのプラットフォームにデプロイするためのプリセットが提供されています。

import { defineConfig } from "@solidjs/start/config";

export default defineConfig({
  server: {
    preset: "netlify_edge",
  },
});

参照元: SolidStart公式ドキュメント

APIフレームワーク統合

SolidStartではファイルベースのAPIルーティングだけでなく、tRPCGraphQLなどのAPIフレームワークを組み込むことも可能になっています。

import { type APIEvent } from "solid-start/api";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import { appRouter } from "~/lib/router";

const handler = (event: APIEvent) =>
  fetchRequestHandler({
    endpoint: "/api/trpc",
    req: event.request,
    router: appRouter,
    createContext: () => ({})
  });

export const GET = handler;

export const POST = handler;

参照元: SolidStart公式ドキュメント

その他

その他にもHTMLのメタデータやルーティングの方法(ファイルルーティング以外)なども柔軟に設定が可能です。

SolidStartのデメリット

SolidStartはまだリリースされたばかりで、各面において足りていない要素が多い印象です。

  • GitHubのIssueが多い
  • 公式ドキュメントが分かりづらい
  • エコシステムが小さいため周辺ライブラリなどは少ない
  • Next.jsのような成熟したフレームワークと比較すると機能が足りない
    • next/image

さいごに

Next.jsがゼロコンフィグをうたっているのに対して、SolidStartは柔軟な設定こそが強みだと感じました。
テンプレートやプリセットを使うことで設定に必要な工数を最小限に抑えつつ、プロジェクトに合わせて柔軟に構築することが可能です。
まだまだ課題もありますが、正式版ということで実用に向けての機能は十分だと思いました。
是非次のプロジェクトの選択肢としてSolidJS/SolidStartを検討してみてください。

参考

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?