注意:この記事はAIが作成しています
参照元の存在、参考元のリンクの信頼度、事実の歪曲がないかをAIによりセルフチェックしています
Astroを使ってマークダウンファイルをアップロードするだけで公開できるWebサイトを構築
はじめに
静的サイトジェネレーター(SSG)の選択肢が増える中、Astroは特にコンテンツ重視のWebサイト構築において注目を集めています。本記事では、Astroを使用してマークダウンファイルを配置するだけで即座に公開可能なWebサイトを構築する方法と、Remarkプラグインを活用した機能拡張について解説します。
Astroとは
Astroは、2021年にリリースされた比較的新しい静的サイトジェネレーターです。「Islands Architecture(アイランドアーキテクチャ)」という設計思想を採用し、必要な部分にのみJavaScriptを使用することで、高速なWebサイトを実現します。
Astroの主な特徴
- ゼロJavaScript by デフォルト: 静的なHTMLを生成し、必要最小限のJavaScriptのみを送信
- マルチフレームワーク対応: React、Vue、Svelte、SolidJSなど複数のフレームワークを同時に使用可能
- 優れたDX(開発者体験): TypeScript、Sass、Tailwind CSSなどをネイティブサポート
- コンテンツファースト: マークダウンやMDXを第一級市民として扱う
プロジェクトのセットアップ
1. Astroプロジェクトの初期化
# npmを使用する場合
npm create astro@latest my-markdown-site
# yarnを使用する場合
yarn create astro my-markdown-site
# pnpmを使用する場合
pnpm create astro@latest my-markdown-site
セットアップウィザードでは以下を選択します:
- テンプレート: "Empty" または "Blog"
- TypeScript: "Strict"(推奨)
- 依存関係のインストール: Yes
2. ディレクトリ構造
my-markdown-site/
├── src/
│ ├── content/
│ │ └── blog/ # マークダウンファイルを配置
│ ├── layouts/
│ │ └── BlogPost.astro
│ └── pages/
│ ├── index.astro
│ └── blog/
│ └── [...slug].astro
├── astro.config.mjs
└── package.json
コンテンツコレクションの設定
1. コンテンツスキーマの定義
src/content/config.ts
を作成し、記事のスキーマを定義します:
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
author: z.string(),
tags: z.array(z.string()).optional(),
image: z.string().optional(),
}),
});
export const collections = {
blog: blogCollection,
};
2. マークダウンファイルの作成
src/content/blog/
ディレクトリに.md
ファイルを配置:
---
title: "Astroで始める静的サイト構築"
description: "Astroを使った効率的なWebサイト開発"
pubDate: 2024-01-15
author: "開発太郎"
tags: ["Astro", "SSG", "Web開発"]
---
# 記事の内容
ここに記事の本文を記述します...
動的ルーティングの実装
ブログ記事ページの作成
src/pages/blog/[...slug].astro
を作成:
---
import { getCollection } from 'astro:content';
import BlogPost from '../../layouts/BlogPost.astro';
export async function getStaticPaths() {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.slug },
props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<BlogPost {...entry.data}>
<Content />
</BlogPost>
Remarkプラグインによる拡張
1. 基本的なRemarkプラグインの導入
npm install remark-gfm remark-toc rehype-slug rehype-autolink-headings
2. astro.config.mjsの設定
import { defineConfig } from 'astro/config';
import remarkGfm from 'remark-gfm';
import remarkToc from 'remark-toc';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
export default defineConfig({
markdown: {
remarkPlugins: [
remarkGfm, // GitHub Flavored Markdown対応
[remarkToc, {
heading: '目次',
tight: true
}],
],
rehypePlugins: [
rehypeSlug, // 見出しにIDを付与
[rehypeAutolinkHeadings, {
behavior: 'append',
content: {
type: 'text',
value: ' 🔗'
}
}],
],
},
});
3. カスタムRemarkプラグインの作成
独自の処理を追加する例:
// plugins/remark-reading-time.mjs
import getReadingTime from 'reading-time';
import { toString } from 'mdast-util-to-string';
export function remarkReadingTime() {
return function (tree, { data }) {
const textOnPage = toString(tree);
const readingTime = getReadingTime(textOnPage);
data.astro.frontmatter.minutesRead = Math.ceil(readingTime.minutes);
};
}
設定への追加:
import { remarkReadingTime } from './plugins/remark-reading-time.mjs';
export default defineConfig({
markdown: {
remarkPlugins: [
remarkReadingTime,
// 他のプラグイン...
],
},
});
高度な機能実装
1. シンタックスハイライト
// astro.config.mjs
export default defineConfig({
markdown: {
shikiConfig: {
theme: 'github-dark',
langs: ['javascript', 'typescript', 'python'],
wrap: true,
},
},
});
2. 画像最適化
---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---
<Image
src={heroImage}
alt="Hero画像"
width={800}
height={400}
format="webp"
/>
3. MDXサポート
npm install @astrojs/mdx
// astro.config.mjs
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
});
デプロイと自動化
GitHub Actionsを使用した自動デプロイ
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
paths:
- 'src/content/**/*.md'
- 'src/**/*.astro'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v2
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v2
パフォーマンス最適化のフロー
ベストプラクティス
1. コンテンツの構造化
- フロントマターでメタデータを統一管理
- タグやカテゴリーによる分類
- 日付形式の統一(ISO 8601推奨)
2. パフォーマンス向上施策
- 画像の遅延読み込み
- フォントの最適化
- Critical CSSの抽出
- プリフェッチの活用
3. SEO対策
---
// SEOコンポーネント
export interface Props {
title: string;
description: string;
image?: string;
}
const { title, description, image = '/og-image.jpg' } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonicalURL} />
<!-- Open Graph -->
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<meta property="og:url" content={canonicalURL} />
トラブルシューティング
よくある問題と解決策
- ビルドエラー: フロントマターの形式を確認
- 画像が表示されない: 相対パスとpublicディレクトリの使い分け
- Remarkプラグインが動作しない: プラグインの順序と設定を確認
まとめ
Astroを使用することで、マークダウンファイルを配置するだけで高品質なWebサイトを構築できます。Remarkプラグインエコシステムを活用することで、目次生成、シンタックスハイライト、読了時間表示など、様々な機能を簡単に追加できます。
静的サイトジェネレーターとしてのAstroの強みは、開発者体験の良さと生成されるサイトのパフォーマンスの高さにあります。コンテンツ重視のWebサイトを構築する際は、ぜひAstroの採用を検討してください。