3
2

More than 3 years have passed since last update.

[Nuxt + Firebase] 認証周りのアーキテクチャ設計

Last updated at Posted at 2020-04-17

NuxtとFirebaseで認証周りでセットで紹介されている記事がないなあと思ったので、Vueのアーキテクチャを応用してNuxt用に作ってみました。
基本的にアーキテクチャを作る目的なのでCSSは当てていません。

◆まずは爆速で動かしたい方はこちら

$ git clone https://github.com/dai-570415/nuxt-firebase-simple.git

Build Setup

# install dependencies
$ npm install

# serve with hot reload at localhost:3000
$ npm run dev

# build for production and launch server
$ npm run build
$ npm run start

# generate static project
$ npm run generate

Firebase data setting

plugins/firebase.js
//省略
    apiKey: "YourCode",
    authDomain: "YourCode",
    databaseURL: "YourCode",
    projectId: "YourCode",
    storageBucket: "YourCode",
    messagingSenderId: "YourCode",
    appId: "YourCode",
    measurementId: "YourCode"
//省略

※各自のFirebaseアプリの情報に差し替え

◆手を動かして実装したい方はこちら

Create Nuxt App

$ npx create-nuxt-app <project-name>

※いろいろ聞かれる思いますが、基本はNoneで今回はnpmにしています
Yarnを使いたい場合はそこでご指定ください。

Firebase管理画面から新規プロジェクト作成
各種設定
- firestore database
- アプリ APIキー等の取得に必要
- Authentication メール認証 有効

firebase イニシャライズ設定

npm install firebase --save

# インストールしてる人は飛ばしてOK
npm install -g firebase-tools

# Firebaseと連携しているGoogleアカウントでログイン
firebase login

firebase init

    ◯ Firestore: Deploy rules and create indexes for Firestore

    ❯ Use an existing project 

# 残りそのままEnter

コード側でFirebase設定

plugins/firebase.js
import firebase from 'firebase';

// YourCodeの部分に先ほどアプリで取得したキーを入れる
const firebaseConfig = {
    apiKey: "YourCode",
    authDomain: "YourCode",
    databaseURL: "YourCode",
    projectId: "YourCode",
    storageBucket: "YourCode",
    messagingSenderId: "YourCode",
    appId: "YourCode",
    measurementId: "YourCode"
};
// Initialize Firebase
if (!firebase.apps.length) {
    firebase.initializeApp(firebaseConfig);
}

export default firebase;
nuxt.config.js
// 省略
plugins: [
    '~/plugins/firebase',
],
// 省略

各種コンポーネント作成

AppNavigation.vueの実装

ここではSignin.vue、Signup.vueを入れたルーティングコンポーネントにしています。
【現状の使い方】
認証の必要のないpages/index.vueへの埋め込み用
現状1ファイルのみしか埋め込んでいないので直接埋め込んでもいいですが、
他に使いたくなったり、コンポーネントの中身を拡張のことを考えてコンポーネント化しています。

components/AppNavigation.vue
<template>
  <nav>
    <ul class="navigation">
      <li><nuxt-link to="/signup">Sign Up</nuxt-link></li>
      <li><nuxt-link to="/signin">Sign In</nuxt-link></li>
    </ul>
  </nav>
</template>

<style scoped>

</style>

default.vueの実装

こちらは共通のコンポーネントです。
基本はいじらないファイルです。

layouts/default.vue
<template>
  <div class="container">
    <header>
      <nuxt-link to="/">Nuxt.js & Firebase</nuxt-link>
    </header>
    <main>
      <nuxt />
    </main>
    <footer class="footer">
        ©︎2020 Nuxt
    </footer>
  </div>
</template>

<script>
  export default {

  }
</script>

<style>
  *,
  *:before,
  *:after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }
  html {
    font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI',
      Roboto, 'Helvetica Neue', Arial, sans-serif;
    font-size: 16px;
    word-spacing: 1px;
    -ms-text-size-adjust: 100%;
    -webkit-text-size-adjust: 100%;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
  }
  ul li {
    display: inline-block;
    list-style: none;
  }
</style>

各種pagesの実装

index.vue

Topページ 認証なし

pages/index.vue
<template>
  <div class="index">
    <h2>Index</h2>
    <AppNavigtion />
  </div>
</template>

<script>
  import AppNavigtion from '~/components/AppNavigation.vue';

  export default {
      name: 'Index',
      components: { AppNavigtion },
  }
</script>

<style scoped>
  ul li {
    display: inline-block;
  }
</style>

Signin.vue

サインイン画面 認証なし

pages/Signin.vue
<template>
  <div class="signin">
    <h2>Sign in</h2>
    <input type="text" placeholder="Username" v-model="username">
    <input type="password" placeholder="Password" v-model="password">
    <button @click="signIn">Signin</button>
    <p>
      You don't have an account? 
      <router-link to="/signup">create account now!!</router-link>
    </p>
  </div>
</template>

<script>
import firebase from 'firebase';

export default {
  name: 'Signin',
  data: function () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    signIn: function () {
      firebase.auth().signInWithEmailAndPassword(this.username, this.password).then(
        user => {
          alert('Success!');
          this.$router.push('/Hello');
        },
        err => {
          alert(err.message);
        }
      )
    }
  }
}
</script>

<style scoped>

</style>

Signup.vue

サインアップ画面 認証なし

pages/Signup.vue
<template>
  <div class="signup">
    <h2>Sign up</h2>
    <input type="text" placeholder="Username" v-model="username">
    <input type="password" placeholder="Password" v-model="password">
    <button @click="signUp">Register</button>
    <p>Do you have an account? 
    <router-link to="/signin">sign in now!!</router-link>
    </p>
  </div>
</template>

<script>
import firebase from 'firebase';

export default {
  name: 'Signup',
  data () {
    return {
      username: '',
      password: ''
    }
  },
  methods: {
    signUp: function () {
      firebase.auth().createUserWithEmailAndPassword(this.username, this.password)
        .then(user => {
          alert('Create account: ', user.email);
          this.$router.push('/Sighin');
        })
        .catch(error => {
          alert(error.message);
        })
    }
  }
}
</script>

<style scoped>

</style>

Hello.vue

サインイン後遷移する画面 認証あり

pages/Hello.vue
<template>
  <div class="hello">
    <h1>Hello {{ name }}!!</h1>
    <button @click="signOut">Sign out</button>
  </div>
</template>

<script>
import firebase from 'firebase';

export default {
  name: 'Hello',
  data () {
    return {
      name: firebase.auth().currentUser.email,
    }
  },
  methods: {
    signOut: function () {
      firebase.auth().signOut().then(() => {
        this.$router.push('/Signin');
      })
    }
  }
}
</script>

<style scoped>

</style>
3
2
1

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