Vue.jsでマテリアルデザイン風なサイトが手軽に構築できるQuasar FrameworkとFirebaseで、ログイン機能を実装してみました。
Quasar Frameworkとは?
レスポンシブ対応で、マテリアルデザイン風のサイトが手軽に構築できるVue.js搭載のデザインフレームワークです。中身はVue.jsですので、Vue.jsが使える方は抵抗なく使えると思います。
Firebaseとは?
googleが提供するMBaasです。主にモバイル用途のようなのですが、普通に小さなウェブアプリとかなら使えるぽいです。
参考
http://quasar-framework.org/
https://medium.com/@anas.mammeri/vue-2-firebase-how-to-build-a-vue-app-with-firebase-authentication-system-in-15-minutes-fdce6f289c3c
https://qiita.com/sin_tanaka/items/ea149a33bd9e4b388241
環境
- macOS High Sierra 10.13.2
- npmがinstallされている
Quasar Framework をインストール・準備する
インストールして、開発サーバを起動させて動作を確認します。
# quasar-cliをinstall
$ npm install -g quasar-cli
# quasar init <スターターキット名> <プロジェクト名>
$ quasar init default quasar-firebase
# プロジェクトフォルダに移動する。
$ cd quasar-firebase
# npmのpackageをinstallする。
$ npm install
# 開発サーバーでの起動
$ quasar dev
http://localhost:8080/
にアクセスして、デモ画面が表示されていれば成功!
Signup.vue, Login.vueを作成する
<template lang="html">
<div>
<div class="layout-padding row justify-center background-whitesmoke items-center">
<div class="col-xs-12 col-sm-7 col-lg-5">
<q-card class="q-card-background-white">
<q-card-main>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-center">
<img src="~assets/quasar-logo-full.svg" class="logo-sized">
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-left">
<h5>新規登録</h5>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-left">
<p style="font-size: 12px;">新規アカウントの登録をお願いします。</p>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1">
<q-field>
<q-input v-model="email" float-label="メールアドレス" color="primary" type="email"/>
</q-field>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1">
<q-field>
<q-input v-model="password" float-label="パスワード" color="primary" type="password"/>
</q-field>
</div>
</div>
<div class="row" style="padding-top: 20px;">
<div class="col-sm-10 offset-sm-1 text-right">
<q-btn color="primary" style="font-weight: bold;" @click="signUp">新規登録</q-btn>
</div>
</div>
<br>
<div class="row">
<p style="color:#027be3;font-size:12px;"><router-link to="/login">すでに登録済みの方はサインインしてください</router-link></p>
</div>
</q-card-main>
</q-card>
</div>
</div>
</div>
</template>
<script>
import {
QBtn,
QCard,
QCardMain,
QField,
QInput
} from 'quasar'
export default {
name: 'Signup',
components: {
QBtn,
QCard,
QCardMain,
QField,
QInput
},
data () {
return {
password: '',
email: ''
}
}
}
</script>
<style lang="stylus">
.q-card-background-white
background white
.background-whitesmoke
background whitesmoke
height 100vh
.logo-sized
width 150px
margin 20px
</style>
<template lang="html">
<div>
<div class="layout-padding row justify-center background-whitesmoke items-center">
<div class="col-xs-12 col-sm-7 col-lg-5">
<q-card class="q-card-background-white">
<q-card-main>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-center">
<img src="~assets/quasar-logo-full.svg" class="logo-sized">
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-left">
<h5>ログイン</h5>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1 text-left">
<p style="font-size: 12px;">メールアドレスとパスワードを入力してください。</p>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1">
<q-field>
<q-input v-model="email" float-label="メールアドレス" color="primary" type="email"/>
</q-field>
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-1">
<q-field>
<q-input v-model="password" float-label="パスワード" color="primary" type="password"/>
</q-field>
</div>
</div>
<div class="row" style="padding-top: 20px;">
<div class="col-sm-10 offset-sm-1 text-right">
<q-btn color="primary" style="font-weight: bold;" @click="signIn">ログイン</q-btn>
</div>
</div>
<br>
<div class="row">
<p style="color:#027be3;font-size:12px;"><router-link to="/signup">新規アカウント作成</router-link></p>
</div>
</q-card-main>
</q-card>
</div>
</div>
</div>
</template>
<script>
import {
QBtn,
QCard,
QCardMain,
QField,
QInput
} from 'quasar'
export default {
name: 'Login',
components: {
QBtn,
QCard,
QCardMain,
QField,
QInput
},
data () {
return {
email: '',
password: ''
}
}
}
</script>
<style lang="stylus">
.q-card-background-white
background white
.background-whitesmoke
background whitesmoke
height 100vh
.logo-sized
width 150px
margin 20px
</style>
vue-routerの設定
quasar init
で作成されたプロジェクトにはvue-routerも自動でインストールされていると思います。src/router.jsに設定します。
- mode: 'history' に変更します。
- routesに、login, singupのrouteを追記します。
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
function load (component) {
// '@' is aliased to src/components
return () => import(`@/${component}.vue`)
}
export default new VueRouter({
mode: 'history',
scrollBehavior: () => ({ y: 0 }),
routes: [
{ path: '/', component: load('Hello') },
{ path: '/login', name: 'login', component: load('Login') },
{ path: '/signup', name: 'singup', component: load('Signup') },
// Always leave this last one
{ path: '*', component: load('Error404') } // Not found
]
})
確認
ターミナルで、$ quasar dev
を実行している状態で、
http://localhost:8080/signup
http://localhost:8080/login
にそれぞれ、以下のように表示されれば成功です!
Firebaseのインストール・設定
npmで、firebaseをインストールする
$ npm install --save firebase
Firebaseのプロジェクトの作成・設定
-
次に、Firebaseのコンソール画面にログインします。(https://console.firebase.google.com/)
-
Firebaseのコンソール画面で、「プロジェクトを追加」から、プロジェクト名と、国/地域 を選択して、プロジェクトを作成します。
※コンソールへのログインは、googleアカウントが必要です。 -
「ウェブアプリにFirebaseを追加する」をクリックします。
- 以下のようなコードが表記されると思います。
<script src="https://www.gstatic.com/firebasejs/4.8.1/firebase.js"></script>
<script>
var config = {
apiKey: "YOUR_KEY",
authDomain: "quasar-YOUR_DOMAIN.firebaseapp.com",
databaseURL: "https://YOUR_DOMAIN.firebaseio.com",
projectId: "YOUR_ID",
storageBucket: "YOUR_BUCKET_ID.appspot.com",
messagingSenderId: "YOUR_SENDER_ID"
};
firebase.initializeApp(config);
</script>
- src/main.jsに以下の3点を追記します。
- config部分をコピペする
- firebaseをimportする
- firebaseのinitializeAppを実行する
require(`quasar/dist/quasar.${__THEME}.css`)
import Vue from 'vue'
import Quasar from 'quasar'
import router from './router'
// firebaseをimportします
import firebase from 'firebase'
Vue.config.productionTip = false
Vue.use(Quasar) // Install Quasar Framework
if (__THEME === 'mat') {
require('quasar-extras/roboto-font')
}
import 'quasar-extras/material-icons'
// config部分をコピペします
var config = {
apiKey: 'YOUR_KEY',
authDomain: 'quasar-firebase.firebaseapp.com',
databaseURL: 'https://YOUR_DOMAIN.firebaseio.com',
projectId: 'YOUR_ID',
storageBucket: 'YOUR_BUCKET_ID.appspot.com',
messagingSenderId: 'YOUR_SENDER_ID'
}
// firebaseの初期化設定します
firebase.initializeApp(config)
Quasar.start(() => {
/* eslint-disable no-new */
new Vue({
el: '#q-app',
router,
render: h => h(require('./App').default)
})
})
Firebaseの認証の設定
Firebaseのコンソール画面から、プロジェクト画面を開いて、「Authentication」にメール/パスワードの認証を有効にします。
新規ユーザーの登録メソッドを追記
-
firebase.auth().createUserWithEmailAndPassword()
を使います。
import firebase from 'firebase'
...
<script>
...
methods: {
signUp: function () {
firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
.then(user => {
alert('アカウントの新規作成が完了しました!', user.email)
})
.catch(error => {
var errorCode = error.code
var errorMessage = error.message
alert(errorCode, errorMessage)
})
}
}
...
</script>
...
ユーザー認証のメソッドを追記する。
-
firebase.auth().signInWithEmailAndPassword
を利用して
...
<script>
...
import firebase from 'firebase'
...
methods: {
signIn: function () {
firebase.auth().signInWithEmailAndPassword(this.email, this.password)
.then(user => {
alert('無事ログインしました!')
})
.catch(err => {
alert(err)
})
}
...
</script>
...
vue-routerでリダイレクトの設定をする
- src/routes.js に次のように設定します。
...
routes: [
{ path: '/', component: load('Hello'), meta: { requiresAuth: true } },
{ path: '/login', name: 'login', component: load('Login') },
{ path: '/signup', name: 'singup', component: load('Signup') },
// Always leave this last one
{ path: '*', component: load('Error404') } // Not found
]
...
- さらに、src/main.jsに、ログインしていない状態でホーム画面にアクセスすると、login画面にリダイレクトするように設定します。
...
firebase.initializeApp(config)
// ここを追加
router.beforeEach((to, from, next) => {
let currentUser = firebase.auth().currentUser
let requiresAuth = to.matched.some(record => record.meta.requiresAuth)
if (requiresAuth && !currentUser) {
next('login')
}
else if (!requiresAuth && currentUser) {
next('hello')
}
else {
next()
}
})
Quasar.start(() => {
/* eslint-disable no-new */
new Vue({
el: '#q-app',
router,
render: h => h(require('./App').default)
})
})
-
http://localhost:8080/
にアクセス→http://localhost:8080/login
にリダイレクト→ログイン実行→ログイン成功のalertが表示されて、http://localhost:8080/
にアクセスされていれば成功です!ただ、リロードすると、またもやログイン画面に戻ってしまいます。。。これを解決するには以下の手順が必要です。
routerの再設定
さきほどセットしたbeforeEachは、firebaseの初期化の前に呼び出されているので、初期化が完了したときには、firebase.auth().currentUserがnullを返してしまい、それが原因で、ログイン画面にリダイレクトされているようです。
Firebaseでは、AuthオブジェクトにObserverを設定することができます。onAuthStateChanged を利用して、Firebaseが初期化されたことが確認された場合にのみ、Vueアプリケーションを初期化するようにします。(Authの状態が中途半端な状態にならないということかな。)
main.jsに、コードを追記します。
let app
firebase.auth().onAuthStateChanged(function (user) {
Quasar.start(() => {
if (!app) {
/* eslint-disable no-new */
app = new Vue({
el: '#q-app',
router,
render: h => h(require('./App').default)
})
}
})
})
ログアウト機能をHello.vueに追記する。
Hello.vueにログアウト機能を実装します。今回はq-toolbarの右端にログアウトボタンをつけてみました。
...
<q-toolbar slot="header" class="glossy">
<q-btn
flat
@click="$refs.layout.toggleLeft()"
>
<q-icon name="menu" />
</q-btn>
<q-toolbar-title>
Quasar App
<div slot="subtitle">Running on Quasar v{{$q.version}}</div>
</q-toolbar-title>
<q-btn outline @click="logout">ログアウト</q-btn>
</q-toolbar>
...
import firebase from 'firebase'
...
logout () {
firebase.auth().signOut()
.then(() => {
alert('ログアウトしました!')
this.$router.replace('login')
})
}
...
これでサインアップ、ログイン、ログアウトまで、ひとまず完成です!
まとめ
サインアップ、ログイン、ログアウトまで大体15分くらいで、できてしまうので、firebaseかなり便利そうだな〜という印象です。
Quasar Frameworkも、ほとんどvue.jsの知識でサクッといい感じのデザインのページが作れてしまうので、マテリアルデザインに抵抗が無い人はおすすめです!