📖 18分で読める

【Git入門 #5】distフォルダって何が入ってるの? — Astroの「選別ルール」を覗いてみた


💡 この記事について AIアシスタント(OpenClaw/スピカ)との会話を元にした学習記録です。 内容は変更される可能性があるため、実際の開発では公式ドキュメントを確認の上、ご自身の判断でお願いします。


この記事で分かること

  • Astro がビルド時に「何を選んで、何を捨てるか」の明確なルール
  • dist/ フォルダの正体と、そこに入る3つのソース
  • ソースコードや設定ファイルが外に出ない理由
  • 「ワークスペースに全部見えてるけど大丈夫なの?」への回答

きっかけ — 同じ画面に全部見えてるのが怖い

ワークスペースのサイドバー。.agent, .github, node_modules など全てのフォルダが一覧で見えている
セブ
セブ
スピカ、ちょっと聞いていい? 最近ずっと気になってたんだけど……
スピカ
スピカ AI
どうした、改まって。
セブ
セブ
自分のワークスペース見てると、ブログの記事ファイルの横に .github とか node_modules とか色々並んでるじゃん。git push したらこれ全部外に出てたりしないよな……?
スピカ
スピカ AI
あー、その不安ね。わかる。IDEで全部フラットに見えてるから「これ全部セットで公開されてんじゃないか」って思うよね。
セブ
セブ
そうそう! しかもAIがファイルを操作してるわけじゃん。間違って変なファイルを公開フォルダに入れたりしてないかって。
スピカ
スピカ AI
先に安心させとくと、何をどう間違えても、Astroが拾わないファイルは物理的に公開されない。運任せじゃなくて、仕組みとしてそうなってる。で、その仕組みがわかれば不安は消える。
スピカ
スピカ AI
全体像はこう。
flowchart LR
  A["📁 ワークスペース\n全ファイル"] -->|"git push"| B["☁️ Cloudflare\nnpm run build"]
  B -->|"3箇所だけ読む"| C["🔨 Astro 変換\n.astro → HTML\n.mdx → HTML\n画像 → WebP"]
  C --> D["📦 dist/\nHTML CSS WebP\nフォント favicon"]
  D --> E["⚡ CDN配信\n読者に届く"]
  A -.->|"❌ 読まない"| F["🚫 対象外\n.github .agent\nnode_modules"]
  A -.->|"npm run dev"| G["💻 ローカル確認\ndist 作られない"]
セブ
セブ
おお、こう見ると流れがわかるな。ローカルで npm run dev してるときは dist 関係ないのか。
スピカ
スピカ AI
そう。で、点線で繋がってる .github とか node_modules は、Astro が読みもしない。ここから先を順番に解説していくよ。

dist/ って誰が決めたの?

セブ
セブ
まずそもそもの疑問。dist ってフォルダ、自分は作った覚えないんだけど。
スピカ
スピカ AI
Astro の初期設定で最初から決まってる。
// astro.config.mjs(あなたのブログの設定ファイル)
export default defineConfig({
  site: 'https://blog.7sapiens.com',
  integrations: [mdx(), sitemap()],
  // ← outDir の指定なし = デフォルトの 'dist' が使われる
});
スピカ
スピカ AI
outDir っていう設定があって、何も書かなければ ./dist になる。dist は “distribution”、つまり「配布物」って意味。完成品を入れる箱の名前だと思えばいい。
セブ
セブ
へえ、じゃあ outDir: './build' って書いたら build/ に変わるってこと?
スピカ
スピカ AI
そう。でも変える理由がない。dist のままでOK。

Astroの「選別ルール」— 読むのは3箇所だけ

セブ
セブ
で、その dist に何を入れるかって、誰がどう決めてるの?
スピカ
スピカ AI
Astro は 3つの場所しか見てない。マジで3つだけ。それ以外は存在すら認識してない。

src/pages/ → HTMLに変換

スピカ
スピカ AI
まず src/pages/ の中身。ここにあるファイルが、そのままURLになるページになる。
pages/ のファイル生成されるURL
index.astro/ (トップページ)
about.astro/about
blog/[...slug].astro/blog/ai-01-openclaw 等(記事ごとに自動生成)
rss.xml.js/rss.xml
セブ
セブ
えっ待って、[...slug].astro って1ファイルからブログ記事が全部生成されるの?
スピカ
スピカ AI
そう。イメージとしてはこう。
テンプレート(1つ)        記事データ(複数)           完成品(dist/)
─────────────         ──────────────          ─────────────
[...slug].astro   ×   ai-01-openclaw.mdx   →  blog/ai-01-openclaw/index.html
                  ×   git-04-cache.mdx     →  blog/git-04-cloudflare-cache/index.html
                  ×   indie-05-store.mdx   →  blog/indie-05-google-play-store/index.html
                      ...(記事の数だけ)         ...(HTMLの数だけ)
スピカ
スピカ AI
テンプレートは「デザインの型紙」で、記事データは「中身の文章」。型紙 × 文章 = 完成した HTML ページ。テンプレート自体は dist に入らない。完成品だけが入る。
セブ
セブ
おお、なるほど。パワポのテンプレートに中身を流し込む感じか。テンプレートファイルそのものは読者に渡らないと。
スピカ
スピカ AI
そういうこと。

public/ → そのままコピー

public/favicon.svg        → dist/favicon.svg
public/fonts/             → dist/fonts/
public/audio/             → dist/audio/
スピカ
スピカ AI
public の中身は変換なしでそのまま dist にコピーされる。フォントとかfaviconとか、加工不要なファイル置き場。

src/content/ → 記事データとしてページに取り込み

// content.config.ts
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' })
スピカ
スピカ AI
src/content/blog/.md.mdx ファイルだけを読み取る。これがさっきの [...slug].astro テンプレートと組み合わさって HTML になる。
セブ
セブ
つまり .mdx ファイル自体は dist に入らないってこと?
スピカ
スピカ AI
入らない。HTML に変換済みだから、元の .mdx はお役御免。

ローカルで動かすのと何が違うの?

セブ
セブ
ちょっと待って。自分のパソコンで npm run dev して確認してるときも dist が作られてるの? それとも Cloudflare だけの話?
スピカ
スピカ AI
いい質問。npm run dev はローカル開発用で、dist は作られない。メモリ上でリアルタイムに変換して、ブラウザに表示してるだけ。
コマンド何が起きるdist 作られる?
npm run devローカルで開発用サーバーが起動。ファイルを変えると即反映❌ 作られない
npm run build全ページをHTMLに変換して dist に出力✅ 作られる
スピカ
スピカ AI
Cloudflare がやってるのは npm run build のほう。git push を受け取ったら、Cloudflare のサーバー上で npm run build を実行して dist を作り、その中身だけをCDNに配信する。
セブ
セブ
つまり自分のパソコンで npm run dev してるときは dist とは無関係で、Cloudflare がビルドしたときに初めて dist ができるってことか。
スピカ
スピカ AI
正確には、自分のパソコンでも npm run build すれば dist はできる。でも普段はやる必要ない。Cloudflare が代わりにやってくれるから。

弾いてるんじゃなくて、読んですらいない

セブ
セブ
じゃあ .github とか node_modules は? ブラックリストみたいなもので弾いてるの?
スピカ
スピカ AI
ここ、よく誤解されるポイント。弾いてるんじゃなくて、最初から読む対象に入ってない
セブ
セブ
……どう違うの?
スピカ
スピカ AI
ブラックリスト方式は「全部読むけど、NGリストに載ってるやつは除外」。Astro はその逆で、ホワイトリスト方式。「この3箇所だけ読みます。他は知りません」。
読む(ホワイトリスト)読まない(存在すら見ない)
src/pages/ → ページ生成.github/
src/content/ → コンテンツデータ.vscode/
public/ → そのままコピー.agent/
src/components/ → import経由のみ.git/
src/layouts/ → import経由のみnode_modules/
src/styles/ → import経由のみREADME.md
package.json
スピカ
スピカ AI
.github フォルダをいくら増やしても、作業メモを置いても、dist には入りようがない。ブラックリストだと「登録し忘れて漏れた」が起きるけど、ホワイトリストだと「勝手に追加された」は起きない。ここがデカい。
セブ
セブ
おおー……。それ聞いてだいぶ楽になった。設定でどうこうじゃなくて、構造的に漏れないのか。

Cloudflareが見てるのは dist だけ

セブ
セブ
Astro 側はわかった。じゃあ Cloudflare は? リポジトリ全体を触れるんだよね?
スピカ
スピカ AI
ビルド時に全ファイルを clone するのはそう。でもホスティングするのは dist の中身だけ。設定もすごくシンプルで、3つしかない。
設定意味
Build commandnpm run buildastro build を実行しろ
Build output directorydistdist の中身だけをホスティングしろ
Root directory7sapiens-blogビルドの起点はここ
セブ
セブ
マジで 3つだけ?
スピカ
スピカ AI
3つだけ。で、「Build output directory が dist」ということは、dist 以外のフォルダは物理的にサーバーに送られない。clone はビルドのために一時的にやってるだけで、ビルドが終わったら dist の中身だけがCDNに乗る。

ソースコードは漏れてないの?

セブ
セブ
で、本題に戻るけど。結局、大丈夫なの?
スピカ
スピカ AI
一個ずつ潰していこう。
心配事漏れる?理由
ソースコード(.astro .ts❌ 漏れないHTML に変換されるだけ。元コードは配信されない
APIキー❌ 漏れない.env.gitignore に入ってて GitHub にすら上がらない
.github のCI設定❌ 漏れないdist に入らないので公開されない
node_modules❌ 漏れないdist に入らないので公開されない
AIの設定ファイル(.agent/❌ 漏れないdist に入らないので公開されない
セブ
セブ
……安心した。ワークスペースで全部並んでるから、なんかごっちゃになって外に出てる気がしてたんだよ。ずっと地味に不安だった。
スピカ
スピカ AI
画面上の見え方と、実際に公開されるものは完全に別。IDEは全ファイルをフラットに見せるけど、Astro は自分の担当フォルダしか触らないし、Cloudflare は dist しか配信しない。二重のフィルターがかかってる。
セブ
セブ
しかもホワイトリスト方式だから、うっかりミスで漏れることもないと。……なんで最初からこれ聞かなかったんだろ。
スピカ
スピカ AI
そう。「ブラックリストに登録し忘れた」は起きるけど、「ホワイトリストに勝手に追加された」は起きない。

まとめ

5つだけ覚えておけば、もう不安にならない。

  1. dist/ は Astro のデフォルト出力先。設定ファイルで変えられるけど、変える理由がない
  2. Astro はホワイトリスト方式src/pages/ + public/ + import されたものだけ処理する
  3. 読まれないファイルは存在すら無視。ブラックリストで弾いてるんじゃなくて、最初から対象外
  4. Cloudflare は dist だけをホスティング。それ以外はサーバーに送られない
  5. .gitignore で二重防壁.envnode_modules は GitHub にすら上がらない
セブ
セブ
仕組みを知ったら「なんとなく不安」が消えた。地味だけど、これ大事な作業だったかもしれない。
スピカ
スピカ AI
「なんとなく大丈夫」と「仕組みを理解して大丈夫」は全然違うからね。

📚 Git入門シリーズ

  1. Antigravityとgit commit & push
  2. git pushしたらブログが公開される仕組み
  3. ブランチとプルリクエスト
  4. ブログ記事を消したのにまだ見える!
  5. distフォルダって何が入ってるの? ← いまここ