4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Svelte 5.44.0の新機能hydratableを試してみた - SSRのデータ取得を半分にする

4
Last updated at Posted at 2025-12-19

概要

2025年12月、Svelte 5.44.0でhydratableという新しいAPIがリリースされました。

サーバーで取得したデータをクライアントでも再利用できるようにする機能です。

実際どれくらい効果があるんだろう?と思い、比較デモを作って試してみた記事です。

結論(先に知りたい方へ)

この機能を使うと以下のメリットがあります

  • サーバーで取得したデータをクライアントで再利用できる
  • データ取得の二重実行を防げる
  • 2回実行が1回で済むため、単純計算で時間が半分になる

1行の変更で実現できるので、SSRを使っているSvelteプロジェクトなら試してみる価値がありそうです。

実験用のデモ

効果を比較するため2つのページを作りました。

  • hydratableなし(これまでと同様)
  • hydratableあり(最適化済み)

なお、このデモではAPI呼び出しをsetTimeoutで再現しており、実際のネットワークリクエストではありません。
効果を分かりやすくするため、意図的に2秒の遅延を設定しています。

何が問題なのか

SSRでは、サーバーでHTMLを生成し、クライアント側でJavaScriptを実行してインタラクティブにするHydrationという処理が行われます。

これまでの実装だと以下のようになります。

<script>
  import { onMount } from 'svelte';

  // 非同期データ取得
  async function fetchUserData() {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    return {
      name: 'Tanaka Taro',
      email: 'tanaka@example.com',
      lastLogin: new Date().toLocaleString('ja-JP')
    };
  }

  // 🚨 問題: awaitを使うと、サーバーとクライアントの両方で実行される
  const userData = await fetchUserData();
</script>

<h1>{userData.name}</h1>

この実装の問題点

  1. サーバーでfetchUserData()を実行(2秒)
  2. HTMLが生成されブラウザに送信される
  3. ブラウザでHydration開始時に再度fetchUserData()を実行(さらに2秒)
  4. 合計4秒以上かかり、Hydrationがブロックされる

ユーザーは約4秒間待たされ、その間ボタンのクリックやフォーム入力などのインタラクションができません。

DevToolsで問題を確認する

実際にブラウザの開発者ツールで確認してみましょう。

Consoleでの確認

デモサイトの「hydratableなし」のページを開き、DevToolsのConsoleタブを見ると、以下のようなログが表示されます。

[🖥️ サーバー] コンポーネント初期化開始
[🖥️ サーバー] fetchUserData() 開始
[🖥️ サーバー] fetchUserData() 完了 (2.00秒)
[🖥️ クライアント] コンポーネント初期化開始
[🖥️ クライアント] fetchUserData() 開始
[🖥️ クライアント] fetchUserData() 完了 (2.00秒)
[🖥️ クライアント] onMount実行 - Hydration完了!
[🖥️ クライアント] 合計時間: 4.02秒

サーバーとクライアントの両方でfetchUserData()が実行されているのが分かります。

Performanceでの確認

DevToolsのPerformanceタブで記録すると、クライアント側でのデータ取得がメインスレッドをブロックし、Hydrationが遅延している様子が確認できます。

解決策: hydratableの導入

Svelte 5のhydratableを使うと、この問題を解決できます。

<script>
  import { hydratable } from 'svelte';

  async function fetchUserData() {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    return {
      name: 'Tanaka Taro',
      email: 'tanaka@example.com',
      lastLogin: new Date().toLocaleString('ja-JP')
    };
  }

  // ✅ 解決策: hydratableを使う
  const userData = await hydratable('user-data', () => fetchUserData());
</script>

<h1>{userData.name}</h1>

1行だけの変更ですが、動作が大きく変わります。

hydratableの仕組み

  1. サーバーでfetchUserData()を実行(2秒)
  2. データがシリアライズされ、HTMLの<head>タグ内に埋め込まれる
  3. ブラウザでHydration開始時、埋め込まれたデータを即座に読み込む(0秒)
  4. 合計2秒のみ、Hydrationをブロックしない

DevToolsで改善を確認する

「hydratableあり」のページでConsoleを見ると、以下のようになります。

[🖥️ サーバー] コンポーネント初期化開始
[🖥️ サーバー] fetchUserData() 開始
[🖥️ サーバー] fetchUserData() 完了 (2.00秒)
[🖥️ クライアント] コンポーネント初期化開始
[🖥️ クライアント] hydratable完了、データ取得済み (キャッシュから即座に読み込み)
[🖥️ クライアント] onMount実行 - Hydration完了!
[🖥️ クライアント] 合計時間: 2.01秒

クライアント側でのデータ取得がスキップされ、約2秒で完了しています。

デザイナー・フロントエンドエンジニアの視点での価値

ユーザー体験への直接的な影響

2回の実行が1回で済むため、ページが早くインタラクティブになり、クリックやタップへの応答が即座に可能になります。

特に低速なモバイルネットワーク環境では、ネットワークリクエストの削減による効果が大きく、ユーザーの離脱率低下につながります。

ローディング状態などを最小化できる

Hydrationが高速化されることで、ローディングスピナーやスケルトンスクリーンの表示時間を短縮できます。

Core Web Vitalsへの影響

TTI(Time to Interactive)が改善されるため、Interaction to Next Paint(INP)などのCore Web Vitals指標にも良い影響を与える可能性があります。

実装時の注意点

一意なキーの使用

// 良い例
const userData = await hydratable('user-data', () => fetchUserData());

// 悪い例: 他のコンポーネントと重複する可能性
const userData = await hydratable('data', () => fetchUserData());

hydratableの第一引数のキーは一意である必要があります。
ライブラリを作成する場合は、ライブラリ名をプレフィックスとして使用してください。

// ライブラリでの使用例
const userData = await hydratable('my-lib:user-data', () => fetchUserData());

実験的機能の有効化

Svelte 5では、コンポーネントのトップレベルでawaitを使う機能は実験的な機能のため、svelte.config.jsで明示的に有効化する必要があります。

svelte.config.js
export default {
  compilerOptions: {
    experimental: {
      async: true
    }
  },
  kit: {
    adapter: adapter()
  }
};

シリアライズ可能なデータ

hydratableで扱うデータは、JSONシリアライズ可能である必要があります。
関数やDOMノードなどは含めないようにしましょう。

// ✅ OK
return {
  name: 'Tanaka Taro',
  email: 'tanaka@example.com',
  lastLogin: new Date().toISOString()
};

// ❌ NG: 関数は含められない
return {
  name: 'Tanaka Taro',
  greet: () => console.log('Hello')
};

まとめ

2025年12月にリリースされたSvelte 5.44.0のhydratableを実験してみました。

1行だけの変更でSSRにおけるデータ取得を最適化でき、2回実行が1回で済むためHydration時間が半分になることが確認できました。

実験を通じて分かったこと

  • SSRでは同じデータ取得が二重に実行される問題がある
  • hydratableを使うとサーバーのデータをクライアントで再利用できる
  • DevToolsで実行順序とタイミングを確認できる

hydratableは簡単に導入できるので、SSRを使っているプロジェクトで試してみる価値がありそうです。

参考リンク

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?