[Astro] 静的サイトジェネレーター [ページ、レイアウト]
ページ
Astro ページ
.astro
拡張子を使い Astro コンポーネントと同じ機能を持ちます。
src/pages/index.astro
---
---
<html lang="ja">
<head>
<title>Home</title>
</head>
<body>
<h1>Welcom to my site.</h1>
</body>
</html>
全てのページで同じ HTML 要素を繰り返すことを避けるために、共通の <head>
と <body>
要素を独自のレイアウトコンポーネントに移動できます。
src/pages/index.astro
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout>
<p>レイアウトに包まれたコンテンツ</p>
</MySiteLayout>
レイアウト
レイアウトのサンプル
src/layouts/MySiteLayout.astro
---
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, intial-scale=1">
<BaseHead title={ title } />
</head>
<body>
<nav>
<a href="#">Home</a>
<a href="#">Blog</a>
<a href="#">Inquiry</a>
</nav>
<h1>{ title }</h1>
<article>
<slot /> <!-- ここにコンテンツが挿入されます -->
</article>
</body>
</html>
src/pages/index.astro
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout title="Home">
<p>レイアウトに含まれたページのコンポーネント</p>
</MySiteLayout>
Markdown と MDX のレイアウト
Astro では layout
というフロントマターの特別なプロパティを使用して、ページのレイアウトとして使用する .astro
コンポーネントを指定できます。
src/pages/page.md
---
layout: ../layouts/BaseLayout.astro
title: "Hello, World!"
author: "uehara"
date: "2023/01/27"
---
すべてのフロントマターのプロパティは、Astro のレイアウトコンポーネントの rops として利用できます
`layout` プロパティは、Astro が提供する唯一の特別なプロパティです
`src/pages/` 内の Markdown と MDX ファイルの両方で使用できます
src/layouts/BaseLayout.astro
---
// 1. frontmatter prop によりフロントマターとその他のデータにアクセスできます
const { frontmatter } = Astro.props;
---
<html>
<head>
<!-- スタイルや meta タグなど、その他の head 要素をここに追加します -->
<title>{ frontmatter.title }</title>
</head>
<body>
<!-- 共通のヘッダーやフッターなど、他のUI コンポーネントをここに追加します -->
<h1>{ frontmatter.title }, Author { frontmatter.author }</h1>
<!-- 2. レンダリングされた HTML はデフォルトスロットに渡されます -->
<slot />
<p>post: { frontmatter.date }</p>
</body>
</html>
MarkdownLayoutProps
または MDXLayoutProps
を使用して、レイアウトの Props
型を設定できます。
src/layouts/BaseLayout.astro
---
inport type { MarkdownLayoutProps } from 'astro';
type Props = MarkdownLayoutProps<{
// フロントマターの props をここで定義します
title: string;
author: string;
date: string;
}>:
const { frontmatter, url } = Astro.props;
---
<html>
<head>
<meta rel="canonical" href={ new URL(url, Astro.site).pathname }>
<title>{ frontmatter.title }</title>
</head>
<body>
<h1>{ frontmatter.title }, author { frontmatter.author }</h1>
<slot />
<p>post: { frontmatter.date }</p>
</body>
</html>
Markdown レイアウトの Props
Markdown と MDX レイアウトは、Astro.props
を介して次の情報にアクセスできます。
Astro.props = {
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/",
frontmatter: {
/** ブログ記事のフロントマター */
title: "Astro",
date: "2023-01-27",
author: "uehara",
description: "Astro",
/** 生成された値 */
file: "/home/user/projects/.../file.md",
url: "/en/guides/markdown-content/"
},
headings: [
{
"depth": 1,
"text": "Astro",
"slug": "astro"
},
{
"depth": 2,
"text": "Responsive partial hydration",
"slug": "responsive-partial-hydration"
}
/* ... */
],
}
レイアウトを手動でインポートする (MDX)
src/pages/posts/first-post.mdx
---
layout: ../../layouts/BaseLayout.astro
title: 'MDX'
publishDate: '2023-01-27'
---
import BaseLayout from '../../layouts/BaseLayout.astro';
function fancyJsHelper() {
return "YAML";
}
<BaseLayout title={ frontmatter.title } fancyJsHelper={ fancyJsHelper }>
MDX
</BaseLayout>
src/layouts/BaseLayout.astro
---
const { title, fancyJsHelper } = Astro.props;
---
<!-- -->
<h1>{ title }</h1>
<slot /> <!-- コンテンツはここに挿入されます -->
<p>{ fancyJsHelper() }</p>
<!-- -->
.md
, .mdx
, .astro
に対し同一のレイアウトを使用する
src/components/MyLayout.astro
---
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
<head></head>
<body>
<h1>{ title }</h1>
<slot />
</body>
</html>
レイアウトの入れ子
src/layouts/BlogPostLayout.astro
---
import BaseLayout from './BaseLayout.astro'
const {frontmatter} = Astro.props;
---
<BaseLayout url={ frontmatter.url }>
<h1>{ frontmatter.title }</h1>
<h2>post: { frontmatter.author }</h2>
<slot />
</BaseLayout>