6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vite × preact × Typescript × Prisma × PlanetScale × Netlify 入門

Posted at

PlanetScale を触ってみたいと思っていたので、簡易的なアプリを作成しました。
Vite、preact、も以前から気になっていたので、参考になれば嬉しいです。

構成

  • ビルドツール
    • vite
  • データベース
    • PlanetScale
  • サーバ
    • Netlify
  • アプリケーション
    • preact, Typescript, Prisma

始める前に結論

  • 無料枠が大きいので個人開発で遊ぶのにも十分だと思う
  • UXが最高。ほとんどのプログラマーがgithubユーザーだと思うので、直感的に操作することが可能
  • mysqlで抱えていた、本番DBと開発DBの情報に差分が発生して意図しないバグを生じてしまう問題を上手く解決してくれそう(上記に記載したように、githubのようなユーザー体験が提供されているためschema変更のrevartなんかも可能)

始める前の準備

PlanetScale と Netlify はそれぞれ cli が用意されているのでインストールしておく

npm install netlify-cli -g
netlify // インストールされているか確認

⬥ Netlify CLI
Read the docs: https://www.netlify.com/docs/cli
Support and bugs: https://github.com/netlify/cli/issues

VERSION
  netlify-cli/9.16.6 darwin-x64 node-v14.17.0

Vite プロジェクト作成

適当なディレクトリを作成

mkdir ディレクトリ名
cd ディレクトリ名
npm init vite@latest .

プロジェクト名等々、何を利用するか問われるので以下の項目を入力・選択

npm init vite@latest
npx: 6個のパッケージを3.977秒でインストールしました。
✔ Project name: … プロジェクト名
✔ Select a framework: › preact
✔ Select a variant: › preact-ts

cd プロジェクト名
npm i

プロジェクト作成完了
ローカルサーバを走らせる

netlify dev

◈ Netlify Dev ◈
◈ Ignored general context env var: LANG (defined in process)
◈ Starting Netlify Dev with Vite

   ┌─────────────────────────────────────────────────┐
   │                                                 │
   │   ◈ Server now ready on http://localhost:8888   │
   │                                                 │
   └─────────────────────────────────────────────────┘

補足: netlify devコマンドに関しては以下を参照
Run the entire Netlify platform right from your terminal

http://localhost:8888でプロジェクトが正常に立ち上がっているか確認
スクリーンショット 2022-04-25 14.07.47.png

PlanetScale の設定

補足: PlanetScale のアカウントをまだ作成していなければ、以下を参照
PlanetScaleというサーバレスDBが凄く勢いのあるサービスらしいのでQuick Startやってみた
pscale cli 取得

$ npm i scale -g
$ which sclae

ターミナルから PlanetScale へ login

$ pscale auth login
 Confirmation Code: ここに認証用コードが表示される

ブラウザで planetscale 認証ページが自動で開かれるので、ターミナル上に出力される認証用コードと一致しているか確認。問題なければブラウザ上に表示されている、「Confirme code」ボタンをクリック

開発用ブランチを作成する

$ pscale branch create データベース名 dev // devは任意のブランチ名

shadowブランチを作成する
※ このブランチはPrismaのmigrations用に使われる

$ pscale branch create データベース名 shadow // devは任意のブランチ名

正常に上記設定が行われているか確認
ローカルからデータベースへ接続

$ pscale connect データベース名 dev[ブランチ名] --port 3309
$ pscale connect データベース名 shadow[ブランチ名] --port 3310

エディタで本プロジェクトコードを展開して.envファイルを追加
追加した.envファイルに以下記述

DATABASE_URL="mysql://root@127.0.0.1:3309/データベース名"
SHADOW_DATABASE_URL="mysql://root@127.0.0.1:3310/データベース名"

Prisma の設定

prisma をプロジェクトに追加

npm i -D prisma
npm i @prisma/client

schemaファイルを生成

npx prisma init

schema.prismaを以下のように修正

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
  shadowDatabaseUrl      = env("SHADOW_DATABASE_URL")
  referentialIntegrity = "prisma"
}

アプリ用モデルをschema.prismaに追加する

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
  shadowDatabaseUrl      = env("SHADOW_DATABASE_URL")
  referentialIntegrity = "prisma"
}

model Post {
  id Int @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @default(now())
  title String @db.VarChar(255)
  content String
}

上記で定義した schema を基にテーブルを作成

$ npx prisma migrate dev

新しいマイグレーション name を入力

Enter a name for the new migration: ... init

試験用データをテーブルに追加する

$ npx prisma studio
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Prisma Studio is up on http://localhost:5555

ブラウザでhttp://localhost:5555を開く
スクリーンショット 2022-04-25 21.44.06.png
schema ファイルを基に prisma client を生成

$ Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma

✔ Generated Prisma Client (3.12.0 | library) to ./node_modules/@prisma/client in 70ms
You can now start using Prisma Client in your code. Reference: https://pris.ly/d/client

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

npx prisma generateコマンドはスキーマを取得し、typescript定義を持つprismaクライアントを作成して、データベースとのやり取りに必要なものを自動で準備してくれる

serverless functionを定義

プロジェクトのルートディレクトリにnetlify/functions/posts.tsを作成する.
ファイル内は以下のような構成.
処理の内容は post した情報をDBから取得して返すだけのシンプルなもの.

import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();

export async function handler() {
  try {
    const posts = await prisma.post.findMany();
    return {
      statusCode: 200,
      header: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(posts),
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify(error),
    };
  }
}

ちなみに、Netlify の Netlify function とは Netlify が提供しているアドオンの1つで、サーバーサイドの機能を簡単に公開できるサービスです。AWS Lambda をラップして使いやすいように提供されており、 AWSにアカウントを用意する必要もありません。NetlifyのプロジェクトとGitリポジトリを連携するだけでOK。Netlifyが代わりにデプロイをしてくれる上に、HTTPで呼び出せる機能がすぐに用意できる代物。

上記コードが正常に機能するかテストする
ローカルサーバを起動(もし起動していなければ)

$ netlify dev
◈ Netlify Dev ◈
◈ Ignored build settings env var: DATABASE_URL (defined in .env file)
◈ Injected .env file env var: DATABASE_URL
◈ Ignored general context env var: LANG (defined in process)
◈ Injected .env file env var: SHADOW_DATABASE_URL
◈ Loaded function post.
◈ Loaded function posts.
◈ Functions server is listening on 62987
◈ Starting Netlify Dev with Vite

> prisma-serverless@0.0.0 dev /Users/ryoma_kishimoto/Desktop/prisma-serverless-planetscale-netlify/prisma-serverless
> vite


  vite v2.9.5 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 540ms.


   ┌─────────────────────────────────────────────────┐
   │                                                 │
   │   ◈ Server now ready on http://localhost:8888   │
   │                                                 │
   └─────────────────────────────────────────────────┘

posts を返すか確認

http://localhost:8888/.netlify/functions/posts

レスポンスが確認できたらOK
スクリーンショット 2022-05-09 19.22.53.png

次は実際にデータを post する処理をプロジェクトのルートディレクトリ(netlify/functions/post.ts)に作成する.

import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();

export async function handler(event) {
  const { title, content } = JSON.parse(event.body);
  try {
    await prisma.post.create({
      data: { title, content },
    });
    return {
      statusCode: 200,
      body: 'post created',
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify(error),
    };
  }
}

正常に起動するか確認する
VSCodeの拡張機能でThunder Clientという優れものがあるので、おすすめです.
https://www.thunderclient.com/

使い方もとてもシンプル
スクリーンショット 2022-05-09 19.34.41.png

ブラウザからのPOST機能実装

以下のコードをそのままsrc/app.tsxcopy & pasteしちゃってOK

src/app.tsx
import { useState, useEffect } from 'preact/hooks';

type Post = {
  id: number;
  title: string;
  content: string;
  createdAt: Date;
  updatedAt: Date;
};

export function App() {
  const [loadPosts, setLoadPost] = useState(true);
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    async function load() {
      if (!loadPosts) {
        return;
      }
      const allPosts = await fetch('/.netlify/functions/posts').then((res) =>
        res.json()
      );
      setPosts(allPosts);
      setLoadPost(false);
    }
    load();
  }, [loadPosts]);

  async function handleSubmit(event: any) {
    event.preventDefault();

    await fetch('/.netlify/functions/post', {
      method: 'POST',
      body: JSON.stringify({ title, content }),
    });
    setTitle('');
    setContent('');
    setLoadPost(true);
  }

  return (
    <>
      <h1>投稿画面</h1>
      <ul>
        {posts.map((post: Post) => (
          <li key={post.id}>
            <h3>{post.title}</h3>
            <p>Created {new Date(post.createdAt).toLocaleString()}</p>
            <p>Updated {new Date(post.updatedAt).toLocaleString()}</p>
          </li>
        ))}
      </ul>
      <h2>投稿しよう</h2>
      <form onSubmit={handleSubmit}>
        <label htmlFor='title'>Title</label>
        <input
          type='text'
          id='title'
          name='title'
          value={title}
          onChange={(e) => setTitle((e.target as HTMLInputElement).value)}
        />

        <label htmlFor='content'>content</label>
        <input
          type='content'
          id='content'
          name='content'
          value={content}
          onChange={(e) => setContent((e.target as HTMLInputElement).value)}
        />

        <button type='submit'>Save</button>
      </form>
    </>
  );
}

一応、cssも記述.

src/index.css
html,
body {
  font-family: 'Helvetica Neue', arial, sans-serif;
}
button,
label {
  display: block;
  margin-top: 1rem;
}

以下画面がブラウザ上で確認できるはずなので正常に「投稿→投稿されたPOSTが表示」されるか挙動チェック

スクリーンショット 2022-05-09 22.09.59.png

PlanetScaleのProduction環境DBの準備

PlanetScale のコンソール画面上からmainブランチを選択
スクリーンショット 2022-05-09 22.19.21.png

mainブランチをproduction用としてpromote
スクリーンショット 2022-05-09 22.22.56.png
スクリーンショット 2022-05-09 22.26.09.png
任意のブランチをmainブランチにdeployするために、deploy requestを上げる.(gitpull requestに近いイメージ)
ターミナルから以下コマンドを叩く

pscale deploy-request create データベース名 dev // devは任意のブランチ名

PlanetScaleのコンソール画面上にある、「Deploy requests」を選択すると、deploy requestが確認できる
スクリーンショット 2022-05-09 22.42.34.png
summaryタブから「Add changes to deploy queue」ボタンをクリック
スクリーンショット 2022-05-09 22.46.22.png

Netlifyへアプリケーションをデプロイ

丁寧にまとめられている、以下記事を参考にして下さい
https://qiita.com/suin/items/743fe6252ad8af425c5e

「Site settings」をクリックし、画面左に表示されている「Build & deploy」タブを選択
スクリーンショット 2022-05-09 22.58.33.png
スクリーンショット 2022-05-09 23.00.31.png
「Build settings」項目で以下のように設定し、下部の「save」ボタンをクリック
スクリーンショット 2022-05-09 23.02.12.png
PlanetScaleからDBへのURLを取得する
コンソール画面上の「overview」タブを選択し、画面右の「connect」ボタンをクリック
スクリーンショット 2022-05-09 23.05.58.png
「connect with」ドロップダウンメニューから「Prisma」を選択し、画面右のコピーアイコンをクリックしたら適当なメモ帳等にペーストしておく
スクリーンショット 2022-05-09 23.09.25.png

Netlifyへ戻り、「Site settings」をクリック、画面左に表示されている「Build & deploy」タブを選択して、以下スクショのように設定(valueには先ほどコピペした、DATABASE_URL情報のここから→mysql://~をペーストする)
スクリーンショット 2022-05-09 23.13.01.png

これで終了. もし正常にdeployされていない場合は、「Deploy」タブから「Trigger deploy」ボタンをクリックして再度、deployを行なって下さい。
スクリーンショット 2022-05-09 23.19.55.png

以下スクショ内のリンクをクリックすると、Netlify にデプロイされたページへ遷移することができます
スクリーンショット 2022-05-16 17.43.24.png

6
0
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
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?