LoginSignup
5
2

More than 3 years have passed since last update.

nuxt.js + GitHub Actions + Firebase hosting / functions でJAMstackを目指して

Posted at

最初からmicrocms / gatsby / netlifyつかっときゃ良かった

自白

2年前にnuxt.jsでお客様が記事書くWebサイトを構築しました。
そしてSSRで記事編集して公開できるようにしました。

それから1年半してJAMstack(SSG)に手を出したらSSRより圧倒的に早いじゃないですか。。。
作ってから時間がたって、スマホだと遅いサイトだなとつくづく実感しました。

PCだとまだましだけどスマホだと完全に遅い。
お客様にも悪いので既存のSSRからSSGに乗り換える提案をするために調査と実験を繰り返しました。

対象読者

・nuxt.js使っててSSGに移行したい人
・でもサイトの編集機能があるからDBの編集機能にも対応したい人
・firebase functions遅いかなって感じてる人

解説しないこと

・nuxt.jsで編集画面作る方法
・firebaseにデプロイする方法
・gitの使い方

本題

既存のfirebaseの設定にGitHubの設定を追加

firebase init hosting:github

色々聞かれるけどこの記事参考にこたえていけばOKだと思います。

firebase-hosting-merge.yml, firebase-hosting-pull-request.ymlが作成されるのでnodeのバージョンとnpmをyarnに変えました。
※本番に導入するならテストの設定もしましょう。(ここでは飛ばす)

firebase-hosting-merge.yml
# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools

name: Deploy to Firebase Hosting on merge
'on':
  push:
    branches:
      - main
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js 12 # nodeのバージョンを12にしてます
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - run: yarn install && yarn generate # npm → yarnに変えてます
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_PROJECT_X }}'
          channelId: live
          projectId: project-x
        env:
          FIREBASE_CLI_PREVIEWS: hostingchannels

このfirebase-hosting-pull-request.ymlをコピーしてfirebase-hosting-manual.ymlを作成します。
firebase-hosting-manual.ymlではworkflow_dispatchという機能でWeb API経由でデプロイできるようにします。

firebase-hosting-manual.yml
name: Manually triggered workflow
on:
  workflow_dispatch: # workflow_dispatchを設定(引数はいらない)
jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js 12
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - run: yarn install && yarn generate
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_PROJECT_X }}'
          channelId: live
          projectId: project-x
        env:
          FIREBASE_CLI_PREVIEWS: hostingchannels

GitHubのmainレポジトリにcommit/pushしてmergeによるfirebaseへのdeployが走ることを確認してください。
うまくいかない場合はfirebase.jsonを見直してください。
参考になるかもしれないので私のやつ置いておきます。

firebase.json
{
  "rulesFile": "database.rules.json",
  "functions": {
    "source": "functions",
    "predeploy": [
      "npm --prefix ./ run build",
      "rm -rf functions/nuxt",
      "cp -r .nuxt/ functions/nuxt/",
      "cp ./nuxt.config.js functions/"
    ]
  },
  "hosting": {
    "public": "dist",
    "rewrites": [
      {
        "source": "**/admin/**", # admin以下の部分は編集画面なのでSSGしない
        "function": "ssrapp"
      }
    ],
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}

ここまででCI/CDできましたがお客様がCRUD処理をしてもサイトが更新されなくなりました。

この記事参考にしてworkflow idを取得します。

curl \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/{github-user-name}/{repository-name}/actions/workflows

またこの記事参考にしてGithubのpersonal access tokenも準備してください。

で次のコマンドを実行するとgithubのワークフローが走りデプロイされることを確認してください。

curl  -XPOST -H "Authorization: token $YOUR_GITHUB_TOKEN" https://api.github.com/repos/{github-user-name}/{repository-name}/actions/workflows/{workflow-id}/dispatches -d '{"ref": "main"}}'

ここまでくればあと一息。
Firebase Functionsに記事作成で起動されるトリガー関数を登録するだけです。

以下の関数をfirebase functionsにデプロイしてください。

functions/index.js
const functions = require('firebase-functions')
const axios = require('axios').default

const GITHUB_TOKEN = functions.config().setting.github_token
const GITHUB_WORKFLOW_ID = functions.config().setting.workflow_id

exports.postGithubAction = functions.database.ref('articles/{articleId}')
  .onWrite(async (change, context) => {
  axios({
    url: `https://api.github.com/repos/${github-user-name}/${repository-name}/actions/workflows/${GITHUB_WORKFLOW_ID}/dispatches`,
    method: 'POST',
    data: {
      ref: 'main'
    },
    headers: {
      Authorization: `token ${GITHUB_TOKEN}`
    }
  })
})

// 以下SSRの関数が続く

記事を更新してGithub Actionが実行されれば成功です!

5
2
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
5
2