Astro.jsで軽量なブログを作る覚え書き
広島フロントエンド勉強会のサイトをAstroで開発できるようにしたので、このブログも軽量なAstroで開発できるようにするための覚え書き。 (まだしてない)
初期セットアップ
まずは、プロジェクトを作ります。
npm create astro@latest
対話形式で環境を制作できます。
まずはプロジェクトのディレクトリを作ります。 今回はAstroBlog
としています。
サンプルファイルやブログのテンプレートを使うか、必要最低限の空の状態にするかと聞かれるので、今回はEmpty
を十字キーで選びます。
依存関係をインストールするかと聞かれるので、Yes
を選択します。
TypeScriptを使うかと聞かれるので、今回はNo
を選択します。
最後にgitリポジトリをイニシャライズするかと聞かれるのでYes
を選択します(リポジトリがすでにある場合はNoを選択)。
これで初期セットアップは完了です。 インストールが終わると
/
├── README.md
├── astro.config.mjs
├── package-lock.json
├── package.json
├── public
│ └── favicon.svg
├── src
│ ├── env.d.ts
│ └── pages
│ └── index.astro
└── tsconfig.json
このようなディレクトリができあがるので、開発環境を起動します。
npm run dev
http://localhost:3000/
にアクセスするとプレーンな画面が開きます。
Indexファイルと共通レイアウト
では早速さわっていきましょう。 /src/pages/index.astro
を開きます。
---
---
<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" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
</body>
</html>
とりあえずこれを必要最低限に編集します。
---
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
</body>
</html>
続いてページを跨いで利用できる共通のレイアウトを作ります。 /src/layouts
にlayout.astro
を作ります。 <slot />
にはこのレイアウトを使うページのコンテンツが挿入されます。
---
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>Astro</title>
</head>
<body>
<!-- ここにコンテンツが入る -->
<slot />
</body>
</html>
/src/pages/index.astro
をレイアウトを使うように変更します。
---
import Layout from '../layouts/layout.astro';
---
<Layout>
<h1>Astro</h1>
</Layout>
このままだとTitleがどのページも『Astro』になってしまうので変数化します。 /src/layouts/layout.astro
を編集します。
---
// ページから渡ってきたtitleを取得
const { title } = Astro.props
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>{ title }</title>
</head>
<body>
<!-- ここにコンテンツが入る -->
<slot />
</body>
</html>
続いて/src/pages/index.astro
も編集します。
---
import Layout from '../layouts/layout.astro';
---
<Layout title="Indexページ">
<h1>Astro</h1>
</Layout>
/src/pages
にpage.astro
を作ります。
---
import Layout from '../layouts/layout.astro';
---
<Layout title="Pageページ">
<h1>Page</h1>
</Layout>
こちらもちゃんとタイトルが変わっています。
記事の作成
ブログの記事を作っていくのですが、AstroはMarkdownをサポートしているので、Markdownで書いてみます。 /src/pages/posts/
にarticle01.md
を作ります。
# article01
article01のテキストが入ります。
このままだとtitleもなくプレーンなテキストが出るだけなので、こちらもレイアウトを使うように変更します。
---
layout: '../../layouts/layout.astro'
title: 'article01ページ'
---
# article01
article01のテキストが入ります。
http://localhost:3000/posts/article01
にアクセスすると記事ページが表示されます。 しかし、タイトルを設定しているのに反映されていません。 layoutに値が渡っているか見てみます。
---
// ページから渡ってきたtitleを取得
const { title } = Astro.props
console.log(Astro.props);
---
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>{ title }</title>
</head>
<body>
<!-- ここにコンテンツが入る -->
<slot />
</body>
</html>
console.logを書いて、http://localhost:3000/
にアクセスします。 コンソールを見てみると
{ title: 'Indexページ' }
{
file: '/Users/takanashi66/Desktop/AstroBlog/src/pages/posts/article01.md',
url: '/posts/article01',
content: {
title: 'article01ページ',
file: '/Users/takanashi66/Desktop/AstroBlog/src/pages/posts/article01.md',
url: '/posts/article01'
},
frontmatter: {
title: 'article01ページ',
file: '/Users/takanashi66/Desktop/AstroBlog/src/pages/posts/article01.md',
url: '/posts/article01'
},
headings: [ { depth: 1, slug: 'article01', text: 'article01' } ],
rawContent: [Function: rawContent],
compiledContent: [Function: compiledContent],
'server:root': true
}
と出ています。 titleを探してみると indexは
{ title: 'Indexページ' }
article01は
{
〜略〜
frontmatter: {
title: 'article01ページ',
file: '/Users/takanashi66/Desktop/AstroBlog/src/pages/posts/article01.md',
url: '/posts/article01'
},
〜略〜
}
frontmatterというプロパティの中に入っています。 ページ(.astro)と記事(.md)では値の渡し方、持ち方が違うようです。 なので/src/layouts/layout.astro
をページに応じて値を代入するように編集します。
---
// ページから渡ってきたtitleを取得
const { title } = Astro.props.frontmatter || Astro.props;
// console.log(Astro.props);
---
~略~
改めてhttp://localhost:3000/posts/article01
にアクセスするとちゃんとタイトルが出ました。
記事の時だけ親要素を追加する
さて、Indexページとarticle01ページでは両方bodyの直下にコンテンツが出てきます。 それぞれのページで別のスタイルを当てたい場合など、astroファイルならHTMLが直接書けるので、問題ないですがMarkdownではそうもいかないので、layoutで対応していきます。 /src/layouts/
にpostLayout.astro
を作ります。
---
import Layout from '../layouts/layout.astro';
const { title } = Astro.props.frontmatter;
---
<Layout title={title}>
<article class="post">
<slot />
</article>
</Layout>
記事ページのレイアウトを上記で作ったレイアウトに変更します。
---
layout: '../../layouts/postLayout.astro'
title: 'article01ページ'
---
# article01
article01のテキストが入ります。
レイアウトファイルの中からさらにレイアウトファイルを呼ぶことで、共通レイアウトを維持したまま親要素をコントロールすることができます。
記事一覧の作成
/src/pages/posts/article01.md
をコピーしてarticle02.md
を作ります。
---
layout: '../../layouts/layout.astro'
title: 'article02ページ'
---
# article02
article02のテキストが入ります。
/src/pages/index.astro
のIndexページに記事の一覧が出るようにしましょう。 Astro.glob
を使って.mdファイルを取得します。 取得した.mdファイルの情報をmapで回してURLとtitleを出力します。
---
import Layout from '../layouts/layout.astro';
// posts内の.mdファイルを取得
const posts = await Astro.glob('./posts/**/*.md')
---
<Layout title="Indexページ">
<h1>Astro</h1>
<h2>記事一覧</h2>
<ul>
{
posts.map(post => {
return <li><a href={post.url}>{post.frontmatter.title}</a></li>
})
}
</ul>
</Layout>
記事の一覧のリンクが出力されました。
Build
最後に公開用のファイルを出力します。
npm run build
すると dist
というディレクトリが作られ、そこにHTMLが出力されます。
dist
├── favicon.svg
├── index.html
├── page
│ └── index.html
└── posts
├── article01
│ └── index.html
└── article02
└── index.html