Vite + React + Cloudflare Pages + Contentful で アプリを立ち上げるまで
ベルリンオフィスの小西です。
Vite + React でアプリを立ち上げ、ヘッドレス CMS として Contentful を接続し、Cloudflare Pages にデプロイしてみました。
1. Contentful の準備
Contentful へのユーザー登録は終わっている前提で、簡単なコンテンツモデルを作成して記事を投稿してみます。
Contentful自体の説明や細かい説明方法は本記事では割愛しますので、気になる方はこちら↓をお読みください。
▼コンテンツモデルの作成
今回は samplePost
という ID でモデルを作成します。
▼入力フィールドの追加
- ID =
title
で [ショートテキスト]形式のフィールドを、 - ID =
thumbnail
で [Media] 形式のフィールドを
追加します。
上記で作成したモデルに対し、記事を公開します。
その後、Contentful のダッシュボードで [Settings] > [API keys] > [Add API key] から トークンを発行し、[Space ID] と [Content Delivery API - access token] をコピーしておきます。
2. ローカルで Vite + React の構築
2-1. Viteプロジェクトの立ち上げ
ガイドに沿ってアプリを立ち上げます。
% npm create vite@latest ✔ Project name: … my-first-vite-pjt ✔ Select a framework: › React ✔ Select a variant: › TypeScript Scaffolding project in /Users/ryokonishi/dev/vite/my-first-vite-pjt... Done. Now run: cd my-first-vite-pjt npm install npm run dev
爆速で素体ができあがりました。
2-2. コードの修正
試しにトップページに Contentful の記事データを表示してみます。
まずは環境変数を設定します。
.env ファイルをルートディレクトリに作成します。先ほど Contentful からコピーしたキーを入力してください。
VITE_CONTENTFUL_SPACE_ID=1234XXXXX VITE_CONTENTFUL_ACCESS_TOKEN=1234XXXXX
src/App.tsx を下記のコードに差し替えてください。
import { useState, useEffect } from 'react' import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import './App.css' type entryItem = { title: string thumbnail: { title: string url: string } } function App() { const [entry, setEntry] = useState() const contentfulEndpoint = `https://graphql.contentful.com/content/v1/spaces/${import.meta.env.VITE_CONTENTFUL_SPACE_ID}/` const query = ` { sampleModel(id:"7lbRXLuIUv8IhSl95oATgo"){ title thumbnail { title url } } } `; useEffect(() => { window .fetch(contentfulEndpoint, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${import.meta.env.VITE_CONTENTFUL_ACCESS_TOKEN}`, }, body: JSON.stringify({ query }), }) .then((response) => response.json()) .then(({ data, errors }) => { if (errors) { console.error(errors); } setEntry(data.sampleModel); }); }, []); return ( <div> <a href="https://vitejs.dev" target="_blank" rel="noopener"> <img src="{viteLogo}" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank" rel="noopener"> <img src="{reactLogo}" alt="React logo" /> </a> </div> <h1>Vite + React</h1> {entry ? <div> <h2>{entry.title}</h2> <img src="{entry.thumbnail.url}" alt="{entry.thumbnail.title}" width="400" /> </div> : 'Loading...' } <p> Click on the Vite and React logos to learn more </p> ) } export default App
2-3. (備考)コードに追加した箇所について
const query = ...
では 投げる GraphQL クエリを記述しています。今回は単一の記事を id
指定で取得しているため、ご自身の Contentful 記事の ID に差し替えてください。
画像などのアセット(下記例では thumbnail がそれにあたる)は、他に description
, size
, width
, height
なども取得できます。
const query = ` { sampleModel(id:"7lbRXLuIUv8IhSl95oATgo"){ title thumbnail { title url } } } `;
上記の例では ID を指定して単一記事を取得しましたが、記事の一覧を取得したい場合は Collection
オブジェクトを利用します。 items
の中には全記事のデータが配列として返ってきます。
const query = ` { sampleModelCollection { items { title thumbnail { title url } } } } `;
下記はGraphQL エンドポイントを介して Contentful へリクエストする箇所です。 Bearer
で先ほど生成したトークンをヘッダーにセットします。
useEffect(() => { window .fetch(contentfulEndpoint, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${import.meta.env.VITE_CONTENTFUL_ACCESS_TOKEN}`, }, body: JSON.stringify({ query }), }) .then((response) => response.json()) .then(({ data, errors }) => { if (errors) { console.error(errors); } setEntry(data.sampleModel); }); }, []);
なお、GraphQL の IDE である GraphiQL を使用して、Contentful のスキーマを探索できます。
GraphiQL サーバーは下記 URL をブラウザで開きます。
<code>https://graphql.contentful.com/content/v1/spaces/YOUR_CONTENTFUL_SPACE_ID/explore?access_token=YOUR_CONTENTFUL_ACCESS_TOKEN</code>
<img src="https://d1tlzifd8jdoy4.cloudfront.net/wp-content/uploads/2023/05/scr_2023-05-11_1522-960x546.png" alt="" width="960" height="546" class="alignnone size-large wp-image-1074292" />
GraphQL が少し過剰という方には、REST API エンドポイントも Contentful から用意されています。
<code>https://cdn.contentful.com</code>
2-4. アプリの確認
上記のコード変更を行った後に再度ローカルホストにアクセスすると、Contentful から設定した記事が確認できると思います。
<img src="https://d1tlzifd8jdoy4.cloudfront.net/wp-content/uploads/2023/05/Screenshot_2023-05-11_at_20.14.37-960x806.png" alt="" width="960" height="806" class="alignnone size-large wp-image-1074296" />
3. Cloudflare Pages へのデプロイ
Cloudflare Pagesは、Vite 3 のプロジェクトをネイティブにサポートしています。
Cloudflare Pages 自体の説明は省きます。詳細は↓
3-1. Wrangler CLI でデプロイする場合
まずビルド。
% npm run build > my-first-vite-pjt@0.0.0 build > tsc && vite build vite v4.3.5 building for production... ✓ 34 modules transformed. dist/index.html 0.46 kB │ gzip: 0.30 kB dist/assets/react-35ef61ed.svg 4.13 kB │ gzip: 2.14 kB dist/assets/index-d526a0c5.css 1.42 kB │ gzip: 0.74 kB dist/assets/index-f1047168.js 143.84 kB │ gzip: 46.39 kB ✓ built in 1.17s
でその後 wrangler でデプロイします。 dist
ディレクトリをアップロードしています。
% wrangler login % npx wrangler pages publish dist ✔ Enter the name of your new project: … konishi-vite-sample ✔ Enter the production branch name: … production ✨ Successfully created the 'konishi-vite-sample' project. ? Uploading... (5/5) ✨ Success! Uploaded 5 files (2.71 sec) ✨ Deployment complete! Take a peek over at https://xxxxxxxx.konishi-vite-sample.pages.dev
上記ですでに Pages プロジェクトが立ち上がっています。(上記の例だとビルドはローカルで行っているため、環境変数やビルドコマンドの設定も不要です)
発行された Pages URL にアクセスしてみます。
成功!
※ wrangler pages
コマンドは本記事執筆時点で beta のため、うまくいかない場合は次に書くコンソールからの操作で進めてください。
3-2. コンソールからデプロイする場合
Cloudflare のコンソール上でも Pages プロジェクトは作成できます。
Githubリポジトリを作成し、上記までのコードの変更を push します。
% git init % git add . % git commit -m "Initial commit" % gh repo create % git push
あとは Cloudflare コンソールから、
Pages > [Create a project] > [Connect to Git] で先ほど作成したリポジトリを選択し、
- [Build command] として
npm run build
と入力 - [Build output directory] として
dist
と入力 - [Environment variables (advanced)] > [Add variable] >
NODE_VERSION
として14.18
を選択
してデプロイするだけです。簡単!
さいごに
CMS とコードを行ったり来たりする開発でも、高速に変更が反映される Vite なら快適に進められます。一式の立ち上げに費用や複雑な設定も必要ないので、個人的な検証環境はこれで十分かなと思いました。