この
きっかけは
この
なぜ Astro にしたのか
移行先の
| Astro | Next.js | |
|---|---|---|
| 得意分野 | コンテンツ中心の静的サイト | 認証・DB ありのアプリ |
| デフォルトの JS 出力 | ゼロ | ルーター + hydration (~40KB) |
| Markdown ブログ | Content Collections が組み込み | 自前で構築が必要 |
| React 資産の再利用 | islands として部分的に利用可 | そのまま |
この
決め手は@astrojs/react を.tsx コンポーネントを.astro へ
移行前後の構成
| 移行前 | 移行後 | |
|---|---|---|
| フレームワーク | Gatsby 5 | Astro 7 |
| UI | React 18 (全体 hydrate) | React 19 (islands) |
| CSS | Tailwind CSS 3 | Tailwind CSS 4 |
| コンテンツ | gatsby-plugin-mdx + GraphQL | Content Collections |
| 画像最適化 | gatsby-plugin-image | astro:assets |
| 検索 | Pagefind | Pagefind (そのまま) |
| Node.js | 22 | 26 |
検索の
手順 1: 依存関係の入れ替え
まず
npm install astro @astrojs/react @astrojs/sitemap \
react react-dom tailwindcss @tailwindcss/vite sharp
npm install -D @astrojs/check typescript
astro.config.mjs は
// astro.config.mjs
import react from "@astrojs/react";
import sitemap from "@astrojs/sitemap";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "astro/config";
export default defineConfig({
site: "https://msageha.net",
integrations: [react(), sitemap()],
vite: {
plugins: [tailwindcss()],
},
});
Tailwind 4 は@tailwind ディレクティブ 3 行が@import "tailwindcss"; の
注意点と"type": "module" がmodule.exports をexport default に
手順 2: GraphQL から Content Collections へ
Gatsby でcontent/blog/*/index.md と
// src/content.config.ts
import { glob } from "astro/loaders";
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
loader: glob({ pattern: "*/index.md", base: "./content/blog" }),
schema: z.object({
title: z.string(),
date: z.coerce.date(),
slug: z.string(),
tags: z.array(z.string()).default([]),
description: z.string().optional(),
}),
});
export const collections = { blog };
zod で
記事一覧の
---
// src/pages/blog/index.astro
import { getCollection } from "astro:content";
const posts = (await getCollection("blog")).sort(
(a, b) => b.data.date.getTime() - a.data.date.getTime(),
);
---
記事ページのgetStaticPaths でslug を
---
// src/pages/blog/[slug].astro
import { getCollection, render } from "astro:content";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.data.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await render(post);
---
Markdown 内の
手順 3: React コンポーネントの island 化
Gatsby 固有の
| Gatsby | Astro (React island) |
|---|---|
<Link to="/blog"> |
<a href="/blog"> |
navigate(url) |
window.location.assign(url) |
useStaticQuery + GatsbyImage |
getImage() の結果を props で渡す |
Head エクスポート |
レイアウト .astro の <head> |
gatsby-browser.js の wrapRootElement |
island のルートで ErrorBoundary |
ページ側は.astro ファイルにclient:load を
<App client:load profileImage={profileImage} />
画像最適化はastro:assets のgetImage() を
---
import { getImage } from "astro:assets";
import profileSource from "../images/profile.jpg";
const profile = await getImage({
src: profileSource,
width: 800,
format: "webp",
});
---
逆に、client:* ディレクティブを
手順 4: Pagefind と BudouX の移植
Pagefind
検索の
{
"scripts": {
"build": "astro build && pagefind --site dist"
}
}
Gatsby のpublic/ でしたが、dist/ です。
BudouX
日本語の<p> や
<script>
import { applyBudouX } from "../../lib/budoux-content";
const content = document.querySelector(".mdx-content");
if (content) {
applyBudouX(content);
}
</script>
applyBudouX は<wbr> を
ハマったポイント
@vite-ignore が dev サーバーで効かない
一番/* @vite-ignore */ を.tsx ファイル内では
// これは dev サーバーでエラーになる
const pagefind = await import(/* @vite-ignore */ "/pagefind/pagefind.js");
Vite は.tsx のastro build はastro dev だけ Failed to resolve import で
回避策は、
// パスを変数経由にすると Vite は解決を試みない
const pagefindPath = "/pagefind/pagefind.js";
const pagefind = await import(/* @vite-ignore */ pagefindPath);
astro dev がデーモンとして起動する
Astro 7 の
astro dev status # 稼働状況の確認
astro dev logs # ログの表示
astro dev stop # 停止
verbatimModuleSyntax による型 import エラー
Astro 推奨のastro/tsconfigs/strict) はverbatimModuleSyntax がimport type に
// Before: エラーになる
import React, { Component, ReactNode } from "react";
// After
import React, { Component, type ReactNode } from "react";
機械的にastro check を
CSS フレームワークのバージョンアップは「ついで」にやる
Tailwind 3 → 4 は
デプロイ設定の変更
この
フレームワークのpublic からdist にnpm run build に
| 設定 | Gatsby | Astro |
|---|---|---|
| Build command | npm run build |
npm run build (変更なし) |
| Build output directory | public |
dist |
| Node バージョン | .nvmrc を自動検出 | .nvmrc を自動検出 (変更なし) |
な@astrojs/cloudflare アダプタは
ちなみに/blog/slug/index.html) で
まとめ
移行作業全体を.astro ページに
やってみて
Gatsby で