LoginSignup
16
10

More than 1 year has passed since last update.

Nuxt +Firebase のメモ

Last updated at Posted at 2021-10-19

内容

Nuxt + firebase で web アプリを作る方法についての内部向けメモです。基本、下記あたりの記事を見てそのままやっただけです。

nuxt2 + firebase v8 です。nuxt3 + firebase9 は下記に書いてます

手順

準備

Ubuntu 20.04LTS でやります。

$ npm -v
6.14.15
$ node -v
v14.18.1
$ yarn -v
1.22.11
$ firebase --version
9.20.0

インストールの手順は下記を参照のこと。

Nuxt

Javascript, Vuetify, ESLint を選択してます。

$ yarn create nuxt-app first
...
✨  Generating Nuxt.js project in first
? Project name: first
? Programming language: JavaScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: ESLint
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/Jamstack hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Continuous integration: None
? Version control system: Git
...

firebase の hosting を使う場合、Deployment target は Static/Jamstack hosting にする必要がある。

作成できたらテスト。

$ cd first
$ yarn dev

http://localhost:3000 にブラウザでアクセスして、下記のようになればOK。vuetify を入れてるので、ない場合とは少し表示が違う(多分)。

image.png

問題なく動いたら、build と start してみる。

$ yarn build
$ yarn start

firebase の設定

基本はNuxt Firebase:Getting Startの通り。

$ yarn add firebase@8.10.0
$ yarn add @nuxtjs/firebase@7.6.1

firebase のモジュールはバージョンを指定しないと 9.0.0 が入る。9.0.0 系は 8.0.0 系と使い方が微妙に違っていて、ネットに転がってる記事がそのまま通用しないことがある。

v9 でも compat を使えば v8 のように使えるけど、それなら普通に v8 を使うでいいような気もするんですが、どうなんでしょうね?

とりぜず、以下では firebase v8 でやってます。

@nuxtjs/firebase は 8.0.0 以上だと firebase v9 対応になってしまい、firebase v8 以下との併用ができないぽい。firebase v8 を使う場合は @nuxjs/firebase もバージョンを指定する必要あり。

初期化

$ yarn generate
$ firebase init hosting
? Please select an option: Use an existing project
? Select a default Firebase project for this directory: myproject (myproject)
? What do you want to use as your public directory? dist
? Configure as a single-page app (rewrite all urls to /index.html)? No
? Set up automatic builds and deploys with GitHub? No
✔  Wrote dist/404.html
? File dist/index.html already exists. Overwrite? No

public directory に dist を指定する。あらかじめ yarn buildyarn generate してないと生成されていないので、先にしておく。

テスト

$ yarn generate
$ firebase serve --only hosting

firebase コマンドでテストやデプロイする場合は、yarn build ではなくて yarn generate する必要がある。これ重要。

これで http://localhost:5000 にアクセスして yarn dev のときと同じ結果になっていればOK。

デプロイ

$ firebase deploy --only hosting

これで https://myproject.web.app にアクセスして、ローカルのときと同じ表示になっていればOK。

apiKey とかの設定

Nuxt Firebase:Getting Start にあるように、nuxt.config.js に apiKey などを設定する。

nuxt.config.js
    modules: ['@nuxtjs/firebase'],
    firebase: 
      {
        config: {
          apiKey: '<apiKey>',
          authDomain: '<authDomain>',
          projectId: '<projectId>',
          storageBucket: '<storageBucket>',
          messagingSenderId: '<messagingSenderId>',
          appId: '<appId>',
          measurementId: '<measurementId>'
        },
        services: {
          auth: true // Just as example. Can be any other service.
        }
      },

使いたいサービスにあわせて Nuxt Firebase:Options を見て true を設定する。ローカルエミュレータを使う場合はもう少し設定が必要。上の麗では auth だけ有効になっている。

Nuxt のファイル構造の基本的な理解

とりあえず、機能を試すのに必要なファイル以外を削除したのが下記の構成。これで、ルートのページには index.vue の中身が表示され、inspire ボタンを押すと inspire.vue の中身が表示される。

assets
└── variables.scss
layouts
├── default.vue
└── error.vue
static
└── favicon.ico
pages
├── index.vue
└── inspire.vue
components
nuxt.config.js
package.json

index.vue の中身は / を指定したときに表示される。

pages/index.vue
<template>
  <v-container>
    Hello World
    <v-btn to="/inspire">
      inspire
    </v-btn>
  </v-container>
</template>

pages/ 以下の index.vue 以外のファイルは、pages/xxxx.vue というファイル名にすることで /xxxx というパスでアクセスできるようになる。vue-router に相当するものは、build したときに .nuxt/router.js に自動的に生成される。

pages/inspire.vue
<template>
  <v-container>
    inspire
    <v-btn to="/">
      Home
    </v-btn>
  </v-container>
</template>

layouts/default.vue には全ページに共通するヘッダやフッダのような、ページの外枠になるUIを書いておく。ファイル中に <Nuxt /> タグを書くと、そこにパスと一致する pages/xxxx.vue の中身を配置してくれる。

layouts/default.vue
<template>
  <v-app dark>
    <v-main>
      <v-container>
        <Nuxt />
      </v-container>
    </v-main>
  </v-app>
</template>

<script>
export default {
  data () {
    return {}
  }
}
</script>

ページによって外観を変えたい場合は、下記のように layout: 'hogex' とかしておいて、

layouts/hoge.vue
<script>
export default {
  layout: 'hogex',
  ...
}
</script>

pages のほうのファイルで、たとえば、

pages/hoge.vue
<template>
  <v-container>
    Hogex
  </v-container>
</template>
<script>
<script>
export default {
  name: 'hoge',
  layout: 'hogex'
}
</script>

みたいなかんじで layout を指定すると、hogex という layout を持つ vue ファイルが外観として使用される。ぽい。

エラーページを出すには layouts/error.vue というファイルを作る。layout に empty が指定されているけど、empty という特別なレイアウトの名前があるわけではないらしい。あと、layouts/ 以下にあるけど、error.vue 自体はページ扱いされる(らしい)。

layouts/error.vue
<template>
  <v-app dark>
    <h1 v-if="error.statusCode === 404">
      {{ pageNotFound }}
    </h1>
    <h1 v-else>
      {{ otherError }}
    </h1>
    <NuxtLink to="/">
      Home page
    </NuxtLink>
  </v-app>
</template>

<script>
export default {
  layout: 'empty',
  props: {
    error: {
      type: Object,
      default: null
    }
  },
  data () {
    return {
      pageNotFound: '404 Not Found',
      otherError: 'An error occurred'
    }
  },
  head () {
    const title =
      this.error.statusCode === 404 ? this.pageNotFound : this.otherError
    return {
      title
    }
  }
}
</script>

<style scoped>
h1 {
  font-size: 20px;
}
</style>

assets ディレクトリ

assets/variables.scss は Vuetify のカスタマイズ用のグローバル設定を書くところ。空でもいいけど、存在しないとエラーになる。nuxt.config.js の下記の設定を消すと、エラーにならなくなる。

nuxt.config.js
 vuetify: {
    customVariables: ['~/assets/variables.scss'],
    ...
 }

Vuetify 用の設定なので、Nuxt には直接関係はない(はず)。

static ディレクトリ

static/favicon.ico は、置いておかないとブラウザが勝手に探しに行って 404 エラーが発生しまくるので、それの回避のためだけに置いてあるだけ。

static 以下にファイルを置くと、直接そのファイルを参照できる。たとえば static/hoge.png みたいなファイルがあるとき、<template> タグの中で、下記のような感じで参照できる。

sample.vue
<template>
   <img src="/hoge.png"/>
</template>

このとき、パスに static は含めない。

ローカルの javascript も static に置ける(asset に置くこともできる)。たとえば static/local.js を参照したい場合は、nuxt.config.js の中に、次のような記述を書くことで読み込める。

nuxt.config.js
  head: {
    script: [
      {
        src: "/local.js",
      }
    ],
  }

画像などの固定リソースは、assets 以下に置く方法もある。

layouts の適用ルール

上記によれば、layout の適用はこのようになるらしい。

  • すべてのページはレイアウトdefault.vueでロードされます
  • ページのレイアウトを指定した場合は、指定したレイアウトで読み込まれます。
  • 指定されたレイアウトが利用できない場合、ページはdefault.vueでロードされます
  • nuxtがlayoutsフォルダーにdefault.vueという名前のファイルを表示しない場合、ページは空のレイアウトで読み込まれます

empty を指定したからといって、レイアウトがなしになるわけではなくて、layout: 'empty' と書かれている layouts/ 以下のファイルを探しに行くだけだそうな。

参考:

テスト再び

ここまでの状態で yarn dev すると、下記のような画面になるはず。

image.png

inspire を押すとこうなる。

image.png

存在しないパスを指定するとこうなる。

image.png

URL を直接指定して http://localhost:3000/inspire にアクセスしてもエラーになる。

image.png

あくまで、home から遷移してしか inspire には行けない。このあたりは vue-router のときと同じ。

firebaseui + firebase authentication でログインする

準備

バージョンを指定して firebaseui モジュールをインストールしておく。バージョンを指定しないと 9.0.0 対応のモジュールが入ってしまって、うまく動かないことがある。(2021/10現在)

$ yarn add firebaseui@5.0.0

apiKey を取得しておく。上のほうで nuxt.config.js に指定済なら問題なし。

ログインページの作成

pages/login.vue
<template>
  <v-container>
    <div>
        <div id="firebaseui-auth-container"></div>
    </div>
    <v-btn to="/">
        home
    </v-btn>     
  </v-container>   
</template>
<script>
export default {
  mounted() {        

    const firebaseui = require('firebaseui');
    require("firebaseui/dist/firebaseui.css");
    const ui = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(this.$fire.auth);
    const tmp = this;

    const config = {
      signInOptions: [
        //firebase.auth.EmailAuthProvider.PROVIDER_ID,
        this.$fireModule.auth.EmailAuthProvider.PROVIDER_ID,
        // firebase.auth.GoogleAuthProvider.PROVIDER_ID
        //this.$fireModule.auth.GoogleAuthProvider.PROVIDER_ID
      ],
      signInSuccessUrl: '/',
      callbacks: {
        signInSuccessWithAuthResult() {
          console.log('ok');
          tmp.$router.push('/');
        },
        uiShown: function () {
          console.log('ui');
        }
      }
    };

    ui.start('#firebaseui-auth-container', config);
  }
};
</script>

$fireModule をつかうのがみそ。signInSuccessUrl が機能してないかんじがするので、直接とばしている。要調査。

オプションとか細かいところは、下記と同じ。

SSR に対応してないプラグインを使うときの注意

Vue とか Vuetify 用で、SSR に対応していないモジュールを使うときは、<client-only> タグを使う

vuetify-markdown-editor を使おうとしたら、document is not found というエラーが出たので、原因を調べたらこれだった。 <no-ssr> タグを使うように書かれている記事が見つかるけど、このタグは nuxt3 で削除されるので、今後は <client-only> を使いなさいということらしい。

editor.vue
<template>
  <v-app>
    <v-main>
      <client-only>
        <Editor
            mode="preview"
            ref="editor"
            hint="Hint"
            :outline="false"
            :render-config="renderConfig"
            v-model="text"
        />
      </client-only>
    </v-main>
  </v-app>
</template>
<script>
import { Editor } from "vuetify-markdown-editor";
export default {
    name: "App",
    components: {
        Editor,
    },
    data: () =>({
      renderConfig: {
        mermaid: {
            
        }
      }
    }),
    mounted: function(){
        this.$vuetify.theme.dark = false;
        console.log("editor module");
    },
    methods: {
    }
}
</script>

こんな感じ。もちろん使うには下記が必要。

$ yarn add vuetify-markdown-editor
16
10
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
16
10