React(Next.js)からSvelte(Sveltekit)に浮気するための参考まとめ
前書き(ボツ)
前書き
皆さんはUIフレームワーク、何を使っていますか?
どうせReactでしょうね。だってReactみんな使ってますもんね。私もです。仕事でもReactです
Next.js、便利ですもんね。すごくわかります。
私も「駆け出し園児ニア」の頃Next.jsを触ったときにpagesフォルダ配下のファイルパスの構造がそのままurlのpathになるのに感動したものです。
ただ最近、特にNext.js v13から出現してきたApp Routerが発表された後の諸々の新規機能の発表があったりしてからキャッチアップしていくのがしんどくなって来てしまいました。具体的には
React Server Components
Server Actions
Async Component
あたりですかね。これらの出現でReactの設計事情がこれまでとは根本的に変わってくるだろう。という界隈の空気感を感じております。
私もこれらのパラダイムの出現による設計事情を悶々と考えていたのですが。もう、疲れちゃいました。
便利な道具としてのフレームワークがどんどん複雑になってきて、私が好きだった頃の彼がどんどん遠くに行ってしまった気がしたんです。
そんなときなんですよね、そんなときに彼が話しかけてきたんです
Svelte < ドシタン?話キコカ?
初めはちょっとした気の迷いだったんです。個人ブログを彼(Svelte)で構築することにしたんですよね。最初はReactとの書き方の違いに戸惑ったんですがReactの今後を考えて疲れた私の心を彼は優しく受け止めてくれたんです。
こちらに書いてあるように、彼は少ないコードで私が表現したいことを叶えてくれるんですよね。
ごめんなさい。Reactさん。私はもう彼の、Svelteさんと一緒に生きていきます。仕事であなたを使ってプログラムを書くことは今後もあるし、別にあなたのことは嫌いじゃないんです。ただ私のプライベートはすべて彼に使わせてください。
何を話す?
React(Next.js)で書いてきた人たちがシームレスにSvelte(Sveltekit)に浮気移行するために、 「React,Next.jsでの機能、Svelte(Sveltekit)ではこう書けるよ」をつらつらとまとめていきます。基本的なそれぞれの機能に関しては解説はしませんが、いくつかサンプルコードをcodesandboxで書いたので参考にしてみてください。サンプルコードが書いていないやつに関しても、公式ドキュメントや他の人が書いてくれたREPLなんかを載せていきます。
個人的にはNext.jsやReactの機能の大部分は再現できるし、これで十分なんじゃない?と思っているので、Reactにつかれた皆さん、ぜひSvelte触ってみてください。
とりあえずSvelteのドキュメントおいておきます。ここで紹介している以外にも便利な機能はたくさんあるのでぜひ一度触ってみてください!
Svelte
Sveltekit※追記(2023-07-15)
フレームワークでの書き方を機能ごとに比較できるサイトとしてこんなサイトがあるのを見つけましたので、参考にどうぞ!
こちらのツイートで知りました
Reactの〇〇、Svelteだとこう書くよ
useState
react
svelte
<script>
let count = 0;
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
Clicked {count}
{count === 1 ? 'time' : 'times'}
</button>
useEffect
react
svelte
depsをトリガーとしてロジックを実行するようなやつ
componentのcleanup処理-> onDestoroy関数を使う
custom hook
react
/customhook ページに移動すると見れます
svelte
/customhook ページに移動すると見れます
custom hook (global state)
react(ライブラリとしてjotaiを入れてます)
/globalstate ページに移動するとみれます
svelte
/globalstate ページに移動するとみれます
データフェッチング
React
いくつかパターンがありますね
custom hook (swrを例に)
import useSWR from 'swr'
function Profile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
if (isLoading) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
Suspense
import { Suspense } from 'react';
import Albums from './Albums.js';
export default function ArtistPage({ artist }) {
return (
<>
<h1>{artist.name}</h1>
<Suspense fallback={<Loading />}>
<Albums artistId={artist.id} />
</Suspense>
</>
);
}
function Loading() {
return <h2>🌀 Loading...</h2>;
}
async component
async function getData() {
const res = await fetch('https://api.example.com/...')
// The return value is *not* serialized
// You can return Date, Map, Set, etc.
// Recommendation: handle errors
if (!res.ok) {
// This will activate the closest `error.js` Error Boundary
throw new Error('Failed to fetch data')
}
return res.json()
}
export default async function Page() {
const data = await getData()
return <main></main>
}
Svelte (おすすめ・超好き)
Svelteのこの書き心地がすごい好きです
<script>
const fetchImage = (async () => {
const response = await fetch('https://dog.ceo/api/breeds/image/random')
return await response.json()
})()
</script>
{#await fetchImage}
<p>...waiting</p>
{:then data}
<img src={data.message} alt="Dog image" />
{:catch error}
<p>An error occurred!</p>
{/await}
interface HogeProps extends FugaPropsみたいなやつ
これに関してはReactが圧勝ですね。。。
react
interface FugaProps {
email: string;
}
interface HogeProps extends FugaProps {
name: string;
}
const Component: FC<HogeProps> = ({email,name}) => {
return (
<>
<div>{name}</div>
<div>{email}</div>
</>
)
}
Svelte (つらい)
Svelteだとこれやるのができないんですよね・・・
ただRFC的にはまだ話合われているっぽいので今後出てくるんじゃないかなと思います。
Next.jsの〇〇、Sveltekitだとこう書くよ
setup
next.js
npx create-next-app@latest
sveltekit
npm create svelte@latest my-app
layout
next.js
/nestlayoutページに移動するとみれます
sveltekit
/nestlayoutページに移動するとみれます
Api Routes
next.js
import { serialize, CookieSerializeOptions } from 'cookie'
import { NextApiResponse } from 'next'
/**
* This sets `cookie` using the `res` object
*/
export const setCookie = (
res: NextApiResponse,
name: string,
value: unknown,
options: CookieSerializeOptions = {}
) => {
const stringValue =
typeof value === 'object' ? 'j:' + JSON.stringify(value) : String(value)
if (typeof options.maxAge === 'number') {
options.expires = new Date(Date.now() + options.maxAge * 1000)
}
res.setHeader('Set-Cookie', serialize(name, stringValue, options))
}
sveltekit
import { error } from '@sveltejs/kit';
/** @type {import('./$types').RequestHandler} */
export function GET({ url }) {
const min = Number(url.searchParams.get('min') ?? '0');
const max = Number(url.searchParams.get('max') ?? '1');
const d = max - min;
if (isNaN(d) || d < 0) {
throw error(400, 'min and max must be numbers, and min must be less than max');
}
const random = min + Math.random() * d;
return new Response(String(random));
}
その他
ライブラリ事情
Reactは言わずもがな、UIライブラリ、便利Hooksライブラリ、その他諸々便利ライブラリなんでもござれです。コミュニティの大きさは正義を体現しています。困ってることを調べるとだいたいそれを解決してくれるようなライブラリが見つかります。
Svelteもあるにはあるのですが、色々動かしてみた感じあまりこういうフレームワークにべったりのライブラリは選定しないほうがいいんじゃないかなっと思っています。UIライブラリならTailwindベースのHeadless UIだったりdaisy uiだったりを使うのがいいと思っています。それ以外でも、Javascript純正のライブラリだったりを主に導入するのがいいのかなと思ってます。
あとSvelteはSvelte自身でstoreだったりのモジュールがあったりするので、できる限りSvelteのモジュールだけでかけるように工夫していけるといいかなと思っています
UIフレームワーク
react
chakra-ui、mui、mantine
とりあえずここらへんのライブラリを使えばそれなりのクオリティのuiがパパってできます
svelte
個人的に使いやすかったのは
flowbite-svelte
daisy ui
くらいですかね
Svelteはフレームワーク側でアニメーションに関するモジュールが使えるようになってるので↑のライブラリプラスSvelteのモジュールで攻めていくのがいいのかな?って思っています
Component Test
reactもsvelteも testing-libraryが使えます。
Hosting
正直こちらは両者とも十分にサポートされてる感じです
next.js
Vercel様(言わずもがな)、Amplify(AWSのやつ)、Cloudflare Pages、Netlify
とりあえず大体のやつはデプロイできます
sveltekit
Svelte公式がサポートしてるのは
cloudflare pages
cloudflare workers
vercel
netlify
あとはSSG用、nodeサーバー用でアダプターが用意されてます。
終わりに
Reactの場合はライブラリをたくさん導入して大規模でリッチなアプリケーションを作っていく感じでSvelteの場合は標準機能 + ライブラリちょい足しで小規模 ~ 中規模なアプリケーションを作っていくのがいいのではないかな?って思っています。
Reactのパラダイムシフトの流れに疲れた皆さん、是非一度Svelteを触ってみてはいかがでしょうか?
以上です!
Discussion