コンテンツにスキップ

Gatsbyからの移行

ここでは、移行を始める際に役立つ主要な概念と移行戦略を紹介します。詳しくはドキュメント全体やDiscordコミュニティをご活用ください。

GatsbyとAstroの類似点

GatsbyとAstroには、プロジェクト移行を容易にするいくつかの共通点があります:

GatsbyとAstroの主な相違点

GatsbyサイトをAstroで再構築する際には、次のような重要な違いに気付くでしょう。

  • GatsbyプロジェクトはReactの単一ページアプリケーションで、index.jsをプロジェクトのルートとして使用します。Astroプロジェクトはマルチページサイトで、index.astroはホームページです。

  • Astroコンポーネントは、ページテンプレートを返すようにexportされた関数で書かれていません。代わりに、コードフェンス(---)でJavaScriptコードを区切って、生成するHTMLのためのコードを分けます。

  • ローカルファイルデータ (EN)の取得: GatsbyはGraphQLを使用してプロジェクトファイルからデータを取得します。AstroではESMインポートとトップレベルawait関数(例: import.meta.glob() (EN)getCollection() (EN))でファイルからデータをインポートします。必要ならAstroプロジェクトにGraphQLを手動で追加できますが、デフォルトでは含まれていません。

GatsbyプロジェクトをAstroに変換する

各プロジェクトの移行手順は様々ですが、GatsbyからAstroへ変換する際に共通して行う作業があります。

新しいAstroプロジェクトの作成する

パッケージマネージャでcreate astroコマンドを実行してAstroのCLIウィザードを起動するか、Astro Theme Showcaseからコミュニティテーマを選択します。

create astroコマンドに--template引数を渡すと、公式スターター(例:docsblogportfolio)のいずれかで新しいAstroプロジェクトを作成できます。また、GitHub上の既存Astroリポジトリから新規プロジェクトを開始 (EN)することも可能です。

 # Astro CLIウィザードを実行
 npm create astro@latest

 # 公式スターターを指定して作成
 npm create astro@latest -- --template <example-name>

次に、既存のGatsbyプロジェクトのファイルをsrcの外側にある別フォルダーへコピーし、新しいAstroプロジェクトへ移行します。

:::tip公式スターターテンプレートの一覧は公式スターターテンプレートを参照してください。IDX、StackBlitz、CodeSandbox、またはGitpodで新規プロジェクトを開くためのリンクもあります。:::

インテグレーションのインストールする(任意)

GatsbyプロジェクトをAstroへ変換する際、以下のようなAstroのオプションインテグレーション (EN)が役立つことがあります。

  • @astrojs/react: 新規Astroサイトで既存のReact UIコンポーネントを再利用するか、Reactコンポーネントで書き続けることができます。

  • @astrojs/mdx: Gatsbyプロジェクトの既存のMDXファイルを持ち込むか、新規AstroサイトでMDXを使用することができます。

ソースコードをsrcに配置する

Astroのプロジェクト構造に従って、次の手順でファイルを整理します。

  1. 削除 Gatsbyのpublic/フォルダ。

    Gatsbyはビルド出力をpublic/ディレクトリに生成しますが、Astroはデフォルトでdist/を使用します。そのためpublic/は安全に削除できます。

  2. リネーム Gatsbyのstatic/フォルダをpublic/、そしてAstroのpublic/フォルダとして使用してください。

    Astroは静的アセット用にpublic/フォルダーを使用します。既存のAstropublic/static/の内容をコピーしても構いません。

  3. コピーまたは移動 Gatsbyのcomponentspagesなどの他のファイルとフォルダを、必要に応じてAstroのsrc/フォルダへ配置してください。Astroのプロジェクト構造を遵守して、ソースコードをsrcに配置してください。

    Astroのsrc/pages/フォルダは、.astro.md.mdxファイルからサイトのページと記事を生成するための特殊なフォルダです。Astro、Markdown、MDXファイルのルーティングを設定する必要はありません。

    その他のフォルダは任意のため、src/フォルダの内容をどのように配置するかは任意です。Astroプロジェクトで一般的なフォルダにはsrc/layouts/src/componentssrc/stylessrc/scriptsがあります。

ヒント:JSXファイルから.astroファイルへの変換する

ここでは、Gatsbyの.jsコンポーネントを.astroコンポーネントに変換するためのいくつかの手順を説明します。

  1. 既存Gatsbyコンポーネントのreturn()部分のみをHTMLテンプレートとして使用してください。

  2. <Link to="">{children}classNameなどGatsby/JSX構文をAstro構文またはHTML標準に変換してください。

  3. import文を含んだ必要なJavaScriptは"コードフェンス" (---)内へ移動してください。注意: 条件付きレンダリング用のJavaScriptは、AstroではHTMLテンプレート内に直接書くことが多いです。

  4. Astro.props (EN)を使用して、以前にGatsby関数に渡された追加のpropsを参照してください。

  5. インポート済みコンポーネントをAstroに変換するか検討してください。公式Reactインテグレーションを使えばAstroファイル内で既存Reactコンポーネントを利用できますが、インタラクティブ性が不要なら.astroへ変換して軽量化できます。

  6. GraphQLクエリは削除し、importimport.meta.glob() (EN)でローカルファイルを読み込ます。

Gatsby Blogスターターを段階的に変換した例も参照してください。

.jsx.astroの比較する

以下のGatsbyコンポーネントと対応するAstroコンポーネントを比較してください:

 import * as React from "react"
 import { useStaticQuery, graphql } from "gatsby"
 import Header from "./header"
 import Footer from "./footer"
 import "./layout.css"

 const Component = ({ message, children }) => {
   const data = useStaticQuery(graphql`
     query SiteTitleQuery {
       site {
         siteMetadata {
           title
         }
       }
     }
   `)
   return (
     <>
       <Header siteTitle={data.site.siteMetadata.title} />
       <div style={{ margin: `0`, maxWidth: `960`}}>{message}</div>
       <main>{children}</main>
       <Footer siteTitle={data.site.siteMetadata} />
     </>
   )
 }

 export default Component

レイアウトファイル移行する

レイアウトファイルをAstroレイアウトコンポーネントに変換するには、Gatsbyのレイアウトやテンプレートから始めてみてください。

Astroの各ページには必ず <html><head><body> タグが必要なため、複数ページで同じレイアウトファイルを再利用するのが一般的です。Astroではページコンテンツ差し込みにReactの {children} ではなく <slot /> を使用し、import文も不要です。Gatsbyのlayout.jsやテンプレートにはこれらが含まれていません。

標準的なHTMLテンプレートと<head>タグへの直接アクセスする例:

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width" />
    <title>Astro</title>
  </head>
  <body>
    <!-- 既存のレイアウトテンプレートで`<slot />`要素を囲んでください。-->
    <slot />
  </body>
</html>

追加でサイトメタデータを含めたい場合は、Gatsbyのsrc/components/seo.jsのコードを再利用できます。注意: Astroでは<Helmet><Header>を使わずに<head>を直接記述します。ページコンテンツを分離して整理するには、コンポーネントを<head>内でインポートして使用することができます。

ページと投稿の移行する

Gatsbyでは ページや投稿src/pages/内、またはcontentなどsrcの外に置かれている場合があります。Astroでは コンテンツコレクション (EN) を使わない限り、すべてのページコンテンツをsrc/内に配置する必要があります。

Reactページ

既存のGatsby JSX(.js)ページはJSXファイルから.astroページへ変換する必要があります。AstroではJSXページファイルをそのまま使用できません。

変換した.astroページsrc/pages/に置き、ファイルパスに基づいてページルートが自動生成されます。

MarkdownとMDXページ

AstroはMarkdownをネイティブサポートし、MDX用のオプション統合も提供しています。既存のMarkdownとMDXファイル (EN)を再利用できますが、フロントマターにAstro専用のlayoutプロパティを追加するなどの調整が必要な場合があります。これらのファイルもsrc/pages/に置けば自動的にファイルベースルーティングを利用できます。

あるいはAstroのコンテンツコレクション (EN)を使ってコンテンツを管理し、自分で取得して動的にページを生成 (EN)することもできます。

テストの移行する

Astroは生のHTMLを出力するため、ビルド後の出力を使用したE2Eテストができます。旧Gatsbyサイトのマークアップが再現できれば、既存のエンドツーエンドテストがそのまま動作する場合があります。JestやReact Testing LibraryなどをインポートしてReactコンポーネントをテストできます。

詳しくはテストガイドを参照してください。

設定ファイルの再利用する

Gatsbyにはルーティングやメタデータを含むトップレベル設定ファイルが複数あり、ルーティングに使用されます。Astroではこれらのgatsby-*.jsファイルを使用しませんが、内容を再利用できる場合があります。

  • gatsby-config.js: src/data/siteMetadata.js(またはsiteMetadata.json)にsiteMetadata: {}を移動して、ページレイアウトにサイト(タイトル、説明、ソーシャルアカウントなど)に関するデータをインポートします。

  • gatsby-browser.js: ここで使用されているものは、主要レイアウト<head>タグに直接追加することを考慮してください。

  • gatsby-node.js: Astroでは独自のノードを作成する必要はありませんが、このファイルのスキーマを確認して、Astroプロジェクトで型を定義するのに役立つかもしれません。

  • gatsby-ssr.js: AstroでSSRを使用する場合、astro.config.mjsに直接SSRアダプターを追加して構成してください。

参考: Astro構文への変換する

以下はGatsby特有の構文をAstroに変換するいくつかの例です。Astroコンポーネントの書き方におけるAstroとJSXの違いも参照してください。

Gatsby LinksをAstroに変換する

Gatsbyの<Link to=""><NavLink>などのコンポーネントをHTMLの<a href="">タグに変換します。

<Link to="/blog">Blog</Link>
<a href="/blog">Blog</a>

Astroにはリンク専用のコンポーネントはありませんが、独自の<Link>コンポーネントを作ってもかまいません。<Link>を他のコンポーネントのようにインポートして使用することができます。

---
const { to } = Astro.props
---
<a href={to}><slot /></a>

Gatsby ImportsをAstroに変換する

必要に応じて、ファイルのインポート (EN)を相対ファイルパスで正確に参照するように変更します。これにはインポートエイリアス (EN)を使用したり、相対パスを完全に書くこともできます。

注意: .astroなど一部のファイルは拡張子を省略できません。

---
import Card from `../../components/Card.astro`;
---
<Card />

Gatsbyの{children}をAstroに変換する

Gatsbyの{children}をAstroの<slot />に変換します。Astroは{children}を関数プロップとして受け取る必要なく、子要素を<slot />で自動的にレンダリングします。

---
---
export default function MyComponent(props) { 
    return (
      <div>
        {props.children}
      </div>
    );  
}

<div>
  <slot />
</div>

Reactコンポーネントが複数の子要素を渡す場合は、named slotsを使用してAstroコンポーネントに移行できます。

特定の<slot />の使用方法に関する詳しい説明は特定の<slot />の使用方法を参照してください。

スタイリングを変換する

必要に応じて、CSS-in-JSライブラリ(例:styled-components)をAstroで使用できるCSSオプションに置き換える必要があります。

必要なら、インラインスタイルオブジェクト(style={{ fontWeight: "bold" }})をインラインHTMLスタイル属性(style="font-weight:bold;")に変換するか、Astroの<style>タグ (EN)を使用してスコープCSSスタイルを記述します。

<div style={{backgroundColor: `#f4f4f4`, padding: `1em`}}>{message}</div>
<div style="background-color: #f4f4f4; padding: 1em;">{message}</div>

TailwindはTailwind Viteプラグイン (EN)をインストールすればサポートされます。既存のTailwindコードは変更する必要はありません。

Gatsbyではgatsby-browser.jsでCSSインポートを使用してグローバルスタイリングを適用します。Astroでは、主なレイアウトコンポーネントに.cssファイルを直接インポートしてグローバルスタイリングを適用します。

詳しくはStyling in Astro (EN)を参照してください。

画像プラグインを置き換える

Gatsbyの<StaticImage /><GatsbyImage />コンポーネントをAstroの独自の画像統合コンポーネント (EN)に変換するか、または適切なReactコンポーネントで標準HTMLの<img>/JSXの<img /> (EN)タグへ変換します。

---
import { Image } from 'astro:assets';
import rocket from '../assets/rocket.png';
---
<Image src={rocket} alt="A rocketship in space." />
<img src={rocket.src} alt="A rocketship in space.">

Astroの<Image />コンポーネントは.astro.mdxファイルのみで動作します。完全なコンポーネント属性のリスト (EN)を確認し、いくつかはGatsbyの属性と異なります。

Markdownファイル(.md)で画像を使用 (EN)を続ける場合は、標準のMarkdown構文(![]())を使用することができます。HTMLの<img>タグを直接使用することは、ローカル画像の.mdファイルではサポートされていません。そのため、それをMarkdown構文に変換する必要があります。

<!-- src/pages/post-1.md -->

# Markdown ページ

<!-- src/assets/stars.png をローカル画像として保存 -->
![A starry night sky.](../assets/stars.png)

Reactコンポーネント(.jsx)で画像を使用する場合は、標準のJSX画像構文(<img />)を使用することができます。Astroはこれらの画像を最適化しませんが、NPMパッケージをインストールして使用することでより柔軟な選択肢を提供できます。

詳しくはAstroの画像ガイド (EN)を参照してください。

Gatsby GraphQLをAstroに変換する

GraphQLクエリへの参照をすべて削除し、代わりにローカルファイルのデータにアクセスするにはimport.meta.glob() (EN)を使用してください。

あるいは、コンテンツコレクションを使用している場合は、MarkdownやMDXファイルをgetEntry()およびgetCollection() (EN)でクエリしてください。

これらのデータリクエストは、Astroコンポーネントのフロントマター内で行われます。

---
import { getCollection } from 'astro:content';

// `src/content/blog/` エントリを全て取得する
const allBlogPosts = await getCollection('blog');

// `src/pages/posts/` エントリを全て取得する
const allPosts = Object.values(import.meta.glob('../pages/post/*.md', { eager: true }));
---

export const pageQuery = graphql`
  {
    allMarkdownRemark(sort: { frontmatter: { date: DESC } }) {
      nodes {
        excerpt
        fields {
          slug
        }
        frontmatter {
          date(formatString: "MMMM DD, YYYY")
          title
          description
        }
      }
    }
  }
`

ガイド付き例:GatsbyレイアウトをAstroへ変換する

この例では、Gatsbyのブログスターターやlayout.jssrc/layouts/Layout.astroに変換します。

ホームページでは1つ目のヘッダーを表示し、それ以外のページでは「Home」へのリンク付きヘッダーを表示します。

  1. return()のJSXを特定する

    import * as React from "react"
    import { Link } from "gatsby"
    const Layout = ({ location, title, children }) => {
      const rootPath = `${__PATH_PREFIX__}/`
      const isRootPath = location.pathname === rootPath
      let header
      if (isRootPath) {
        header = (
          <h1 className="main-heading">
            <Link to="/">{title}</Link>
          </h1>
        )
      } else {
        header = (
          <Link className="header-link-home" to="/">
            Home
          </Link>
        )
      }
      return (
        <div className="global-wrapper" data-is-root-path={isRootPath}>
          <header className="global-header">{header}</header>
          <main>{children}</main>
          <footer>
            © {new Date().getFullYear()}, Built with
            {` `}
            <a href="https://www.gatsbyjs.com">Gatsby</a>
          </footer>
        </div>
      )
    }
    export default Layout
  2. Layout.astroを作成して、このreturn値をAstro構文に変換します。

    注意点:

    • {new Date().getFullYear()}はそのまま動作 🎉
    • {children}<slot />に変換 🦥
    • classNameclassに変換 📛
    • GatsbyAstroに変換 🚀
    ---
    ---
    <div class="global-wrapper" data-is-root-path={isRootPath}>
      <header class="global-header">{header}</header>
      <main><slot /></main>
      <footer>
        © {new Date().getFullYear()}, Built with
        {` `}
        <a href="https://www.astro.build">Astro</a>
      </footer>
    </div>
  3. レイアウトがHTMLドキュメントに必要な要素を各ページに提供できるように、ページシェルを追加します:

    ---
    ---
    <html>
      <head>
        <meta charset="utf-8" />
        <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
        <meta name="viewport" content="width=device-width" />
        <title>Astro</title>
      </head>
      <body>
        <div class="global-wrapper" data-is-root-path={isRootPath}>
          <header class="global-header">{header}</header>
          <main>
            <slot />
          </main>
          <footer>
            &#169; {new Date().getFullYear()}, Built with
            {` `}
            <a href="https://www.astro.build">Astro</a>
          </footer>
        </div>
      </body>
    </html>
  4. 必要なインポート、props、JavaScriptを追加します

    Astroでページルートとタイトルに基づいてヘッダーを条件付きでレンダリングするには:

    • Astro.props経由でpropsを提供します。(注:Astroのテンプレートでは、関数に渡すのではなく、フロントマターからpropsにアクセスします)
    • 三項演算子を使用して、ホームページの場合は1つの見出し、それ以外の場合は別の見出しを表示します
    • {header}{isRootPath}の変数は不要になったため削除します
    • Gatsbyの<Link/>タグを<a>アンカータグに置き換えます
    • classNameの代わりにclassを使用します
    • クラス名を有効にするために、プロジェクトからローカルのスタイルシートをインポートします
    ---
    import '../styles/style.css';
    const { title, pathname } = Astro.props
    ---
    <html>
      <head>
        <meta charset="utf-8" />
        <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
        <meta name="viewport" content="width=device-width" />
        <title>Astro</title>
      </head>
      <body>
        <div class="global-wrapper">
          <header class="global-header">
            { pathname === "/" 
            ? 
              <h1 class="main-heading">
              <a href="/">{title}</a>
              </h1>
            : 
              <h1 class="main-heading">
              <a class="header-link-home" href="/">Home</a>
              </h1>
            }  
          </header>
          <main>
            <slot />
          </main>
          <footer>
            &#169; {new Date().getFullYear()}, Built with
            {` `}
            <a href="https://www.astro.build">Astro</a>
          </footer>
        </div>
      </body>
    </html>
  5. index.astroを更新して、この新しいレイアウトを使用して、必要なtitlepathname propsを渡します:

    ---
    import Layout from '../layouts/Layout.astro';
    const pagePathname = Astro.url.pathname
    ---
    <Layout title="Home Page" pathname={pagePathname}>
        <p>Astro</p>
    </Layout>

    :::tip現在のページのパスはAstro.url (EN)で取得できます。:::

  6. 条件付きヘッダーをテストするには、同じパターンを使用して2番目のページ、about.astroを作成します:

    ---
    import Layout from '../layouts/Layout.astro';
    const pagePathname = Astro.url.pathname
    ---
    <Layout title="About" pathname={pagePathname}>
        <p>About</p>
    </Layout>

    Aboutページでは「Home」へのリンクが表示され、ホームページでは表示されません。

コミュニティリソース

:::注意[共有したいリソースはありますか?]GatsbyサイトをAstroに移行する方法について、参考になる動画やブログ記事を見つけた(または作成した)場合は、このリストに追加してください!:::

その他のマイグレーションガイド

貢献する コミュニティ スポンサー