0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめての記事投稿
Qiita Engineer Festa20242024年7月17日まで開催中!

Astroで自前のエンドポイントを作成して、Vueコンポーネントでデータを取得する

Posted at

前書き

こんにちは、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/にアクセスします

image.png

大丈夫そうです

エンドポイント作成

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というファイルを作成します

ソースコードはドキュメントに則って、以下のようにします

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にアクセスしてみます

image.png

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で実装します
エラー処理はしていません

src/components/DisplayList.vue
<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を追加する必要があると思います、多分

src/pages/index.astro
---
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/#オンデマンドレンダリング

astro.config.mjs
import { defineConfig } from 'astro/config';

import vue from "@astrojs/vue";

// https://astro.build/config
export default defineConfig({
  integrations: [vue()],
  output: 'hybrid',
});

そして、動作確認です
image.png

よさそうですね

まとめ

以上、ドキュメント通りに実践してみました

今後、これをベースにして、メモの追加機能を実装したり、Cloudflare D1と接続してみたりしたいと思います

後、Lucia Authという認証ライブラリを使って、GitHubアカウントによるログイン機能も試したので、それも追々まとめていきます

ここまで、ご清聴ありがとうございました

おまけメモ

package.json
{
  "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"
  }
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?