lit-render-string の再取得でビルド破損を修正
ビルドプロセスで lit-render-string が正しく更新されず、Konnor が導入した変更でビルドが失敗するケースが発生していました。本修正はビルド完了後にモジュールを動的に再インポートし、最新の renderString 関数を取得することで問題を解消します。
背景
ビルドスクリプトは SSR 用の render-string.js を一度だけインポートし、以後その関数を保持していました。litRenderString はモジュール読み込み時に固定され、ビルドが再実行されても再取得されません。この挙動は生成物が変更された場合に古い実装が残り、実行時エラーを引き起こすリスクがあります。
Konnor が導入した変更により、render-string.js の出力がビルドごとに更新されるようになりました。ビルドが成功した後でも、スクリプトは旧バージョンの renderString を参照し続けます。結果として、SSR の出力が期待と乖離し、CI でのビルド失敗が観測されました。
したがって、ビルドプロセス全体の信頼性を確保するためには、最新のモジュールを毎回取得する必要があります。この要件を満たすには、インポート時にモジュールキャッシュをバイパスする手法が有効です。そこで本PRでは動的インポートとキャッシュバストを組み合わせた実装が選択されました。
技術的な変更
修正では litRenderString をデフォルトで単純パススルー関数として宣言し、ビルド完了後に上書きできるようにしました。この変数はスクリプト全体で使用され、SSR のレンダリングロジックに渡されます。宣言だけで動作に影響はなく、後続の動的再インポートに備える形となります。
let litRenderString = str => str;
let litRenderString = str => str; をファイル冒頭に追加しました。これにより、モジュールがまだ読み込まれていない段階でも関数呼び出しが安全に行えます。実際の実装はビルド成功時に差し替えられます。
ビルドが成功した後、spinner.succeed の直後で render-string.js をタイムスタンプ付きで再インポートし、litRenderString に最新の renderString を代入しています。?cachebust=${new Date().getTime()} クエリはモジュールキャッシュを回避し、常に新しいファイルが取得されます。この処理はビルドが失敗した場合には実行されず、エラーハンドリングに影響を与えません。
const mod = await import(`../dist/ssr/render-string.js?cachebust=${new Date().getTime()}`);
litRenderString = mod.renderString;
以前は ../dist/ssr/render-string.js を静的にインポートし、litRenderString を即座に取得していました。const { renderString: litRenderString } = await import('../dist/ssr/render-string.js'); の行を削除し、動的取得へ統一しました。これにより、モジュールがビルドごとに変化しても常に最新実装が使用されます。
以上の変更はスクリプトのロジックを大幅に変更せず、インポートタイミングのみを調整した点に留めています。ビルドフローや他の機能への副作用は報告されていません。結果として、Konnor が導入した変更に起因するビルド破損が解消されました。
設計判断
設計上はビルドごとに SSR 用レンダリング関数を再取得する方針が採られました。静的インポートではモジュールキャッシュが残り、生成物の差分が反映されません。動的インポートに切り替えることで、ビルドのたびに最新コードを確実に使用できます。
キャッシュバストとしてタイムスタンプクエリを付与する実装は、Node の ES モジュールローダがクエリ違いを別モジュールと見なす挙動を利用しています。この手法は追加の依存や設定変更を必要とせず、シンプルにキャッシュ回避が可能です。代替案として import.meta.resolve やモジュールキャッシュの手動削除が検討されましたが、コード可読性と安全性の観点から採用されませんでした。
動的再インポートは若干のオーバーヘッドを伴いますが、ビルド信頼性の向上という利益が上回ります。インポートはビルド成功時に1回だけ実行されるため、全体の処理時間への影響は最小です。設計者は信頼性を最優先し、実装の簡潔さを保つ選択を行いました。
まとめ
本修正により、render-string.js の変更がビルドプロセスに即座に反映され、Konnor が引き起こしたビルド破損が解消されます。動的インポートとキャッシュバストの組み合わせは、生成物が頻繁に変わる環境での安全なモジュール取得手段として有効です。今後も同様のパターンでモジュール更新が必要な箇所に適用すれば、ビルドの堅牢性を維持できるでしょう