FirebaseとNuxt.jsで、CRUDのベストプラクティスを作ってみる。(主にFirebaseまわりについて)

FirebaseとNuxt.jsで、CRUDのベストプラクティスを作ってみます。

プレビューはこちらから
■nuxt-basic-crud2
https://nuxt-basic-crud2.firebaseapp.com

作ったファイルは以下にアップしています。
■dog-ears/nuxt-basic-crud
https://github.com/dog-ears/nuxt-basic-crud

【環境】
・Windows10
・Visual Studio Code
・Node(Nodist)

ホスティングは、firebase hostingを使用する。
データベースは、Cloud Firestoreを使用する。

Nuxtは、サーバーサイドレンダリング(SSR)させる。
yarnは使わず、npmを使う。

(1)環境の準備

1) Visual Studio Codeをインストール

2) Nodeは、Nodistを使用。

■Nodist(公式)
https://github.com/nullivex/nodist/releases

2020年2月現在、Cloud FunctionsのNode.jsのバージョンは、10.15.3

■The Node.js 10 Runtime(英語)
https://cloud.google.com/functions/docs/concepts/nodejs-10-runtime?hl=en

nodistインストール後、下記実行

nodist + 10.15.3
nodist 10.15.3

nodeのバージョンは、10.15.3
npmのバージョンは、6.4.1
npxのバージョンは、10.2.0

(2)Firebase の準備およびhostingテストまで。

1) firebaseコンソールでやること

firebaseコンソールをブラウザで開く
https://console.firebase.google.com

googleアカウントでログインする。

プロジェクトの作成
googleアナリティクスは使用するとする。

Databaseを選択し、「データベースの作成」を選ぶ
「テストモードで開始」を選んで、「有効にする」を押す

Hostingを選択し、始めるを選ぶ。

2)Firebase CLIのインストールおよびデプロイまで

ローカルにプロジェクトフォルダを作成する。
以後、[project_folder]とする。

Visual Studio Codeで、プロジェクトフォルダを開きコンソールから、以下実行

CLIのインストール

npm install -g firebase-tools

ログインと初期化

firebase login
firebase init

? Are you ready to proceed?
→ Y

? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. (Press <space> to select)
→ Firestore、Functions、Hosting

? Select a default Firebase project for this directory:
→Use an existing project
→ 先ほど作ったプロジェクトを指定

— Firestore関連の質問 —

? What file should be used for Firestore Rules? (firestore.rules)
→ そのままenter

? What file should be used for Firestore indexes? (firestore.indexes.json)
→ そのままenter

— Functions関連の質問 —

? What language would you like to use to write Cloud Functions?
→ Javascript

? Do you want to use ESLint to catch probable bugs and enforce style? (y/N)
→ n

? Do you want to install dependencies with npm now?
→ Y

— Hosting関連の質問 —

? What do you want to use as your public directory? (public)
→ そのままenter

? Configure as a single-page app (rewrite all urls to /index.html)?
→ N

これで、Firebaseの初期化が完了しました。
ディレクトリ構成は以下のようになっているかと思います。

[プロジェクトディレクトリ]
┣functions
┃┣node_modelus
┃┣.gitignore
┃┣index.js
┃┣package-lock.json
┃┗package.json
┣public
┃┣404.html
┃┗index.html
┣.firebaserc
┣.gitignore
┣firebase.json
┣firestore.indexes.json
┗firestore.rules

firebase serve

で、ローカルサーバーが立ち上がり、
http://localhost:5001
で、functionsのページが、
http://localhost:5000
で、Welcome Firebase Hosting Setup Completeのページが開きます。

ctrl + cでいったんサーバーを終了。

firebase deploy

で、
https://[プロジェクト名].firebaseapp.com/
にページがアップされます。

(3)Functions の準備およびHostingからFunctionsを呼ぶまで。

1) Node10ランタイムの設定

(参考)SSR モードの Nuxt.js を Firebase に Deploy する Tutorial
https://qiita.com/okamuuu/items/c9f2989241af4a1bf588

node10ランタイムを使えるようにします。

/functions/package.json

"engines": {"node": "8"}
↓
"engines": {"node": "10"}
2) FunctionのhelloWorldテスト

/functions/index.js内に、helloWorldがコメントアウトされているので、
こちらを有効化します。
ついでに、function名をhelloWorldからnuxtServerに変えておきます。

/functions/index.js

// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send("Hello from Firebase!");
// });

exports.nuxtServer = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});

ローカルサーバーで確認してみる。

firebase serve --only functions:nuxtServer

http://localhost:5000/[プロジェクト名]/us-central1/nuxtServer

無事、Hello from Firebase!が表示されました。

3) HostingからFunctionsを呼び出す。

次に、hostingから、functionsを呼ぶようにします。

/firebase.json

"hosting": {
[中略]
  "rewrites": [
    {
      "source": "**/*.*",
      "destination": "/404.html"
    },
    {
      "source": "**",
      "function": "nuxtServer"
    }
  ]
}
}

※rewritesの上の行の]の後に、「,」を足すのを忘れずに。

拡張子付きのアドレスにアクセスした場合、ファイルがあれば表示。
なければ、notFoundページを表示するようにしました。
それ以外のアドレスは、すべてnuxtServerファンクションを呼ぶようにしてます。

ローカルテスト

firebase serve --only functions:nuxtServer,hosting

http://localhost:5000/hoge
などを開くと、helloWorldが実行されます。
※ただし、ルートに関しては、/public/index.htmlがあるため、そちらの表示が優先されます。

確認後、/publicフォルダの中にあるindex.htmlファイルは、不要なので、削除します。

(4)functions下にnuxtをインストールする

functions下にnuxtをcliでインストールしようと思います。
ただ、普通にfunctionsフォルダで、

npx create-nuxt-app

を実行すると、package.json等が上書きされてしまうので、
いったん下の階層(nuxt-src)にインストールします。

Visual Studio Codeのターミナルで、下記実行

cd functions
npx create-nuxt-app nuxt-src

? Project name
→ なんでもOK

? Project description
→ なんでもOK

? Author name
→ なんでもOK

? Choose a package manager
→ Npm

? Use a custom UI framework (Use arrow keys)
→ Buefy

? Use a custom server framework (Use arrow keys)
→ none

? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection)
→DotEnvのみ選択

? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
→ ESLint、Prettierを選択

? Use a custom test framework (Use arrow keys)
→ none

? Choose rendering mode (Use arrow keys)
→ Universal

? Choose development tools
→ jsconfig.json

インストール完了後、

cd ./nuxt-src
npm run dev

を実行すると、.nuxtフォルダが生成され、
ローカルサーバーが立ち上がり

http://localhost:3000/

で、テストページを確認できました。

ローカルサーバーは、ctrl+cでいったん停止しておきます。
/functions/nuxt-src/.nuxtフォルダもいったん削除。

次にnuxtのルートフォルダを一つ上のfunctionsに移動します。

functions/nuxt-src/package.jsonから
functions/package.jsonに、下記のように表記を移動します。

■scripts
→ そのまま全部追加。

startのみ、ダブるのでもともとあったfunctionsのstartは削除します。

"start": "npm run shell", // → こちらを削除
"start": "nuxt start",

ついでに、npm run serveとnpm run deployで、hostingもサーブ・デプロイするように変更しておきます。

"serve": "firebase serve --only functions",
"deploy": "firebase deploy --only functions",

"serve": "firebase serve --only functions,hosting",
"deploy": "firebase deploy --only functions,hosting",

■dependencies、devDependencies
→ まるごと移動でOK

移動が完了したら、
functions/nuxt-src/内の
・node_modules
・package.json
・package-lock.json
・.git ※あれば
は削除します。

nuxt-srcに残ったファイル(※フォルダはそのまま)を上の階層に移動
.editorconfig
.env
.eslintrc.js
.gitignore(※上書きでOK)
.prettierrc
jsconfig.json
nuxt.config.js
README.md

移動したnuxt.config.jsに、以下追加。

srcDir: 'nuxt-src'
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {}
},

build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {},
publicPath: '/assets/'
},

上記すべて終わったら、functionsフォルダで

npm install

を実行しておく。

npm run devすると、
WARN No .env file found in …
が出るので、.env関連を修正する。

nuxt用の.envモジュール「@nuxtjs/dotenv」
公式を見ると、
modulesではなく、buildModulesに入れろと書いてあったので、
buildModdulesに移動しつつ、オプションでパスの指定をします。

buildModules: [
....(中略)
// Doc: https://github.com/nuxt-community/dotenv-module
['@nuxtjs/dotenv', { path: __dirname }]
],

(5)ESlintがらみの設定変更

nuxtをインストールした時点で、
基本的なルールは設定されており、

npm run lint

で、lintチェックを実行できます。

実際に、lintチェックを実行したところ、
\functions\index.js
で、エラーが3つほど出ました。

修正をするにあたり、
まず、functions下に移動した.eslintrc.jsと.prettierrcを
VisualStudioCodeで使えるようにします。

※拡張機能のESLint、Prettierはインストールしておく。

■VisualStudioCodeでESLint拡張機能が動かない気がする時に確認したこと
https://note.kiriukun.com/entry/20190817-eslint-not-working-in-vscode

設定 – eslint.workingDirectories
をワークスペースで定義する。

settings.json
"eslint.workingDirectories": [
  "./functions"
]

これでfunctions/index.htmlを開くと、
エラー箇所に赤波線が表示されます。
赤波線にカーソルを合わせて、「クイックフィックス」→fix this pretier/pretier problem
で、自動的に修正されます。

次に、基本ルールですが、
初期設定でconsole.logが使用禁止のため、
このルールを修正します。

functions/.eslintrc.js

rules: {
'no-console': 'off',

上記のルールで、console出力があってもエラー表示をしなくなります。

(6)function「nuxtServer」で、nuxtをよびだしレンダリングする。

/functions/index.js
を、下記のように変更

https://github.com/dog-ears/nuxt-basic-crud/blob/master/functions/index.js

コンフィグ内、@nuxtjs/eslint-moduleは残していると、デプロイ後に
Error: could not handle the request
が、発生する。
(ログを見ると、FATAL Cannot find module '@nuxtjs/eslint-module’と表示される)
なので、コンフィグを読み込んだ後に、@nuxtjs/eslint-moduleを除外する。

また、index.jsでrequireを使ってnuxt.config.jsを読み込むため、
nuxt.config.jsを以下のように修正します。

export default {

module.exports = {

この時点で、npm run lint で、チェックすると、

1:1 error Unexpected module.exports, please use export default instead nuxt/no-cjs-in-config

が、出る。

CommonJSのrequireを使うなというエラー。
ルールから除外する。

/functions/.eslintrc.js
のrulesに、下記追加

'nuxt/no-cjs-in-config': 'off',

エラーが出なくなった。

nuxtをビルドする

npm run build

ローカルでfirebase サーバーを確認してみる

npm run serve

デプロイしてみる

npm run deploy

→見える(ただしエラーあり。)
/assetsにクライアントスクリプトを探しに行ってしまうので、
.nuxt/dist/clientの中身を/public/assetsにコピー。
これで、エラーが出なくなります。

npm buildしたときに自動的に.nuxt/dist/clientのなかみを
/public/assetsにコピーするようにする

npm install --save-dev cpx rimraf

下記ファイルを修正

/functions/package.json

"scripts": {
  "postbuild": "npm run remove-assets && npm run copy-assets",
  "remove-assets": "rimraf ../public/assets",
  "copy-assets": "cpx ./.nuxt/dist/client/** ../public/assets",

これで npm run buildを実行すると、
/public/assets
内が、自動的に更新される。

/public/assetsは、git対象外にするので、.gitignoreに
public/assets
を追加します。

(7)nuxtを修正する。

必要パッケージを入れる

npm install dayjs firebase htmlspecialchars vuexfire

.envの設定

デフォルトの設定では、サーバーサイドでしか読み取れない。
下記の対応をすることで、クライアントサイドでも読み取れるようになる。

/functions/nuxt.config.js
先頭に以下追加

require('dotenv').config()

Nuxtの修正内容は、以下のコミット履歴から確認できます。

https://github.com/dog-ears/nuxt-basic-crud/commit/819eb8fb5b179deab9abec82365374b9a9d94d4c

だいぶ投稿が長くなってしまったので、Nuxtの詳細については割愛します。

リポジトリをクローンして、.env.sampleから.envファイルを作って、
npm run devすれば、コンソールで処理の流れが終えるようにしているので、
見ていただければと思います。

nuxt

Posted by dog-ears