MENU

Googleスプレッドシート駆動のお知らせ機能だけを搭載したサイト開発

更新頻度が低い小規模なWebサイトにはWordPressだとオーバースペックに…また、クライアントによってはWordPress管理画面での操作がハードルになってしまう…なんてことがあったので、お知らせ機能など軽い更新作業だけを使い慣れたGoolgeスプレッドシートで完結させる構成を試してみました。

目次

プロジェクト構成

  • バックエンド:Google Apps Script (GAS) をWeb App化し、スプレッドシートの内容をJSONで返すAPIにする
  • フロントエンド:Next.js(App Router)
  • 本番環境:Node.jsが動かない共有サーバーを想定

上記のような共有サーバーだと想定し、Next.jsは静的エクスポート一択。

ディレクトリ構成

gsheets-nextjs-site/
├── clasp/    # GASプロジェクト
│   └── src/
└── nextjs/   # フロントエンド

GAS側:スプレッドシートをJSON APIにする

以下のようなスプレッドシートを準備しておきます。

date | title | body

ヘッダー行(1行目)の値をそのままJSONのキーとしたいので、ヘッダーは英語表記で統一。

実際の運用を考えると、公開ステータス(pulished)などあった方が良いと思いますが、今回はひとまずの表示を目指します。

claspのセットアップ

claspはCommand Line Apps Script Projectsの略で、Googleが公式で提供しているCLIツールです。GASプロジェクトをローカルで作成、編集、デプロイを行うことができます。PCに1回インストールすればよいグローバルツールです。

# claspが初めての環境で1回インストールします
npm install -g @google/clasp
clasp login

# 以下でバージョンが表示されればインストール済みです
clasp -v

プロジェクトを新規作成します

cd clasp
clasp create --type webapp --title my-gsheets-api --rootDir ./src

スプレッドシートをJSONで返す

clasp/src/main.js(これがAPI本体です)

function doGet(e) {
  const sheet = SpreadsheetApp.openById('シートID').getSheetByName('news');
  const values = sheet.getDataRange().getValues();
  const [header, ...rows] = values;

  const data = rows.map((row) =>
    Object.fromEntries(header.map((key, i) => [key, row[i]]))
  );

  return ContentService
    .createTextOutput(JSON.stringify(data))
    .setMimeType(ContentService.MimeType.JSON);
}

シートIDはGoogleスプレッドシートのURLから取得できます。ここではシート名を「news」にしています。

以下でGoogle側に反映

clasp push

デプロイと権限承認

clasp deploy --description "v1"
clasp deployments

インデックス「v1」でデプロイできました。

発行されたWeb AppのURLに初めてアクセスすると、「このアプリがあなたのデータへのアクセス許可を求めています」と表示されるので、許可します。以降はJSONが返るようになります。

フロントエンド側:Next.js

npx create-next-app@latest nextjs --typescript --app --eslint

next.config.tsで静的エクスポートを有効にしておきます。

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  output: 'export',
  images: {
    unoptimized: true,
  },
  trailingSlash: true,
};

export default nextConfig;

GASのURLを.env.localに。Apps Scriptの[デプロイを管理]から取得できます。

GAS_API_URL=https://script.google.com/macros/s/xxxxx/exec

お知らせ一覧ページを作成します。app/news/page.tsx を用意。

type NewsItem = {
  title: string;
  date: string;
  body: string;
};

async function getNews(): Promise<NewsItem[]> {
  const res = await fetch(process.env.GAS_API_URL!);
  return res.json();
}

export default async function NewsPage() {
  const news = await getNews();

  return (
    <ul>
      {news.map((item, i) => (
        <li key={i}>{item.date} {item.title}</li>
      ))}
    </ul>
  );
}

ローカルで確認してみます。

cd nextjs
npm run dev

http://localhost:3000/news にアクセスして、スプレッドシートのお知らせが表示されれば成功です。

おまけ

小規模なWebサイトの場合、Node.jsが動かない共有サーバーを利用することが想定されます。

なので、Next.jsは静的エクスポートをデプロイする必要があり、output: ‘export’を有効にしましたが、スプレッドシートを更新しただけではサイトの表示は変わらず、再ビルド・再デプロイが必要です。

つまり、このままだと、スプレッドシートを更新するたびに手動で npm run build をしてアップロードする必要があり、非現実的です。

そこで、スプレッドシートに更新を反映するトリガーを用意してはどうかと考えてみました。

スプレッドシートからトリガーを送り、ビルド・デプロイを自動化する

以下のようなイメージです。

スプレッドシートの「反映する」メニュー
↓
GASがGitHub Actionsに「実行して」とAPI経由で通知(repository_dispatch)
↓
GitHub Actions上でNext.jsをビルド
↓
サーバーへSSH経由(rsync)でアップロード

GASに「反映する」メニューを追加し、それがトリガーとなり、GitHub Actionsがビルドとデプロイを担います。

こうすれば、クライアントはスプレッドシートを編集して、メニューから反映するを押すだけでお知らせを公開できるようになります。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次