👩‍🎤

SvelteKitと@emotion/cssでSSRする

2024/01/09に公開

svelteKit使ってプロダクト開発していて、css-in-jsを使いたく、@emotionを採用しましたが、Reactと違って、sveltekitとの使い方に関しての情報があまりなかったので、書き残しておきたいと思います。

ソースコードを読みながら、見つけたやり方なので、他にスマートなやり方あるよという方がいたら、教えてください🙇‍♂️

流れ

@emotion/serverパッケージの👇extractcriticalを使い、静的なCSSを生成し、サーバーから生成される文字列のHTMLレスポンスのHeadタグ内にインジェクションします。

https://emotion.sh/docs/ssr#extractcritical

実装

reactの場合はreact-dom/serverからrenderToStringを使ってjsxをhtml文字列に変換することができますが、svelteの場合はそもそもコンセプトが違うので、やり方がかなり違う気がしました。

ただ、sveltekitの場合はhooksが用意されています。

'Hooks' are app-wide functions you declare that SvelteKit will call in response to specific events, giving you fine-grained control over the framework's behaviour.
「フック」とは、SvelteKitが特定のイベントに応答して呼び出すアプリ全体の関数であり、フレームワークの動作を細かく制御できます。

remixでいうと、entry.server.tsxと似ているのかもしれません。

server.hooks.ts
import type { Handle } from '@sveltejs/kit';
import { extractCritical } from '@emotion/server';

export const handle: Handle = async ({ event, resolve }) => {
	const response = await resolve(event, {
		transformPageChunk({ html, done }) {
			const { html: emotionHtml, css, ids } = extractCritical(html);
			if (done) {
				return emotionHtml.replace(
					'</head>',
					`<style data-emotion-css="${ids.join(' ')}">${css}</style></head>`
				);
			}
		}
	});
	return response;
};

以上です。

Discussion