ゲーム開発
Unity
UnrealEngine
C++
ゲーム数学
ゲームAI
サウンド
アニメーション
GBDK
制作日記
3DCG
Houdini
Blender
USD
グラフィックス
テクノロジ
ツール開発
フロントエンド関連
サーバサイド関連
ソフトウェア設計
ハードウェア関連
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
その他
都会のエレキベア
ラーメン日記
四コマ漫画
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • ゲーム数学
    • ゲームAI
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • 3DCG
    • Houdini
    • Blender
    • USD
    • グラフィックス
  • テクノロジ
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • ソフトウェア設計
    • ハードウェア関連
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • その他
    • 都会のエレキベア
    • ラーメン日記
    • 四コマ漫画
    • おすすめアイテム
    • おもしろコラム
  1. ホーム
  2. 20260201_01_astro_basic

【Astro】Astroの使い方と複数UIフレームワーク(React、Vue、Svelte)を組み合わせるサンプル

JavaScriptReactAstroTypeScriptVue.jsSvelte
2026-02-01

ぷらずも
ぷらずも
みなさんこんにちは! ぷらずもです。
エレキベア
エレキベア
こんにちクマ〜〜
ぷらずも
ぷらずも
今日は久しぶりにフロントエンド関連の技術を触ってみます。 取り上げるのは、前々から気になっていた Astro です!
エレキベア
エレキベア
Astroクマか なんか聞いたことあるクマ
ぷらずも
ぷらずも
State of JavaScriptでも年々使用率が上がっていて、話題になることも多かったからね。 静的サイト生成に特化したフレームワーク で、ブログやポートフォリオ作成などに適しています。
20260201_01_01

20260201_01_06
▲年々使用率が上がってきている

エレキベア
エレキベア
確かにこの伸び率は何かありそうクマね どんなものか気になるクマ〜〜〜

Astroとは

ぷらずも
ぷらずも
それでは改めてAstroについてですが、静的サイト生成に特化したフレームワークです。 Next.js等のWebアプリフレームワークと比べるとシンプルで、アーランドアーキテクチャ という設計思想により様々なメリットがあります。
✔ Astroとは
  • コンテンツ駆動のウェブサイトを制作するためのフレームワーク
    • アイランドアーキテクチャにより様々なメリットがある
    • ブログ、 ポートフォリオなどの静的サイトを作るのに向いている
      • Markdownコンテンツの使用がデフォルトで考慮されている
エレキベア
エレキベア
アイランドアーキテクチャ・・・ 気になるクマ
ぷらずも
ぷらずも
アイランドアーキテクチャは、それぞれの要素をアイランド(島)の単位として独立して考えるアーキテクチャを表しているようです。 これによりJavaScriptが必要な箇所のみ読み込むようにしたり、React、VueといったUIフレームワークも任意に組み合わせることができます。

Islands architecture | Docs

✔ アイランドアーキテクチャのメリット
  • 必要最低限の箇所のみJavaScriptを読み込む(デフォルトでゼロJS
  • 複数のUIフレームワークを組み合わせることができる
  • 主要なインテグレーション機能が用意されていて組み合わせることができる

20260201_01_05
▲それぞれの要素を独立したアイランドとしてkジャンガエル

エレキベア
エレキベア
React、Vueも混在できるのクマか・・・ 依存関係も整理出来そうで、設計としても綺麗クマね
ぷらずも
ぷらずも
その他のメリットとして、様々なテーマ(テンプレート)が用意されているのも大きな魅力だと思います。 こちらのテンプレートに手を加えて作る、なども気軽に出来そうですね。

Themes | Astro

20260201_01_07
▲様々なテーマが用意されている

エレキベア
エレキベア
これはWordpressなんかより断然にいいクマ ゴホンゴホン、なんでもないクマ

Astroの基本的な使い方

ぷらずも
ぷらずも
次にAstroの使い方について記載しようと思いますが、正直公式チュートリアルがかなり分かりやすかったのでそちらを一通り行うのがおすすめです。

Build a blog tutorial | Docs
▲公式チュートリアル

20260201_01_02
▲チュートリアルを通してシンプルなブログの作り方を学ぶ

20260201_01_03
▲Markdownによる記事管理まで解説している

エレキベア
エレキベア
まさにAstroに興味あるユーザが求めているチュートリアルクマね
ぷらずも
ぷらずも
今回はこのチュートリアルの中からいくつか主要な部分を抜粋して記載します。

プロジェクト作成

  1. npm create コマンドのみでプロジェクトを作成する (質問内容は用途にあわせて選択する)

    > npm create astro@latest
    
    Need to install the following packages:
    create-astro@4.13.2
    Ok to proceed? (y) y
    
    astro   Launch sequence initiated.
    
    dir   Where should we create your new project?
    		./astro-blog-tutorial
    
    tmpl   How would you like to start your new project?
    		Use minimal (empty) template
    
    deps   Install dependencies?
    		Yes
    
    git   Initialize a new git repository?
    		Yes
    
    	✔  Project initialized!
    		■ Template copied
    		■ Dependencies installed
    		■ Git initialized
    
    next   Liftoff confirmed. Explore your project!
    
    		Enter your project directory using cd ./astro-blog-tutorial
    		Run npm run dev to start the dev server. CTRL+C to stop.
    		Add frameworks like react or tailwind using astro add.
    
    		Stuck? Join us at https://astro.build/chat
    npm notice
    npm notice New major version of npm available! 10.2.4 -> 11.8.0
    npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.8.0
    npm notice Run npm install -g npm@11.8.0 to update!
    npm notice
    
  2. npm run dev コマンドで起動する

    cd [プロジェクト名]
    npm run dev
    
  3. デフォルトページが表示される

    20260201_01_08

基本構成

  • astroファイル

    • astro拡張子の中にHTMLを書くとそれが表示される
    • ---で囲んだ部分にはスクリプトを記載でき、HTML内で参照できる
    ---
    
    const PageTitle = "Astro";
    ---
    
    <html lang="en">
    	<head>
    		<meta charset="utf-8" />
    		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    		<link rel="icon" href="/favicon.ico" />
    		<meta name="viewport" content="width=device-width" />
    		<meta name="generator" content={Astro.generator} />
    		<title>{PageTitle}</title>
    	</head>
    	<body>
    		<h1>{PageTitle}</h1>
    	</body>
    </html>
    
    
  • ルーティング

    • src/pages配下に置いたファイル名がそのままパスになる
    src
    ├── components
    ├── layouts
    ├── pages
    │   ├── about.astro
    │   ├── blog.astro
    │   ├── index.astro
    │   ├── posts
    │   │   ├── post-1.md
    │   │   ├── post-2.md
    │   │   ├── post-3.md
    │   │   └── post-4.md
    │   ├── rss.xml.js
    │   └── tags
    │       ├── [tag].astro
    │       └── index.astro
    ├── scripts
    └── styles
    
      • /about/
      • /blog/
      • /posts/post-1/
  • Markdown

    • デフォルトでMarkdownをサポートしていて、メタ情報も埋め込める
    • ※メタ情報の参照については後述
    ---
    title: "My First Post"
    pubDate: 2026-02-01
    description: "This is my first post"
    author: "plasmo310"
    image:
    url: "https://docs.astro.build/assets/rose.webp"
    alt: "logo by astro。"
    tags: ["astro", "blog", "tutorial"]
    ---
    
    # My First Post
    
    ## Topic 1
    
    - XXX
    - XXX
    
    ## Topic 2
    
    - XXX
    - XXX
    
    

コンポーネント

  • astro拡張子で作成したファイルはコンポーネントとしても扱うことができる

    • コンポーネントの引数は Astro.props で取得する
    • 例えばSNS情報を記載したコンポーネントをFooterコンポーネント内で使うなどが行える
    ---
    const { label, platform, username } = Astro.props;
    ---
    
    <div>
    	{label}: <a href={`https://www.${platform}.com/${username}`}>{username}</a>
    </div>
    
    ---
    import Social from "./Social.astro";
    ---
    
    <style>
    	.social-list {
    		display: flex;
    		flex-flow: column;
    		gap: 1rem;
    		margin-top: 2rem;
    	}
    </style>
    
    <footer>
    	<div class="social-list">
    		<Social label="X" platform="twitter" username="plasmo310" />
    		<Social label="GitHub" platform="github" username="plasmo310" />
    	</div>
    </footer>
    
    
    ---
    import Header from '../components/Header.astro';
    import Footer from '../components/Footer.astro';
    import '../styles/global.css';
    
    const { pageTitle } = Astro.props;
    ---
    <html lang="ja">
    <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>{pageTitle}</title>
    </head>
    <body>
    	<Header />
    	<h1>{pageTitle}</h1>
    	<Footer />
    	<script>
    	import "../scripts/menu.js";
    	</script>
    </body>
    </html>
    

ページレイアウト

  • ページレイアウトとしても使用することができる

    • 囲んだHTML要素は slotタグ を使用して設定できる
    ---
    import Header from '../components/Header.astro';
    import Footer from '../components/Footer.astro';
    import '../styles/global.css';
    
    const { pageTitle } = Astro.props;
    ---
    <html lang="ja">
    <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>{pageTitle}</title>
    </head>
    <body>
    	<Header />
    	<h1>{pageTitle}</h1>
    	<slot />
    	<Footer />
    	<script>
    	import "../scripts/menu.js";
    	</script>
    </body>
    </html>
    
    ---
    import Greeting from '../components/Greeting';
    import BaseLayout from '../layouts/BaseLayout.astro';
    import '../styles/global.css';
    
    const pageTitle = "My Astro Blog";
    ---
    
    <BaseLayout pageTitle={pageTitle}>
    	<h2>By Astro Official Tutorial</h2>
    	<Greeting client:load messages={["Hello", "Yah", "Hej"]} />
    </BaseLayout>
    
    
  • Markdownにもlayoutメタ情報にパスを指定することで適用できる

    • Markdownのメタ情報は Astro.props内の frontmatter として渡される
    ---
    layout: ../../layouts/MarkdownPostLayout.astro
    title: "My First Post"
    pubDate: 2026-02-01
    description: "This is my first post"
    author: "plasmo310"
    image:
    url: "https://docs.astro.build/assets/rose.webp"
    alt: "logo by astro。"
    tags: ["astro", "blog", "tutorial", "test"]
    ---
    
    ## Topic 1
    
    - XXX
    - XXX
    
    ## Topic 2
    
    - XXX
    - XXX
    
    
    ---
    import BaseLayout from "./BaseLayout.astro";
    
    const { frontmatter } = Astro.props;
    ---
    <BaseLayout pageTitle={frontmatter.title}>
    	<p>Date: {frontmatter.pubDate.toString().slice(0, 10)}</p>
    	<p>Author: {frontmatter.author}</p>
    	<img
    		src={frontmatter.image.url}
    		width="300"
    		alt={frontmatter.image.alt}
    	/>
    	<div class="tags">
    		{frontmatter.tags.map((tag: string) => (
    			<p class="tag"><a href={`/tags/${tag}`}>{tag}</a></p>
    		))}
    	</div>
    	<slot />
    </BaseLayout>
    
    <style>
    a {
    	color: #00539F;
    }
    
    .tags {
    	display: flex;
    	flex-wrap: wrap;
    }
    
    .tag {
    	margin: 0.25em;
    	border: dotted 1px #a1a1a1;
    	border-radius: .5em;
    	padding: .5em 1em;
    	font-size: 1.15em;
    	background-color: #F8FCFD;
    }
    </style>
    
    

動的ルーティング

  • 動的ルーティング

    • []で囲むことで動的ルーティングを定義できる
    src
    ├── components
    ├── layouts
    ├── pages
    │   ├── ...
    │   └── tags
    │       ├── [tag].astro
    │       └── index.astro
    ├── scripts
    └── styles
    
    • getStaticPaths関数内で返却した配列がパスとして設定される
      • この時、propsも設定して渡すことができる
    ---
    import BlogPost from '../../components/BlogPost.astro';
    import BaseLayout from '../../layouts/BaseLayout.astro';
    
    export async function getStaticPaths() {
    const allPosts = Object.values(import.meta.glob('../posts/*.md', { eager: true }));
    const uniqueTags = [...new Set(allPosts.map((post: any) => post.frontmatter.tags).flat())];
    
    return uniqueTags.map((tag: string) => {
    	const filteredPosts = allPosts.filter((post: any) => post.frontmatter.tags.includes(tag));
    	return {
    		params: { tag },
    		props: { posts: filteredPosts }
    	}
    });
    }
    
    const { tag } = Astro.params;
    const { posts } = Astro.props;
    ---
    <BaseLayout pageTitle={`tag: ${tag}`}>
    <p>{tag} posts</p>
    <ul>
    	{posts.map((post: any) => <BlogPost url={post.url} title={post.frontmatter.title} />)}
    </ul>
    </BaseLayout>
    
      • /tags/astro/
      • /tags/tutorial
      • /tags/

インタラクティブJS

  • ---で囲んだ部分のスクリプトや、UIフレームワークを用いたコンポーネントのスクリプトはデフォルトでビルド時しか実行されない

  • そのため、インタラクティブにスクリプトを実行したい場合には、以下のいずれかの対応を行う

    • UIフレームワークを用いたコンポーネントにclientタグ(client::loadなど)を指定する
    import { useState } from "preact/hooks";
    
    export default function Greeting({ messages }) {
    const randomMessage = () =>
    	messages[Math.floor(Math.random() * messages.length)];
    
    const [greeting, setGreeting] = useState(messages[0]);
    
    return (
    	<div>
    	<h3>{greeting}! Thank you!!</h3>
    	<button onClick={() => setGreeting(randomMessage())}>New Greeting</button>
    	</div>
    );
    }
    
    
    • scriptタグで囲んでスクリプトを記述する
    ---
    import Greeting from '../components/Greeting';
    import BaseLayout from '../layouts/BaseLayout.astro';
    import '../styles/global.css';
    
    const pageTitle = "My Astro Blog";
    ---
    
    <BaseLayout pageTitle={pageTitle}>
    	<h2>By Astro Official Tutorial</h2>
    	<Greeting client:load messages={["Hello", "Yah", "Hej"]} />
    </BaseLayout>
    
    
ぷらずも
ぷらずも
主な使い方としてはこんな感じです!
エレキベア
エレキベア
シンプルで分かりやすいクマね propsや動的ルーティングもNext.js使っていれば馴染むクマ

複数UIフレームワークを組み合わせる

ぷらずも
ぷらずも
簡単な使い方が分かったところで、次はAstroの大きな魅力である 複数UIフレームワークを混在させるサンプル を実装してみようと思います。 今回は React、Vue、Svelte を用いてそれぞれのカウントコンポーネントを表示してみました。
20260201_01_04
▲複数UIフレームワークを用いたサンプル

GitHub - astro-multi-framework-sample
▲GitHubリポジトリ

エレキベア
エレキベア
うーむ、ほんとに混在できるのクマね・・・
ぷらずも
ぷらずも
環境セットアップも簡単で、npx astro add コマンドで必要なパッケージを入れるのみ です。 あとはデフォルトで通常のコンポーネントとして使用できて、デフォルトでTypeScriptも使えます。

環境セットアップ

npx astro add react
npx astro add vue
npx astro add svelte
▲各パッケージの追加

メインとなるスクリプト

---
import ReactCounter from "../components/ReactCounter";
import VueCounter from "../components/VueCounter.vue";
import SvelteCounter from "../components/SvelteCounter.svelte";
---

<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<link rel="icon" href="/favicon.ico" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Multiple UI Framework Sample</title>
	</head>
	<body>
		<h1>Multiple Framework Sample</h1>
		<h2>React</h2>
		<ReactCounter client:load />
		<h2>Vue</h2>
		<VueCounter client:load />
		<h2>Svelte</h2>
		<SvelteCounter client:load />
	</body>
</html>
▲複数のUIフレームワークを同じ画面に表示できる
import { useState } from "react";

function ReactCounter() {
  const [count, setCount] = useState<number>(0);
  const doubled = count * 2;

  return (
    <div>
      <p>Count: {count}</p>
      <p>Doubled: {doubled}</p>
      <button type="button" onClick={() => setCount((prev) => prev + 1)}>
        Add
      </button>
      <button type="button" onClick={() => setCount(0)}>
        Reset
      </button>
    </div>
  );
}
export default ReactCounter;
▲React版コンポーネント
<script lang="ts" setup>
import { computed, ref } from "vue";

const count = ref<number>(0);
const doubled = computed(() => count.value * 2);

const increment = (): void => {
  count.value += 1;
};

const reset = (): void => {
  count.value = 0;
};
</script>

<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Doubled: {{ doubled }}</p>
    <button type="button" @click="increment">Add</button>
    <button type="button" @click="reset">Reset</button>
  </div>
</template>
▲Vue版コンポーネント
<script lang="ts">
	let count = 0;
	$: doubled = count * 2;

	function increment(): void {
		count += 1;
	}

	function reset(): void {
		count = 0;
	}
</script>

<div>
	<p>Count: {count}</p>
	<p>Doubled: {doubled}</p>
	<button type="button" on:click={increment}>Add</button>
	<button type="button" on:click={reset}>Reset</button>
</div>
▲Svelte版コンポーネント
エレキベア
エレキベア
それぞれの書き方の違いも分かって勉強にもなるクマね
ぷらずも
ぷらずも
他にもSolid.jsなども使えたりするので、好きなUIフレームワークを使って実装を試してみましょう!

おわりに

ぷらずも
ぷらずも
というわけで今回は Astro の紹介でした! どうだったかな?
エレキベア
エレキベア
Next.jsよりも断然シンプルで使いやすそうに思ったクマ 設計思想も綺麗でいいクマね
ぷらずも
ぷらずも
機能モリモリなNext.jsに対してシンプル・軽量さが際立つAstro! ぜひブログやポートフォリオ制作に活用してみてはいかがでしょうか
ぷらずも
ぷらずも
それでは今日はこの辺で! アデューー!
エレキベア
エレキベア
クマ〜〜〜〜

JavaScriptReactAstroTypeScriptVue.jsSvelte
2026-02-01
記事をSNSで共有する
X
Facebook
LINE
はてなブックマーク
Pocket
LinkedIn
Reddit

著者の各種アカウント
フォローいただけると大変励みになります!
X
GitHub

関連記事
【VSCode】ドラッグ&ドロップで画像ファイルをリサイズ・保存する拡張機能を作る
2025-11-22
【ゲーム数学】第九回 p5.jsで学ぶゲーム数学「フーリエ解析」
2024-05-12
【Node.js】廃止されたAmazonアソシエイト画像リンクをAmazon Product Advertising API経由で復活させる
2024-01-08
【都会のエレキベア】ブログを大幅リニューアル!WordPressからNext.jsに移行するまでの流れをまとめる
2024-01-01
【Next.js】第四回 WordPressブログをNext.jsに移行する 〜サーバ移行・SEO・広告設定編〜
2023-12-31
【Next.js】第三回 WordPressブログをNext.jsに移行する 〜Markdown執筆環境構築編〜
2023-12-31
【Next.js】第二回 WordPressブログをNext.jsに移行する 〜WordPressデータの移行・表示編〜
2023-12-31
【Next.js】第一回 WordPressブログをNext.jsに移行する 〜全体設計、環境構築編〜
2023-12-31