起きる症状
distフォルダをZIPにするとき、フォルダごと圧縮してしまうとZIP内の構造がdist/index.htmlになります。ホスティングサービスはZIP直下のindex.htmlを探すため、distフォルダが1段挟まると「ページが見つかりません」と404エラーになります。Macのフォルダ右クリックや「zip -r dist.zip dist/」のようなコマンドはこの構造になりやすいため注意してください。
distフォルダの中身をZIPにしたつもりでも、ビルド設定のbaseパスが絶対URL(例: /app/)に設定されている場合、アセットのパスがドメイン依存になります。ギガサイト便のURLはランダムなサブドメインなので、絶対パスのアセットは読み込めずに画像やCSSが表示されません。ビルド前にbaseの設定を確認してください。
- 相手がログインなしで開ける状態か確認する
- PCとスマホで最低1回ずつ表示を確認する
- 内部情報・個人情報・不要な外部送信が残っていないか見る
- レビュー期限と修正時の差し替え方を決めておく
正しい構成
Viteプロジェクトの場合、npm run build 後に「cd dist && zip -r ../site.zip . && cd ..」を実行します。cdでdistフォルダに入ってから「.」(カレントディレクトリ)を圧縮するのがポイントで、これによりZIP直下にindex.htmlとアセットが配置されます。作成したsite.zipを「unzip -l site.zip | head」で確認し、1行目がindex.htmlかassetsフォルダであればOKです。
Create React Appではnpm run build後のbuildフォルダを使います。Viteと同様に「cd build && zip -r ../site.zip . && cd ..」で作成します。package.jsonのscriptsに「build:zip」コマンドを追加しておくと、毎回コマンドを打つ手間が省けて運用が楽になります。
- ZIP直下または指定階層にindex.htmlがあるか確認する
- 相対パスの画像・CSS・JSが同梱されているか見る
- 不要な隠しファイルや作業ファイルを除く
- 圧縮前のフォルダ名に日本語や空白を入れすぎない
圧縮前チェック
distフォルダに環境変数の機密情報が埋め込まれていないかを確認します。ViteはビルドにVITE_プレフィックスの環境変数を展開するため、APIキーなどの値がバンドルに含まれることがあります。distフォルダ内のアセットをテキスト検索し、機密情報が含まれている場合はその変数の使い方を見直してください。
distフォルダ内のファイル名とフォルダ名に日本語や特殊文字が含まれていないかも確認します。ビルドツールは通常英数字のハッシュ値をファイル名に付与しますが、元の画像ファイル名が日本語だとdistにも日本語名で出力されることがあります。find distコマンドで出力を確認し、非ASCII文字を含むファイルがあれば元ファイルをリネームしてビルドし直してください。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
アップロード後確認
アップロード後にURLを開き、ページが表示されたら開発者ツールのNetworkタブで全リソースが正常に読み込まれているかを確認します。Viteでビルドしたアプリはチャンク分割されたJSファイルが複数あるため、すべてのchunkが200で返っているかをNetworkタブでフィルタリングして確認してください。
SPAのルーティングが正しく動くかを確認するため、直接サブパスのURLを入力してアクセスします。静的ホスティングではサブパスへの直接アクセスは404になることが多いため、HashRouter(/#/aboutの形式)を使っているか、すべてのパスをindex.htmlへフォールバックする設定がホスティング側で有効かを確認してください。
- HTML内の外部script・form action・iframeを確認する
- APIキーやトークンらしき文字列がないか検索する
- 画像・CSS・JSのパスが公開後も解決できるか見る
- noindexと認証を混同せず、必要なら両方設定する
よくある質問
distフォルダをGitHubにpushしないように設定しているのにZIPを作れますか?
.gitignoreでdistを除外していてもローカルには生成されているため、ZIPを作ることは問題なくできます。ビルドを実行してdistが生成されていることを確認してから圧縮してください。
Nuxt.jsでも同じ手順が使えますか?
Nuxtの静的生成(nuxt generate)後は.output/publicまたは.nuxt/dist/clientにビルド結果が生成されます。そのフォルダの中身をZIPにすれば同様の手順で共有できます。設定によって出力先が変わるため、nuxt.config.tsを確認してください。
毎回コマンドを打つのが面倒です。自動化する方法はありますか?
package.jsonのscriptsにbuild:zipのようなエイリアスを追加するのが手軽です。CIを使っているならビルドジョブの最後にZIPを成果物としてアーカイブする設定にすることで、コマンド操作なしに最新のZIPを取得できます。