前書き
こんにちは、Vue.jsとNuxt.jsでJavaScriptフレームワーク入門した者です
少し前にAstroにも手を出しまして、今は便利な世の中になったなあと実感しています
今回は、Astroのエンドポイントを実践します
内容としては、以下のページの内容です
背景情報
実践に移る前に、少し背景情報を書きます
そもそもやりたかったことは、「Astro Studioのデータベースに保存した情報をVueコンポーネントで表示する」ということでした
Astro StudioというAstroサイト向けのプラットフォームがありまして、これにデータベースがあります
そして、それはAstro DBから気軽にアクセスできるように設計されています
これは便利だと思って利用しようとしたのですが、Astro StudioのDBに保存したデータをどうやってVueコンポーネントに渡せばいいかわかりません
Astroにおいて、親コンポーネント(Astro)と子コンポーネント(Vue)間のデータのやりとりの適切な仕方がよくわからないということです
propsとか何かかなとは思いつつ、いまいちイメージがわきません
そのため、ひとまずエンドポイントを使うことにしました
Astro Studioのデータベース
↓ ↑
Astroエンドポイント
↓ ↑
Vueコンポーネント
こんな感じで、データのやりとりをおこないます
最終的には、Astro Studioではなく、CloudflareのD1を使うことにしたのですが、こんな背景があったのだなとご想像ください
今回の記事では、このうちの、AstroエンドポイントとVueコンポーネントの間のみを実装しますが、いずれ、AstroでCloudflare D1を利用するとかも気が向けば書きたいと思います
今回つくるもの
以下のようなものをつくることにしたいと思います
- 「タイトル」と「内容」をセットにしたコンテンツ(以降メモ)を渡すエンドポイントをつくる
- Vueコンポーネントからfetchでメモを取得する
そのうち、メモを保存する機能もつくりますが、今回は固定のメモを取得して、表示するだけです
本編
プロローグ
まずは各種パッケージとかを準備します
便利なものが準備されているので、それらを活用します
npm create astro@latest
↓ 実行結果
> npm create astro@latest
Need to install the following packages:
create-astro@4.8.0
Ok to proceed? (y) y
> npx
> create-astro
astro Launch sequence initiated.
dir Where should we create your new project?
.
tmpl How would you like to start your new project?
Empty
ts Do you plan to write TypeScript?
Yes
use How strict should TypeScript be?
Strict
deps Install dependencies?
Yes
◼ Nice!
Git has already been initialized
▲ error
Error: Timeout
▲ error
Dependencies failed to install, please run npm install to install them manually after setup.
✔ Project initialized!
■ Template copied
■ TypeScript customized
■ Dependencies installed
next Liftoff confirmed. Explore your project!
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 install
up to date, audited 457 packages in 3s
178 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
はい、OKです
では、ひとまず動かしてみます
npm run dev
↓ 実行結果
> npm run dev
> dev
> astro dev
19:32:54 [types] Added src/env.d.ts type declarations.
astro v4.11.0 ready in 605 ms
┃ Local http://localhost:4321/
┃ Network use --host to expose
19:32:55 watching for file changes...
で、http://localhost:4321/
にアクセスします
大丈夫そうです
エンドポイント作成
https://docs.astro.build/ja/guides/endpoints/#静的ファイルのエンドポイントによると、
カスタムエンドポイントを作成するには、.jsまたは.tsファイルを/pagesディレクトリに追加してください。.jsまたは.tsの拡張子はビルドプロセス中に削除されるので、ファイル名には作成したいデータの拡張子を含める必要があります。たとえば、src/pages/data.json.tsは、ビルドすると/data.jsonエンドポイントとなります。
とのことなので、今回はエンドポイントのアドレスをhttp://localhost:4321/v1/memo
とするため、src/pages/v1/memo.ts
というファイルを作成します
ソースコードはドキュメントに則って、以下のようにします
const example = [
{ id: 1, title: "タイトル1", content: "コンテント1" },
{ id: 2, title: "タイトル2", content: "コンテント2" },
]
export async function GET() {
return new Response(
JSON.stringify({
body: { memos: example }
})
)
}
この状態で(npm run dev
して)、http://localhost:4321/v1/memo
にアクセスしてみます
OKですね
次に、Vueコンポーネントでエンドポイントからデータを取得します
Vueコンポーネントでエンドポイントにアクセスする
Vueコンポーネントを使えるように、インテグレーションを追加します
npx astro add @astrojs/vue
↓ 実行結果
> npx astro add @astrojs/vue
✔ Resolving packages...
Astro will run the following command:
If you skip this step, you can always run it yourself later
╭──────────────────────────────────────────────╮
│ npm install @astrojs/vue@^4.5.0 vue@^3.4.29 │
╰──────────────────────────────────────────────╯
√ Continue? ... yes
✔ Installing dependencies...
Astro will make the following changes to your config file:
╭ astro.config.mjs ─────────────────────────────╮
│ import { defineConfig } from 'astro/config'; │
│ │
│ import vue from "@astrojs/vue"; │
│ │
│ // https://astro.build/config │
│ export default defineConfig({ │
│ integrations: [vue()] │
│ }); │
╰───────────────────────────────────────────────╯
√ Continue? ... yes
success Added the following integration to your project:
- @astrojs/vue
VueコンポーネントはComposition APIで実装します
エラー処理はしていません
<script setup>
import { ref, onMounted, computed } from 'vue';
const memos = ref(0);
onMounted(() => {
getMemos();
});
async function getMemos() {
const response = await fetch('v1/memo');
const json = await response.json();
if (json.body.memos) {
memos.value = json.body.memos;
}
}
</script>
<template>
<div>
<dl>
<template v-for="memo in memos">
<dt>{{ memo.id }}:{{ memo.title }}</dt>
<dd>{{ memo.content }}</dd>
</template>
</dl>
</div>
</template>
AstroコンポーネントでVueコンポーネント呼び出し
メインのAstroコンポーネントにDisplayListコンポーネントを呼び出すコードを追加します
このとき、https://docs.astro.build/ja/guides/framework-components/#インタラクティブなコンポーネント にあるように、client:load
を追加する必要があると思います、多分
---
import DisplayList from "../compoents/DisplayList.vue"
---
<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>
<DisplayList client:load/>
</body>
</html>
後、エンドポイントを使うので、astro.config.mjs
に output: 'hybrid'
を追加しておきます(これもわたしには理解できていないおまじないです)
https://docs.astro.build/ja/basics/rendering-modes/#オンデマンドレンダリング
import { defineConfig } from 'astro/config';
import vue from "@astrojs/vue";
// https://astro.build/config
export default defineConfig({
integrations: [vue()],
output: 'hybrid',
});
よさそうですね
まとめ
以上、ドキュメント通りに実践してみました
今後、これをベースにして、メモの追加機能を実装したり、Cloudflare D1と接続してみたりしたいと思います
後、Lucia Authという認証ライブラリを使って、GitHubアカウントによるログイン機能も試したので、それも追々まとめていきます
ここまで、ご清聴ありがとうございました
おまけメモ
{
"name": "",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro check && astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "^0.7.0",
"@astrojs/vue": "^4.5.0",
"astro": "^4.11.0",
"typescript": "^5.5.2",
"vue": "^3.4.29"
}
}