レイアウト
レイアウトは、ページテンプレートのような再利用可能なUI構造を作成するために使用されるAstroコンポーネントです。
ヘッダーやナビゲーションバー、フッターなど、ページ間で共有される共通のUIを提供するAstroコンポーネントには、慣習的に「レイアウト」という用語が使われます。典型的なAstroのレイアウトコンポーネントは、Astro、Markdown、またはMDXのページに以下を提供します。
- ページシェル(<html>,<head>,<body>タグ)
- 個々のページコンテンツが挿入される場所を指定する<slot />
ただし、レイアウトコンポーネントに何か特別なところがあるわけではありません。他のAstroコンポーネントと同様に、propsを受け取り、他のコンポーネントをインポートして使用できます。UIフレームワークコンポーネントやクライアントサイドスクリプトも含められます。ページ全体のシェルを提供する必要すらなく、代わりに部分的なUIテンプレートとしても使用可能です。
レイアウトコンポーネントは一般的にプロジェクト内のsrc/layoutsディレクトリに配置されますが、これは必須ではなく、プロジェクト内のどこに置いても構いません。レイアウトコンポーネントをページと同じ場所に置くこともでき、その場合はレイアウト名の先頭に_を付けます。
レイアウトのサンプル
---import BaseHead from '../components/BaseHead.astro';import Footer from '../components/Footer.astro';const { title } = Astro.props---<html lang="ja">  <head>    <meta charset="utf-8">    <meta name="viewport" content="width=device-width, initial-scale=1">    <BaseHead title={title}/>  </head>  <body>    <nav>      <a href="#">ホーム</a>      <a href="#">ブログ</a>      <a href="#">お問い合わせ</a>    </nav>    <h1>{title}</h1>    <article>      <slot /> <!-- ここにコンテンツが挿入されます -->    </article>    <Footer />  </body></html>---import MySiteLayout from '../layouts/MySiteLayout.astro';---<MySiteLayout title="ホームページ">  <p>レイアウトに包まれたページのコンテンツ</p></MySiteLayout>📚 スロットについてもっと学ぶ。
MarkdownとMDXのレイアウト
ページレイアウトは、ページフォーマットをもたないMarkdownページとMDXページに対して特に便利です。
Astroでは、layoutというフロントマターの特別なプロパティを使用して、ページのレイアウトとして使用する.astroコンポーネントを指定できます。
---layout: ../layouts/BaseLayout.astrotitle: "Hello, World!"author: "Matthew Phillips"date: "2022年8月9日"---すべてのフロントマターのプロパティは、Astroのレイアウトコンポーネントのpropsとして利用できます。
`layout`プロパティは、Astroが提供する唯一の特別なプロパティです。
`src/pages/`内のMarkdownとMDXファイルの両方で使用できます。MarkdownまたはMDXページの典型的なレイアウトは以下を含みます。
- MarkdownまたはMDXページのフロントマターとその他のデータにアクセスするためのfrontmatterプロパティ。
- ページのMarkdownやMDXコンテンツをレンダリングする場所を示すためのデフォルトの<slot />。
---// 1. frontmatter propによりフロントマターとその他のデータにアクセスできますconst { frontmatter } = Astro.props;---<html>  <head>    <!-- スタイルやmetaタグなど、その他のhead要素をここに追加します -->    <title>{frontmatter.title}</title>  </head>  <body>    <!-- 共通のヘッダーやフッターなど、他のUIコンポーネントをここに追加します -->    <h1>{frontmatter.title} {frontmatter.author}著</h1>    <!-- 2. レンダリングされたHTMLはデフォルトスロットに渡されます -->    <slot />    <p>投稿日: {frontmatter.date}</p>  </body></html>MarkdownLayoutPropsまたはMDXLayoutPropsを使用して、レイアウトのProps型を設定できます。
---import type { MarkdownLayoutProps } from 'astro';
type Props = MarkdownLayoutProps<{  // フロントマターのpropsをここで定義します  title: string;  author: string;  date: string;}>;
// `frontmatter`や`url`などのMarkdownのレイアウトプロパティに// 型安全にアクセスできますconst { frontmatter, url } = Astro.props;---<html>  <head>    <link rel="canonical" href={new URL(url, Astro.site).pathname}>    <title>{frontmatter.title}</title>  </head>  <body>    <h1>{frontmatter.title} {frontmatter.author}著</h1>    <slot />    <p>投稿日: {frontmatter.date}</p>  </body></html>MarkdownレイアウトのProps
MarkdownとMDXレイアウトは、Astro.propsを介して次の情報にアクセスできます。
- file- ファイルの絶対パス(たとえば- /home/user/projects/.../file.md)。
- url- ページであれば、そのページのURL(- /en/guides/markdown-content)。
- frontmatter- MarkdownまたはMDXドキュメントのすべてのフロントマター。- frontmatter.file- トップレベルの- fileプロパティと同じ。
- frontmatter.url- トップレベルの- urlプロパティと同じ。
 
- headings- MarkdownまたはMDXドキュメントの見出し(- h1 -> h6)と、関連するメタデータのリスト。このリストは次の型に従います:- { depth: number; slug: string; text: string }[]。
- (Markdownのみ) rawContent()- 生のMarkdownドキュメントを文字列として返す関数。
- (Markdownのみ) compiledContent()- HTML文字列にコンパイルしたMarkdownドキュメントを返す関数。
Markdownのブログ記事がレイアウトに渡すAstro.propsオブジェクトは以下のようになるでしょう。
Astro.props = {  file: "/home/user/projects/.../file.md",  url: "/en/guides/markdown-content/",  frontmatter: {    /** ブログ記事のフロントマター */    title: "Astro 0.18 Release",    date: "Tuesday, July 27 2021",    author: "Matthew Phillips",    description: "Astro 0.18 is our biggest release since Astro launch.",    /** 生成された値 */    file: "/home/user/projects/.../file.md",    url: "/en/guides/markdown-content/"  },  headings: [    {      "depth": 1,      "text": "Astro 0.18 Release",      "slug": "astro-018-release"    },    {      "depth": 2,      "text": "Responsive partial hydration",      "slug": "responsive-partial-hydration"    }    /* ... */  ],
  /** Markdownでのみ利用可能 */  rawContent: () => "# Astro 0.18 Release\nA little over a month ago, the first public beta [...]",  compiledContent: () => "<h1>Astro 0.18 Release</h1>\n<p>A little over a month ago, the first public beta [...]</p>",}MarkdownとMDXのレイアウトは、ファイルがエクスポートしたプロパティのすべてにAstro.propsからアクセスできますが、いくつかの重要な違いがあります。
- 
見出し情報(つまり h1 -> h6要素)は、getHeadings()関数ではなく、headings配列を介して利用できます。
- 
fileとurlは、ネストされたfrontmatterプロパティ(つまりfrontmatter.urlとfrontmatter.file)としても利用できます。
- 
フロントマターの外部で定義された値(たとえばMDXの export文)は利用できません。代わりにレイアウトをインポートしてください。
レイアウトを手動でインポートする(MDX)
MDXレイアウトに、フロントマターには存在しない(または存在しようがない)情報を渡す必要がある場合があります。この場合、代わりに<Layout />コンポーネントをインポートして使用し、他のコンポーネントと同様にpropsを渡せます。
---layout: ../../layouts/BaseLayout.astrotitle: '初めてのMDX記事'publishDate: '2022年9月21日'---import BaseLayout from '../../layouts/BaseLayout.astro';
function fancyJsHelper() {  return "YAMLでやってみよう!";}
<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>  MDXを使用した新しいAstroブログへようこそ!</BaseLayout>すると、レイアウトのAstro.propsを介して値が利用でき、MDXコンテンツは<slot />コンポーネントが書かれている場所に挿入されます。
---const { title, fancyJsHelper } = Astro.props;---<!-- --><h1>{title}</h1><slot /> <!-- コンテンツはここに挿入されます --><p>{fancyJsHelper()}</p><!-- -->📚 MarkdownとMDXのガイドでAstroのMarkdownとMDXサポートについてもっと学ぶ。
.md、.mdx、.astroに対し同一のレイアウトを使用する
一つのAstroレイアウトで、.mdと.mdxファイルのfrontmatterオブジェクトと、.astroファイルから渡された名前付きのpropsを受け取るように書くことができます。
以下の例では、レイアウトは、フロントマターのYAMLのtitleプロパティまたはtitle属性を渡すAstroコンポーネントからページタイトルを受け取ってそれを表示します。
---const { title } = Astro.props.frontmatter || Astro.props;---<html>  <head></head>  <body>    <h1>{title}</h1>    <slot />  </body></html>レイアウトの入れ子
レイアウトコンポーネントは、ページ全体に相当するHTMLを含む必要はありません。レイアウトをより小さなコンポーネントに分割し、各コンポーネントを組み合わせてより柔軟なページレイアウトを作成できます。このパターンは、複数のレイアウト間でコードを共有したい場合に便利です。
たとえば、BlogPostLayout.astroレイアウトはブログ記事のタイトル、日付、作者にスタイルを付けるとします。そして、サイト全体で共通のBaseLayout.astroは、ナビゲーションやフッター、SEOメタタグ、グローバルスタイル、フォントなどのページテンプレートの残りを処理します。また、他の入れ子になったコンポーネントと同様に、ブログ記事から受け取ったpropsを他のレイアウトに渡すこともできます。
---import BaseLayout from './BaseLayout.astro'const {frontmatter} = Astro.props;---<BaseLayout url={frontmatter.url}>  <h1>{frontmatter.title}</h1>  <h2>投稿者: {frontmatter.author}</h2>  <slot /></BaseLayout>