1.概要
フロントエンドは【vue.js】、バックエンドは【Node.js】を使い
簡単なBasic認証を使ったSPAを開発します。
2.完成予定
下図のようなログイン画面を作成し、
Basic認証がOKであれば、下図のような適当なページを表示するといったものになります。
3.開発準備
まずは開発に必要な環境を構築します。
私の開発用PCはWindows10になります。
①Node.js
Node.jsについては【nodist】を使った管理をしています。
詳しくは下記の記事を参照して下さい。
今回使ったバージョンは【12.13.0】です。
②npm
npmとはNode Package Manageの略です。
これはNode.jsをインストールすると一緒にインストールされます。
今回使ったバージョンは【6.9.0】です。
③@vue/cli
vue.jsの開発ツール@vue/cliのインストールを行います。
【-g】とすることでグローバルインストールになります。
>npm install -g @vue/cli
今回使ったバージョンは【4.4.6】です。
4.プロジェクトの作成
今回は【basicsample】というフォルダの下に
【frontend】
【backend】
という名前の2つのプロジェクトを作成していきます。
フロントエンド
まずはプロジェクトを作成します。
プロジェクト名は半角英数字と小文字のみで指定します。
>cd basicsample >vue create frontend ? Please pick a preset: (Use arrow keys) > default (babel, eslint) Manually select features
default (babel, eslint)を選択し【ENTER】を押します。
下記のように表示されたら完了になります。
・ ・・ Successfully created project frontend. ・ ・・ Get started with the following commands: $ cd frontend $ npm run serve
次にプロジェクトフォルダに移動して必要なパッケージを追加していきます。
>cd frontend
①vuetifyのインストール
Vue.jsのマテリアルデザインコンポーネントフレームワークです。
簡単に奇麗で直観的なUIを作成することが可能になります。
>vue add vuetify
? Choose a preset: (Use arrow keys)
> Default (recommended)
Prototype (rapid development)
Configure (advanced)
Default (recommended)を選択し【ENTER】を押します。
今回はログイン画面を簡単に作成する為に使います。
②vue-routerのインストール
SPAでルーティング制御をするためのものになります。
>npm install vue-router
今回はコンポーネントとルートのマッピングはもちろんのこと、ナビゲーションガードにも使います。
③axiosのインストール
ブラウザとnode.js上で動くPromiseベースのHTTPクライアントです。
jQueryでいうajaxと同じようなものです。
Vue.jsでは非同期通信を行うのにaxiosを使うのがスタンダードとなっています。
>npm install axios
今回は認証情報をバックエンド側にPOSTする為に使います。
④vuexの追加
Vue.js アプリケーションのための 状態管理パターン + ライブラリです。
簡単に言うと異なるコンポーネントで情報を共有するために使います。
>npm install vuex
今回は認証情報をコンポーネント間で共有する為に使います。
追加したパッケージたちは【pachage.json】の【dependencies】に
しっかりと記載されています。
"dependencies": { "axios": "^0.19.2", "core-js": "^3.6.5", "vue": "^2.6.11", "vue-router": "^3.4.3", "vuetify": "^2.3.9", "vuex": "^3.5.1" },
また、--saveオプションは【npm v5】以降不要になっているのでここでは省いています。
バックエンド
まずはプロジェクトを作成します。
>cd basicsample >mkdir backend >cd backend >npm init -y
npm initで初期化処理を行うと、アプリケーションに必要な情報を対話形式で入力していくことになります。
ここでの情報は【package.json】に記録されます。
今回は特に意識する必要がないので【-y】でとばしています。
次に必要なパッケージを追加していきます。
①expressのインストール
Node.js のための高速で、革新的な、最小限のWebフレームワーク。
これはNode.jsでWebアプリケーションを開発するためには必須といっていいでしょう。
>npm install express
②body-parserのインストール
HTML フォームからポストされたデータをパースしてくれます。
>npm install body-parser
今回はreq.body経由でデータを取得するために使います。
③corsのインストール
Cross-Origin Resource Sharing オリジン間リソース共有のこと。
ブラウザは異なるオリジン間のアクセスに制限をかけています。
別のオリジンサーバーへのアクセスを許可出来るようになります。
>npm install cors
これでとりあえず準備は完了です。
5.コード
それでは実際にコードを書いていきます。
フロントエンド
①src/main.js
アプリケーションのエントリポイントです。
まずは使用するモジュールをimportしていきます。
Vue.jsのプラグインであるaxiosをVue.use()メソッドで使えるようにします。
更にPOST先のbackend側のURLを設定しています。
import Vue from 'vue' import App from './App.vue' import vuetify from './plugins/vuetify'; import router from './router.js' import axios from 'axios' import store from '@/store' Vue.config.productionTip = false Vue.use({ install (Vue) { Vue.prototype.$axios = axios.create({ baseURL: 'http://localhost:3000/' }) } }) new Vue({ vuetify, router, store, render: h => h(App) }).$mount('#app')
②src/router.js
ルートのマッピングになります。
認証済でなければPage1、Page2を表示出来ないようにし、
Login画面に飛ばすように設定しています。
import Vue from 'vue' import Router from "vue-router" import Page_1 from "./components/Page1.vue" import Page_2 from "./components/Page2.vue" import Login from "./components/Login.vue" import Store from '@/store/index.js' Vue.use(Router) //export default new Router({ const router = new Router({ mode: "history", base: process.env.BASE_URL, routes: [ //ルーティングの設定 { path: '/page1', //ブラウザに表示されるURL component: Page_1, //表示するコンポーネント name: 'page1', //ルートの名前を指定 meta: { requiresAuth: true } }, { path: '/Page2', component: Page_2, name: 'page2', meta: { requiresAuth: true } }, { path: '/', component: Login, name: 'home', }, { path: '/Login', component: Login, name: 'login', } ] }); router.beforeEach((to, from, next) => { if (to.matched.some(record => record.meta.requiresAuth)) { if (!Store.state.isLogin) { next({ path: '/Login', query: { redirect: to.fullPath } }) } else { next(); } } else { next(); } }); export default router
③src/store/index.js
アプリケーションの状態管理に使います。
isLoginで認証済かどうかを判断しています。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { isLogin : false, userId : '' }, mutations: { auth(state, user) { state.isLogin = true; state.userId = user; } }, actions: { fetch(context, user) { context.commit('auth', user); } }, modules: {}, }) export default store
④src/components/Login.vue
ログイン画面になります。
<template> <v-app> <v-card width="500px" class="mx-auto mt-5"> <v-toolbar color="primary" flat> test </v-toolbar> <v-card-title> Login? </v-card-title> <v-card-text> <v-form> <v-text-field prepend-icon="mdi-account-circle" label="user ID" v-model="authId"/> <v-text-field v-bind:type="showPassword ? 'text' : 'password'" prepend-icon="mdi-lock" v-bind:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" label="password" @click:append="showPassword = !showPassword" v-model="authPass"/> <v-card-actions> <v-btn block class="info" @click='post'>LogIn</v-btn> </v-card-actions> <div class="mt-12 text-center"> {{ msg }} </div> </v-form> </v-card-text> </v-card> </v-app> </template> <script> export default { name: 'Login', data () { return { showPassword : false, msg : 'userIDとpasswordを入力して下さい', authId : '', authPass : '' } }, methods: { async post() { const data = { id : this.authId, pass : this.authPass }; this.msg = await this.$axios.post('/test', data) .then(function (response) { console.log(response); return response.data.message; }) .catch(function (error) { console.log(error); return error.message; }); if(this.msg == 'OK'){ this.$store.dispatch("fetch", this.authId); this.$router.push('/Page1'); } } } }; </script>
⑤src/components/Page1.vue
<template> <div> <h1>ここはページ1です</h1> <h3>user:{{$store.state.userId}}</h3> <router-link to="/page2">ページ2へ</router-link> </div> </template>
⑥src/components/Page2.vue
<template> <div> <h1>ここはページ2です</h1> <h3>user:{{$store.state.userId}}</h3> <router-link to="/page1">ページ1へ</router-link> </div> </template>
バックエンド
①index.js
バックエンドはこれだけです。
id、passwordがtestであればOKを返します。
本来であればDBなどから取得した方がいいのですが
今回はベタ書きしています。
const express = require('express') const bodyParser = require('body-parser') const cors = require('cors') const app = express() app.use(bodyParser.json()) app.use(cors()) app.post('/test', function(req, res) { if(req.body.id == 'test' && req.body.pass == 'test'){ res.send({ message: 'OK' }) }else{ res.send({ message: '認証エラー' }) } }) app.listen(process.env.PORT || 3000)
6.動作確認
フロントエンド側は
>npm run serve
バックエンド側は
>node index.js
で起動させます。
ブラウザで【http://localhost:8080/】にアクセスすると
【Login.vue】で作成したログイン画面が表示されます。
user ID :test
password:test
と入力すると
【Page1.vue】が表示されます。
ログインが成功していない状態で直接
【http://localhost:8080/Page1】
を表示しようとするとログイン画面に飛ばされます。