AstroサイトをGitHubPagesで公開する方法

作成したAstroブログサイトを、GitHub Pagesを使って無料で公開してみます。すでにGitHubリポジトリで管理している場合は、いくつかの設定を追加するだけで簡単に公開できます。

ここでは[Astro公式ページの手順](https://docs.astro.build/ja/guides/deploy/github/)に従ってGithubActionを使ってページを公開します。

## AstroサイトをGithubPagesに公開する手順

### 1.`astro.config.mjs` を設定する
プロジェクトのルートにある `astro.config.mjs` ファイルを開き、`site` と `base` オプションを追加または編集します。

```javascript
// astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  // ... 他の設定 ...

  // ↓ GitHub Pages用の設定を追加
  site: 'https://あなたのGitHubユーザー名.github.io', // 必ずあなたのユーザー名に置き換えてください
  base: '/あなたのリポジトリ名', // 必ずあなたのリポジトリ名に置き換えてください
  // ↑ ここまで追加
});
```
* `site:` には `https://<あなたのGitHubユーザー名>.github.io` を設定します。
* `base:` にはスラッシュ (`/`) から始まる **あなたのリポジトリ名** を設定します。
    * (例外: リポジトリ名が `<あなたのユーザー名>.github.io` の場合は `base` の設定は不要です。)
* **【超重要！】`base` を設定した場合の影響:**
    * この設定を行うと、サイト内のすべての **内部リンク**（例: `/blog/記事スラッグ/`, `/tags/タグ名/`, `/about` など）の先頭に、自動的に `base` の値 (例: `/あなたのリポジトリ名`) が付与されるようになります。
    * これまで作成した **リンク生成ロジック**（例えば `getPostUrl` ヘルパー関数など）や、テンプレート内に直接記述したリンク (`<a href="/about">` など）を **修正する必要** があります。修正しないと、公開後にサイト内リンクが正しく機能しません！
    * 例えば、`getPostUrl` 関数は `/blog/${post.slug}/` ではなく、Astroが内部で処理してくれる `post.url` を使うか、あるいは `import.meta.env.BASE_URL` を先頭に付けるように修正する必要があります。

### 2.GitHub Actions ワークフローを作成する
* プロジェクトのルートに `.github` という名前のフォルダがなければ作成します。
* `.github` フォルダの中に `workflows` という名前のフォルダを作成します。
* `workflows` フォルダの中に `deploy.yml` という名前で新しいファイルを作成し、以下の内容を貼り付けます。

```yaml
name: Deploy to GitHub Pages

on:
  # `main`ブランチにプッシュするたびにワークフローを実行します。
  # 異なるブランチ名を使用する場合は、`main`をブランチ名に置き換えてください。
  push:
    branches: [ main ]
  # このワークフローをGitHubのActionsタブから手動で実行できるようにします。
  workflow_dispatch:

# このジョブがリポジトリをクローンし、ページデプロイメントを作成することを許可します。
permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout your repository using git
        uses: actions/checkout@v4
      - name: Install, build, and upload your site
        uses: withastro/action@v3
        # with:
          # path: . # リポジトリ内のAstroプロジェクトのルートロケーション。（オプション）
          # node-version: 20 # サイト構築に使用するNodeのバージョン。デフォルトは20です。（オプション）
          # package-manager: pnpm@latest # 依存関係のインストールとサイトのビルドに使用するNodeパッケージマネージャ。ロックファイルに基づいて自動的に検出されます。（オプション）

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
```
* **`branches: [main]`** の `main` 部分は、あなたが普段コードをプッシュしているデフォルトのブランチ名（`main` や `master` など）に合わせてください。

### 3.GitHub リポジトリを設定する
* ブラウザであなたのGitHubリポジトリを開きます。
* リポジトリ上部の「Settings」タブをクリックします。
* 左側のメニューから「Pages」を選択します。
* 「Build and deployment」セクションにある「Source」のドロップダウンメニューをクリックし、**「GitHub Actions」** を選択します。

### 4.変更をコミット & プッシュする
ローカルで編集した `astro.config.mjs` ファイルと、新しく作成した `.github/workflows/deploy.yml` ファイルを `git add`, `git commit` して、GitHubリポジトリに `git push` します。

### 公開の確認

プッシュが完了すると、GitHub Actionsが自動的に起動し、サイトのビルドとデプロイが始まります。

GitHubリポジトリの「Actions」タブで、ワークフローの実行状況を確認できます。緑色のチェックマークが付けば成功です。

デプロイが完了すると、以下のURLであなたのサイトが公開されます。GithubのSettings->Pagesからサイトに移動することもできます。

`https://<あなたのGitHubユーザー名>.github.io/<あなたのリポジトリ名>/`

## 内部リンクの修正について
今回のようにリポジトリ名をルートに入れている場合は全ての内部リンクのURLに`base`の値を入れる必要があります。

`base`で設定したURLは`const baseUrl = import.meta.env.BASE_URL;`で取得することができます。

以下のようにURLが固定の場合はそのまま入れてしまっても大丈夫です。
```
<a href={`${baseUrl}/tags/`}>すべてのタグ一覧へ</a>
```

ブログ記事へのリンクなど繰り返し同じ処理を行う場合は、`src/utils/url.js`にファイルを作成し`getPostUrl`のような関数を作成して使用します。
```
function getPostUrl(post) {
  const baseUrl = import.meta.env.BASE_URL;
  const basePath = baseUrl === '/' ? '' : baseUrl; // BASE_URLが '/' の場合はプレフィックスなし
  if (post.data.url) {
    // フロントマターにurlがあれば、ルートからのパスにbaseを追加して返す
    return `${basePath}/${post.data.url}/`;
  }
  // なければファイルパスに基づくデフォルトのパスにbaseを追加して返す
  return `${basePath}/blog/${post.slug}/`;
}
export { getPostUrl };

// 使用例: index.astro
---
// 省略
import { getPostUrl } from '../utils/url';
---

// 省略

<h2>新着記事</h2>
<ul>
{recentPosts.map((post) => (
  <li>
    {/* getPostUrlヘルパーでリンク先URLを生成 */}
    <a href={getPostUrl(post)}>{post.data.title}</a>
    <span style="font-size: 0.8em; margin-left: 8px;">
      ({post.data.pubDate.toLocaleDateString()})
    </span>
  </li>
))}
</ul>
```