TECHNICAL ARTICLE / PWA & PERFORMANCE

BuildレスPure Static Webアプリにおける Service Worker キャッシュと相対パス設計

Vite や Webpack 等のバンドラーを使用せず、標準の HTML5 / CSS3 / Native ES Modules のみで構成された Pure Static アプリ(BorderLens 等)において、GitHub Pages サブパスとルートドメイン環境で完全なオフラインキャッシュと自動更新を両立させた開発ノート。


1. 背景と課題 (Problem)

渡航制限・危険情報・ビザ要件を可視化する静的アプリ BorderLens の開発において、開発の軽量化と長期的なメンテナンス性を維持するため、TypeScript やビルドステップを一切挟まない Pure Static HTML/ES Modules 構成 を採用しました。

しかし、Service Worker(PWA オフライン対応)を導入する際、以下の課題に突き当たりました。

2. 解決アプローチと相対パスの統一 (Architecture & Implementation)

① 100% 相対パス (./) の徹底

Service Worker のアセット定義リスト(キャッシュマニフェスト)および ES Modules の `import` 文において、先頭の `/` を排除し、すべて ./ から始まる相対パスで静的アセット(全 45 ファイル)を指定しました。

// sw.js 内のキャッシュ対象リスト定義
const CACHE_NAME = 'borderlens-v1.0.4';
const ASSETS_TO_CACHE = [
  './',
  './index.html',
  './404.html',
  './styles.css',
  './src/pages/MainApp.js',
  './src/services/dataStore.js',
  './src/data/countries.json',
  './src/data/official-portals.json',
  './src/data/visa-rules.json'
];

// install イベントでのアセット一括追加
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      return cache.addAll(ASSETS_TO_CACHE);
    })
  );
  self.skipWaiting();
});

② Python による Pre-flight 自動検証スクリプト

手動でのファイル追加忘れやパス間違いを防止するため、デプロイ前に python3 scripts/verify_build.py を実行する事前検証パイプラインを構築しました。全 JSON の構文チェック、ES Modules の依存関係テスト、および sw.js にリストされた全アセットの実ファイル存在チェックを自動実行します。

# verify_build.py からの抜粋(アセット自動整合性アサート)
for asset_path in sw_cache_assets:
    local_path = asset_path.lstrip('./')
    if not os.path.exists(local_path):
        print(f"❌ SW Cache Asset Missing: {asset_path}")
        sys.exit(1)
print("✅ ALL SERVICE WORKER ASSETS PASSED INTEGRITY CHECK!")

3. 得られた成果と結果 (Results)