この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どうも、ベルリンオフィスの小西です。
ここ最近Next.jsを触っているのですが、外部DBからデータを引っ張ってくるために Airtable を利用するケースを紹介したいと思います。
Airtableとは
Excel/Googleスプレッドシートライクにデータベースを構築できるクラウドベースのアプリケーションです。
操作感はスプレッドシートに似ていて直感的でかつ、プライマリーフィールドの設定、各カラムへのデータ型の指定、デフォルト値のセットなど、RDBMS的な機能も利用できます。
APIでデータの操作もできるので、モックの簡易DBとしてサクッと使えるのも便利です。APIドキュメントも、最近よく見るタイプの、ログインしたら自分の情報がインサートされている形で素敵です。
Airtableの準備
※前段階としてAirtableに登録し、プロジェクトを作成します。
sample
というテーブルを作り、
- slug
- Title
- Description
というカラムを作成します。
ちなみに、レコード(一行)ごとのユニークIDと作成日はAirtable側で作成/保存されています(自分で作ってもいいけど)。
レコード取得APIの返り値は下記のようになります。 id
はAirtable側で振っているユニークIDです。
{
"id": "recbqWeotvpmDZC5P",
"fields": {
"Title": "テスト記事1 タイトル",
"Description": "テスト記事1 本文本文本文本文本文本文本文本文本文本文本文",
"slug": "test-post-1"
},
"createdTime": "2021-04-19T15:23:35.000Z"
}
ちなみにslugをプライマリーキーに設定してますが、Airtable側にユニークチェック機能はないので、レコードを登録する際はアプリ側もしくは運用側でユニークチェックが必要になるのでお気をつけください。
Next.jsの準備
まずさくっとNext.jsアプリを立ち上げます。
※Node.js の v10.13以降をダウンロードしておいてください。
npm init next-app sample-airtable
cd sample-airtable
npm run dev
これで http://localhost:3000/
にアクセスしてNext.jsのスタートページが立ち上がっていたらOK。いったんアプリを終了します。
パッケージのインストール
npm install airtable
環境変数ファイルの設置
.env.local
AIRTABLE_API_KEY=keyXXXXXXXX
AIRTABLE_BASE_ID=appXXXXXXXX
AIRTABLE_TABLE_NAME=sample
- APIキーは https://airtable.com/account から [Generate API Key] で生成できます。
- Base ID は各プロジェクトごとに発行されるので、 https://airtable.com/api からプロジェクトを選択し、次のページで [The ID of this base is appXXXXXXXX] という記載で確認できます。
Airtableクライアントを作成し、テーブルのデータを扱えるようにします。
pages/api/airtable.js
const Airtable = require('airtable');
const base = new Airtable({ apiKey: process.env.AIRTABLE_API_KEY }).base(
process.env.AIRTABLE_BASE_ID
);
const table = base(process.env.AIRTABLE_TABLE_NAME);
export { table };
次に、pagesディレクトリの配下に posts.js
を作成し、下記の記述をします。
src/pages/posts.js
import Head from 'next/head'
import styles from '../styles/Home.module.css'
import { table } from './api/airtable';
export default function Posts({ airtableRecords }) {
return (
<div className={styles.container}>
<Head>
<title>posts from Airtable</title>
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Posts
</h1>
<div>
{
airtableRecords.map((record) =>
<div style={{margin: 10, padding: 10, border: "solid 1px gray"}} key={record.id}>
<h2>{record.fields.Title}</h2>
<p>{record.fields.Description}</p>
</div>
)
}
</div>
</main>
</div>
)
}
export async function getStaticProps(context) {
let airtableRecords = await table
.select({
maxRecords: 10,
sort: [
{field: 'slug', direction: 'asc'},
{field: 'Title', direction: 'desc'},
],
})
.firstPage();
airtableRecords = airtableRecords.map((record) => {
return {
id: record.id,
fields: record.fields
}
});
return {
props: {
airtableRecords: airtableRecords,
},
};
}
ざっくり posts.js 内容の説明
静的ページとしてビルドするため getStaticProps
の中で処理をしています。
select
はレコードの諸々のデータが入ったオブジェクトを返すメソッドですが、中でオプションを指定できます。上記の例ではMAXのレコード数とソートを指定していますが、下記の例のようにフィールドの値で絞り込みなども行えます。
.select({
//slugがtest-post-3のレコードを除外する
filterByFormula: "NOT({slug} = 'test-post-3')"
})
また firstPage
メソッドは返り値のページ数の指定です。Airtableはデフォルトで最大100件までのレコードを1ページとして返すのですが、今回はそれ以下の数なので firstPage
を指定しています。100を超える場合は eachPage
メソッドを使いましょう。
詳しくは https://airtable.com/api に載っています。
データが取得できたかの確認
以上の準備を終えた上で、再度 npm run dev
をして http://localhost:3000/posts
にアクセスすると、下記のように記事が生成されているのが確認できると思います。
以上、非常に簡単に外部データをNext.js上で表示できました。
今回はビルド時にAirtableのデータを引っ張ってきてループで書き出す処理をしただけですが、Auth0と組み合わせて簡単なユーザーデータベースなども作成できます。
また今回は使っていないslugカラムをベースに記事詳細ページも生成したりできますね。
セットアップ不要でエンドポイントのある簡易データベースを使えるという意味でAirtableはこれから重宝しそうです。