👩🎤
SvelteKitと@emotion/cssでSSRする
svelteKit使ってプロダクト開発していて、css-in-jsを使いたく、@emotionを採用しましたが、Reactと違って、sveltekitとの使い方に関しての情報があまりなかったので、書き残しておきたいと思います。
ソースコードを読みながら、見つけたやり方なので、他にスマートなやり方あるよという方がいたら、教えてください🙇♂️
流れ
@emotion/server
パッケージの👇extractcritical
を使い、静的なCSSを生成し、サーバーから生成される文字列のHTMLレスポンスのHeadタグ内にインジェクションします。
実装
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