Astro製Webサイトのデプロイでハマったポイント
2025年末にWebサイトをWordPressからAstroに切り替えました。
生成AIの活用でWebサイト本体の開発はスムーズにいきましたが、実運用を考えながらデプロイ周りを整理する段階でいろいろつまづいたので記録を残しておきます。
この記事の話題
- Astro
- TypeScript
- pnpm
- GA4 / GTM
- GitHub Actions
画像関係
Astroはビルド時に自動で圧縮してくれるようです。
そういった便利機能はなるべくフレームワークの仕様に乗っかる方針です。
そのため、画像は基本的にpublicディレクトリではなくsrcディレクトリに配置。
開発時のローカル環境では問題なかったのに、ビルド・デプロイしたらそういった画像が一切合切リンク切れを起こしたという話。
最初はパス関連の設定ファイルでミスがあったかと思い、configファイルを中心に点検したのですが、そこは問題なく。
生成AIに確認しながらいろいろな可能性を潰していったのですがなかなかヒットせず、そこそこ時間を浪費。
最終的な原因はこちら。
本当は自動でインストールされるはずのSharpというライブラリが入っていなかった、ということ。
どうもpnpmとの相性が悪かったようで。
これを手動で入れたら解決しました。
これに気づいたきっかけはうろ覚えですが、確か、ビルド後のassetsディレクトリに配置された画像のファイル名とhtml内のファイル名が違っていたこと。
assets内がwebpになっているのに、html内はpngやjpgのままだった・・・とかだったと思います。
pnpmを使っている方々、お気をつけくださいませ。
(その後、別のプロジェクトで経験したところによると、ビルド時のログにさらっと「Sharpがないよ〜」と書いてありました😓)
計測関係
お次はGoogle Analytics(GA4) / Google Tag Manager(GTM)でハマりました。
もともとWordPress時代で使っていたので、タグなどは発行済み。
しかし、Analyticsのリアルタイムに反映されてこないというトラブル。
これの原因は主に自分の不勉強によるところが大きいです。
恥を忍んで書き起こすと以下のような流れ。
- 生成AIの提案+ググって見つけた先人の知恵にしたがい、partytownというライブラリを使用してタグの情報を実装。
- Analyticsに反映されていないことに気づく。
- いろいろ検証した結果、partytownをうまく使えていない様子。
- GA4/GTMのためだけにpartytownを使う必要はないだろうという結論に至る。
- partytownをアンインストールして普通にhead内に記述する方針に落ち着く。
- TypeScriptの型定義が必要
declare global {
interface Window {
dataLayer: any[];
}
}
この型定義は別になんてことないことですが、なんのために書いたコードか忘れそうなのでメモとして。
さらにダメ押しで、
- GitHub Actionsとの兼ね合い
というトラップもありました。コレに関しては次の項で。
CI/CD関係
ブログを書くことなど考えるとデプロイの手間は少しでも減らしたい。
ということでCI/CDを検討(実際はCDのみ、かな?)。
モバイル開発が中心の自分にはこれまで縁がなかったGitHub Actionsのお世話になることに。
GitHubにプッシュしたら自動でサーバー側にデプロイしてもらえる構成を目標としました。
GitHub Actions
経験が少ないため、yamlファイルはもちろん生成AI頼み。
ここでもpnpmにやられました。(← 自分が知らなすぎるだけ)
生成AIに渡している要件定義書にpnpmの記載が漏れていたため、しれっとnpm版で出してきていました。
気付かずに使って、もちろん失敗。
pnpm版に書き換えてもらったのですが、ここでの生成AIの回答がちょっと微妙な結果に。
最終的には自分なりに勉強して構成。
以下を最終形として、なんとか運用にこぎつけました。
name: 🚀 Deploy Astro SSG on push
on:
push:
branches: [main]
jobs:
deploy:
name: 🎉 Deploy
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [24]
steps:
- name: 🤖 Get latest code
uses: actions/checkout@v6
- name: 🤖 Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: 🤖 Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
- name: 🤖 Install dependencies
run: pnpm install --frozen-lockfile
- name: 🤖 Build
run: pnpm run build
env:
PUBLIC_GA_MEASUREMENT_ID: ${{ secrets.xxxxxx }}
- name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
with:
server: secrets.xxxxxx
username: secrets.xxxxxx
password: secrets.xxxxxx
local-dir: xxxxxx
server-dir: xxxxxx
結局のところは公式の発信内容をちゃんと見なきゃいかんのですよね。
ハマったポイントは3つ。
- yamlの記載順
- ディレクトリ名
- 計測関係
yamlの記載順
記載順は、actions/setup-nodeの前にpnpm/action-setupを持ってくるのが大事だったようです。
各ライブラリのReadmeを照らし合わせて上記の順番に落ち着きました。
ディレクトリ名
ディレクトリ名は、生成AIによると「GitHub Actions(Linux)は大文字小文字の区別が厳密だよ」ということで。
表面上はもちろんパスに合わせた記述にしてあったのですが、開発端末(Mac)上では大文字に見えてもGitの方では小文字になっている、ということがあったらしく。
経験ある方にとっては既知の内容かと思われますが、これはGitのキャッシュなんかも絡み修正も手間で厄介でした。
生成AI向けの要件定義書に「ディレクトリ名は小文字」と書いておいた方が良いのかもしれません。
計測関係
またまた GA4/GTM です。
テスト環境でのページ閲覧を計測から除外するために、環境変数を使用していました。
この手法が、GitHub側でビルドする方法だと使えない。
Webサイトをデプロイしてしばらくこの事に気付いておりませんでした。
📂 Sync files の手前にある2行が後から対応した部分です。 .envファイルからGitHubのSecrets変数にお引越しして、問題解決。
この問題に対するワークアラウンドは複数あるようなので、最適解かは分かりません。
他の手法も試しましたがコード整形ツールとAstroの相性もあったりと、なかなか難しかったです。
GA4/GTMはこの後も擦ったもんだあり、しっかり稼働するまで試行錯誤が必要でした。
これも自分の試行錯誤の記録として、別の記事に書きます。
とりあえず今回はここまで。
勉強になりました。