mcpField
F
frontend-async-best-practices

frontend-async-best-practices

github.com/sergiodxa開発92224 回インストール38 週間前に更新
リポジトリ

frontend-async-best-practices について

データ取得コードを書く開発者向けの、JavaScript 非同期処理のパフォーマンス指針です。リクエストのウォーターフォールを減らし、並列性を高める 5 つのルールをまとめています。

主な機能

  1. 01Promise.all() による独立処理の並列化
  2. 02結果が必要になるまで await を遅らせる
  3. 03依存関係のある処理を効率よく連鎖
  4. 04API ルートで Promise を早期に開始
  5. 05データ読み込み中に Suspense で描画

活用シーン

  1. 01非同期コードの逐次リクエストをレビュー
  2. 02Remix loaders と actions のデータ取得を最適化
  3. 03複数の非同期処理の応答時間を改善

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sergiodxa/agent-skills --skill frontend-async-best-practices

インストール後、Claude Code で/frontend-async-best-practicesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

rules/
api-routes.md
defer-await.md
dependencies.md
parallel.md
suspense-boundaries.md

詳細

非同期処理のベストプラクティス

非同期 JavaScript コードのパフォーマンス最適化パターンです。リクエストのウォーターフォールを解消し、並列性を最大限に高めることに重点を置いた 5 つのルールを紹介します。

影響度:重大 — ウォーターフォールはパフォーマンス低下の最大の原因です。逐次的な await を追加するたびに、ネットワーク遅延がそのまま加算されます。

適用する場面

次の場合に、これらのガイドラインを参照してください。

  • Remix のローダーまたはアクションを作成するとき
  • データ取得ロジックを実装するとき
  • 複数の非同期処理を扱うとき
  • ウォーターフォールパターンがないかコードをレビューするとき
  • 応答時間を最適化するとき

ルールの概要

parallel(重大)— @rules/parallel.md

独立した処理には Promise.all() を使用します。

// Bad: 3 sequential round trips
const user = await fetchUser();
const posts = await fetchPosts();
const comments = await fetchComments();

// Good: 1 parallel round trip
const [user, posts, comments] = await Promise.all([
  fetchUser(),
  fetchPosts(),
  fetchComments(),
]);
defer-await(高)— @rules/defer-await.md

実際に使用する分岐内に await を移動します。

// Bad: always waits even when skipping
async function handle(skip: boolean) {
  let data = await fetchData();
  if (skip) return { skipped: true };
  return process(data);
}

// Good: only waits when needed
async function handle(skip: boolean) {
  if (skip) return { skipped: true };
  let data = await fetchData();
  return process(data);
}
dependencies(重大)— @rules/dependencies.md

依存する処理は順につなぎ、独立した処理は並列化します。

// Bad: profile waits for config unnecessarily
const [user, config] = await Promise.all([fetchUser(), fetchConfig()]);
const profile = await fetchProfile(user.id);

// Good: profile starts as soon as user resolves
const userPromise = fetchUser();
const profilePromise = userPromise.then((user) => fetchProfile(user.id));

const [user, config, profile] = await Promise.all([
  userPromise,
  fetchConfig(),
  profilePromise,
]);
api-routes(重大)— @rules/api-routes.md

ローダーでは早めに Promise を開始し、await は最後に行います。

// Bad: sequential execution
export async function loader() {
  let session = await auth();
  let config = await fetchConfig();
  return { session, config };
}

// Good: parallel execution
export async function loader() {
  let sessionPromise = auth();
  let configPromise = fetchConfig();
  const [session, config] = await Promise.all([sessionPromise, configPromise]);
  return { session, config };
}
suspense-boundaries(高)— @rules/suspense-boundaries.md

データの読み込み中に UI をすぐ表示するには、Suspense を使用します。

// Bad: entire page blocked by data
async function Page() {
  let data = await fetchData();
  return (
    <Layout>
      <Content data={data} />
    </Layout>
  );
}

// Good: layout shows immediately, content streams in
function Page() {
  return (
    <Layout>
      <Suspense fallback={<Skeleton />}>
        <Content />
      </Suspense>
    </Layout>
  );
}

コメント