レイアウト
レイアウトは、ページテンプレートのような再利用可能なUI構造を作成するために使用されるAstroコンポーネントです。
ヘッダーやナビゲーションバー、フッターなど、ページ間で共有される共通のUIを提供するAstroコンポーネントには、慣習的に「レイアウト」という用語が使われます。典型的なAstroのレイアウトコンポーネントは、Astro、Markdown、またはMDXのページに以下を提供します。
- ページシェル(
<html>,<head>,<body>タグ) - 個々のページコンテンツが挿入される場所を指定する
<slot />
ただし、レイアウトコンポーネントに何か特別なところがあるわけではありません。他のAstroコンポーネントと同様に、propsを受け取り、他のコンポーネントをインポートして使用できます。UIフレームワークコンポーネント (EN)やクライアントサイドスクリプト (EN)も含められます。ページ全体のシェルを提供する必要すらなく、代わりに部分的なUIテンプレートとしても使用可能です。
レイアウトコンポーネントがページシェルを含んでいる場合、レイアウトコンポーネントの<html>タグは他の全てのタグの親である必要があります。
レイアウトコンポーネントは一般的にプロジェクト内のsrc/layoutsディレクトリに配置されますが、これは必須ではなく、プロジェクト内のどこに置いても構いません。レイアウトコンポーネントをページと同じ場所に置くこともでき、その場合はレイアウト名の先頭に_を付けます (EN)。
レイアウトのサンプル
Section titled “レイアウトのサンプル”---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> <style> h1 { font-size: 2rem; } </style></html>---import MySiteLayout from '../layouts/MySiteLayout.astro';---<MySiteLayout title="ホームページ"> <p>レイアウトに包まれたページのコンテンツ</p></MySiteLayout>レイアウトでTypeScriptを使用する
Section titled “レイアウトでTypeScriptを使用する”どのAstroレイアウトでも、propsに型を定義することで、型安全性と自動補完を導入できます:
---interface Props { title: string; description: string; publishDate: string; viewCount: number;}const { title, description, publishDate, viewCount } = Astro.props;---<html lang="ja"> <head> <meta charset="UTF-8"> <meta name="description" content={description}> <title>{title}</title> </head> <body> <header> <p>Published on {publishDate}</p> <p>Viewed by {viewCount} folks</p> </header> <main> <slot /> </main> </body></html>Markdownのレイアウト
Section titled “Markdownのレイアウト”ページレイアウトは、ページフォーマットをもたない個別のMarkdownページにとって特に便利です。
Astroは、ファイルベースルーティングを使用してsrc/pages/内に配置される個別の.mdファイル (EN)向けに、特別なlayoutフロントマタープロパティを提供しています。これにより、ページレイアウトとして使用する.astroコンポーネントを指定できます。このコンポーネントを使用すると、メタタグ(例: <meta charset="utf-8">)やスタイルなどの<head>コンテンツをMarkdownページに提供できます。デフォルトでは、指定されたコンポーネントはMarkdownファイルからデータに自動的にアクセスできます。
ただしコンテンツコレクション (EN)を使ってコンテンツをクエリ・レンダリングする場合、このプロパティは特別なものとして認識されません。
---layout: ../layouts/BlogPostLayout.astrotitle: "Hello, World!"author: "Matthew Phillips"date: "2022年8月9日"---すべてのフロントマターのプロパティは、Astroのレイアウトコンポーネントのpropsとして利用できます。
`layout`プロパティは、Astroが提供する唯一の特別なプロパティです。
`src/pages/`内のMarkdownファイルで使用できます。Markdownページの典型的なレイアウトは以下を含みます。
- Markdownページのフロントマターとその他のデータにアクセスするための
frontmatterプロパティ。 - ページのMarkdownコンテンツをレンダリングする場所を示すためのデフォルトの
<slot />。
---// 1. frontmatter propによりフロントマターとその他のデータにアクセスできますconst { frontmatter } = Astro.props;---<html> <head> <!-- スタイルやmetaタグなど、その他のhead要素をここに追加します --> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8"> <title>{frontmatter.title}</title> </head> <body> <!-- 共通のヘッダーやフッターなど、他のUIコンポーネントをここに追加します --> <h1>{frontmatter.title} {frontmatter.author}著</h1> <!-- 2. レンダリングされたHTMLはデフォルトスロットに渡されます --> <slot /> <p>投稿日: {frontmatter.date}</p> </body></html>MarkdownLayoutPropsを使用して、レイアウトのProps型 (EN)を設定できます。
---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> <meta charset="utf-8"> <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
Section titled “MarkdownレイアウトのProps”Markdownレイアウトは、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 }[]。rawContent()- 生のMarkdownドキュメントを文字列として返す関数。compiledContent()- MarkdownドキュメントをHTML文字列にコンパイルして返すasync関数。
Markdownレイアウトは、Astro.propsからMarkdownファイルの利用可能なプロパティ (EN)すべてにアクセスできますが、2つの重要な違いがあります:
-
見出し情報(つまり
h1 -> h6要素)は、getHeadings()関数ではなく、headings配列を介して利用できます。 -
fileとurlは、ネストされたfrontmatterプロパティ(つまりfrontmatter.urlとfrontmatter.file)としても利用できます。
レイアウトを手動でインポートする(MDX)
Section titled “レイアウトを手動でインポートする(MDX)”MDXファイルのフロントマターでも、特別なMarkdownのlayoutプロパティを使って、同じように指定したレイアウトコンポーネントへfrontmatterとheadingsのpropsを直接渡すことができます。
MDXレイアウトに、フロントマターには存在しない(または存在しようがない)情報を渡すには、代わりに<Layout />コンポーネントをインポートして使用できます。これは他のAstroコンポーネントと同じように動作し、propsは自動で受け取りません。必要なpropsを直接渡してください。
---layout: ../../layouts/BaseLayout.astrotitle: '初めてのMDX記事'publishDate: '2022年9月21日'---import BaseLayout from '../../layouts/BaseLayout.astro';
export function fancyJsHelper() { return "YAMLでやってみよう!";}
<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}> MDXを使用した新しいAstroブログへようこそ!</BaseLayout>すると、レイアウトのAstro.propsを介して値が利用でき、MDXコンテンツは<slot />コンポーネントが書かれている場所に挿入されます。
---const { title, fancyJsHelper } = Astro.props;---<html> <head> <!-- --> <meta charset="utf-8"> </head> <body> <!-- --> <h1>{title}</h1> <slot /> <!-- your content is injected here --> <p>{fancyJsHelper()}</p> <!-- --> </body></html>レイアウトを使用する場合(frontmatterのlayoutプロパティを使用するか、レイアウトをインポートするかに関わらず)、レイアウトに <meta charset="utf-8"> タグを含める必要があります。AstroはMDXページにこのタグを自動的に追加しなくなったためです。
レイアウトの入れ子
Section titled “レイアウトの入れ子”レイアウトコンポーネントは、ページ全体に相当する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>