SSR 用のコンポーネント集約エンドポイントを追加

shoelace-style/webawesome

Web Awesome に dist/ssr/all.js エンドポイントが新たに導入され、サーバーサイドでのコンポーネント一括インポートが容易になりました。

背景

サーバーサイドレンダリング(SSR)において、個別コンポーネントを逐次インポートする手間とバンドルサイズの増大が課題でした。既存のクライアント向けエクスポートは軽量化が目的で、サーバ側で全部を読み込むケースを想定していませんでした。今回の PR では、SSR 用に /ssr プレフィックスでエンドポイントを明示し、サーバー側のみが利用すべきことを文書化しています。これにより、開発者はクライアントとサーバーでインポート戦略を明確に分離できます。

技術的な変更

packages/webawesome/scripts/build.jsgenerateAllComponentFile ステップが追加され、ビルドフローの steps 配列に組み込まれました。ステップは cleanupgenerateManifestgenerateAllComponentFilegenerateReactWrappers…と続き、SKIP_SLOW_STEPS 環境変数でスキップ可能です。スピナーで進行状況を表示し、スキップ時には情報メッセージを出す実装となっています。

@@
-      const steps = [cleanup, generateManifest, generateReactWrappers, generateTypes, generateStyles];
+      const steps = [
+        cleanup,
+        generateManifest,
+        generateAllComponentFile,
+        generateReactWrappers,
+        generateTypes,
+        generateStyles,
+      ];

generateAllComponentFile 関数 は新規に導入された make-all.js を呼び出し、ssr/all.js(実際は TypeScript の all.ts)を生成します。関数内部では process.env.SKIP_SLOW_STEPS による早期リターンと、execSyncmake-all.js --outdir を実行するロジックが実装されています。

function generateAllComponentFile() {
  if (process.env.SKIP_SLOW_STEPS === 'true') {
    spinner.info('Skipping "ssr/all.js" file generation.');
    return Promise.resolve();
  }

  spinner.start('Generating "ssr/all.js" file');
  try {
    execSync(`node ${join(__dirname, 'make-all.js')} --outdir "${getCdnDir()}"`, { stdio: 'inherit' });
  } catch (error) {
    // error handling omitted for brevity
  }
}

packages/webawesome/scripts/make-all.js は新規追加されたスクリプトで、custom-elements.json から全コンポーネントメタデータを取得し、src/ssr/all.ts にエクスポート文を自動生成します。生成前に既存ファイルを削除し、prettier でフォーマットした上で書き出すことで、コード整形と一貫性を保ちます。

const allFile = path.join(process.env.ROOT_DIR || '.', 'src', 'ssr', 'all.ts');
deleteSync(allFile);
const metadata = JSON.parse(fs.readFileSync(path.join(outdir, 'custom-elements.json'), 'utf8'));
const components = getAllComponents(metadata);
const index = [];
components.sort((a, b) => a.tagName.localeCompare(b.tagName));
for (const component of components) {
  if (!component.tagName) continue;
  const tagWithoutPrefix = component.tagName.replace(/^wa-/, '');
  index.push(`export { default as ${component.name} } from '../components/${tagWithoutPrefix}/${tagWithoutPrefix}.js';`);
}
let text = `// This file is auto-generated. Do not edit it directly.\n` + index.join('\n');
text = await prettier.format(text, { ...prettierConfig, parser: 'babel-ts' });
fs.writeFileSync(allFile, text, 'utf8');

packages/webawesome/src/ssr/all.ts は自動生成されたファイルで、各コンポーネントを名前付きエクスポートとしてまとめています。例として WaButtonWaAccordion などが列挙され、サーバー側で import * as Wa from 'dist/ssr/all.js' のように一括取得できます。ファイル冒頭に自動生成コメントが入っており、手動編集は推奨されません。

// This file is auto-generated. Do not edit it directly.
export { default as WaAccordionItem } from '../components/accordion-item/accordion-item.js';
export { default as WaButton } from '../components/button/button.js';
export { default as WaCard } from '../components/card/card.js';
// ...(以下同様に全コンポーネントがエクスポートされる)

packages/webawesome/docs/docs/resources/changelog.md には、dist/ssr/all.js エンドポイントが追加された旨が追記され、エンドポイントがサーバー向けであることが明示されています。この変更はドキュメントにも反映され、利用者が新機能をすぐに把握できるようになっています。

設計判断

SSR 用エンドポイントを /ssr に限定した設計は、クライアントバンドルへの負荷増大を防ぎつつ、サーバー側でのコンポーネント一括取得をシンプルにする意図が読み取れます。ビルドプロセスにスキップ可能なステップを導入し、CI 環境でのビルド時間を最適化できる点も設計上の配慮です。既存のクライアント向けエクスポート構造を変更せず、generateAllComponentFile のみを追加したことで後方互換性を保ちつつ新機能を提供しています。

まとめ

dist/ssr/all.js エンドポイントの追加により、Web Awesome の SSR 連携が格段に簡便化されました。ビルドスクリプトの拡張、メタデータ駆動の自動生成スクリプト、そしてドキュメントへの記載という三位一体の改修により、開発者はサーバー側で必要なコンポーネントを一括インポートでき、クライアントバンドルへの影響を回避できます。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
c0531db7

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的変更、設計判断(任意)およびまとめがすべて揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ⚠ WARNING

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックはファイル名付きシンタックスハイライトが正しく使用されていますが、PRへのリンクが "[PR #2520](URL)" となっており、仕様の "[#2520](URL)" 形式になっていません。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

専門的なエンジニア向けの記述で、余計な初心者向け説明はなく適切です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論パラグラフ、各論パラグラフ、結論パラグラフで構成され、トピックセンテンスが先頭にあり、1段落1トピック・適切な長さが保たれています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事中のコードブロックは Diff に記載された変更と一致しており、抜粋や省略も内容理解に支障がありません。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

SSR、generateAllComponentFile、make-all.js などの用語が正確に使用され、PR の記述と整合しています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

技術的な説明は Diff と PR 内容に基づき正確で、因果関係も論理的です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事のすべての主張は PR の情報で裏付けられており、推測や捏造は見られません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR 番号 #2520 や環境変数名など、数値・固有名詞は正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルは PR の内容(SSR 用の all.js エンドポイント追加)を適切に要約しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

バージョンサポートやリリース日程など、PR に記載のない外部情報は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現の歪曲はなく、PR の記述と一致しています。