JavaScript
Express
Vue.js
nuxt.js
vuetifyjs

これさえあればWEBアプリが簡単に作れる!Nuxt・Express・Vuetifyを使ったログイン画面の実装テンプレ


目的

nuxt.jsを使うことでWEBアプリが簡単に作れるようになりました。

加えてVuetifyやExpressを使うことで、高度なWEBアプリが開発できます。

今回はそれらを使ったログイン画面の実装テンプレートを紹介します。


実装に向けて

https://github.com/nuxt-community

基本このGithubを参考にしました。

Expressやauth-moduleのテンプレートはありますが、

まるっと統合したものが欲しかったので、これらを応用して作成しました。


使用したフレームワーク・ライブラリ


  • nuxt

  • Express(API)

  • vuetify(デザイン)

  • axios(API通信)


ドキュメント


GitHubレポジトリ

https://github.com/tonio0720/nuxt_login_template


ソース解説


フォルダ構成

./api                  # Express

./api/index.js
./api/routes # Express Router
./api/routes/auth.js # 認証用API
./assets
./assets/css
./assets/css/main.css # 全体のCSS
./components
./layouts # レイアウト
./layouts/default.vue # デフォルトのレイアウト(Vuetify)
./layouts/error.vue
./layouts/blank.vue # ログイン画面用のレイアウト(ログイン画面ではヘッダーとかは見えてほしくないので)
./nuxt.config.js # nuxtの設定
./package.json
./pages # この中に各ページを作る
./pages/index.vue # ホーム画面
./pages/login.vue # ログイン画面
./plugins
./static
./static/favicon.ico
./store
./store/index.js


nuxt.config.js


nuxt.config.js

module.exports = {

// <head>タグの中身
head: {
title: 'nuxt-login-template',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'nuxt login template' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{
rel: 'stylesheet',
type: 'text/css',
href: 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'
}
]
},
plugins: [],
css: [
// 全体のCSS
'~/assets/css/main.css'
],
build: {
vendor: ['@nuxtjs/axios'],
extractCSS: true,
extend(config) {
if (process.server && process.browser) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
});
}

}
},
serverMiddleware: [
// API
'~/api/index.js'
],
// ライブラリの読込
modules: [
'@nuxtjs/axios',
'@nuxtjs/auth',
'@nuxtjs/vuetify'
],
axios: {
proxy: true
},
proxy: {
'/api': `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}`
},
// ここでauth-moduleを有効にする
auth: {
redirect: {
login: '/login',
logout: '/',
callback: '/login',
home: '/'
},
strategies: {
local: {
endpoints: {
login: {
url: '/api/auth/login',
method: 'post',
propertyName: 'token.accessToken'
}
}
}
}
},
// Vuetifyを有効にする
vuetify: {}
};



api

Expressを使って実装。

認証はexpress-jwtを使用。


index.js


index.js

const express = require('express');

const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const jwt = require('express-jwt');

const app = express();
const secret = 'dummy'; // jwt secret

app.use(cookieParser());
app.use(bodyParser.json());

// ログインしてなくてもここにはアクセスできる
app.use(
jwt({ secret })
.unless({ path: '/api/auth/login' })
);

app.use('/auth', require('./routes/auth'));

// other routes

app.use((err, req, res, next) => {
console.error(err);
res.status(401).send(err + '');
});

module.exports = {
path: '/api',
handler: app
};



routes/auth.js


auth.js

const { Router } = require('express');

const jsonwebtoken = require('jsonwebtoken');

const router = Router();
const secret = 'dummy';

async function checkAuth({ username, password }) {

// ここでDBに接続するなり、IDPASSの確認

if (username === 'xxx' && password === 'xxx') {
return true;
}

return false;

}

router.post('/login', async (req, res, next) => {

const { username, password } = req.body;

if (!await checkAuth({ username, password })) {
res.status(401).send('Invalid username or password');
return;
}

const accessToken = jsonwebtoken.sign({
username
}, secret);

res.json({ token: { accessToken } });

});

router.get('/user', (req, res, next) => {
res.json({ user: req.user });
});

router.post('/logout', (req, res, next) => {
res.json({ status: 'OK' });
});

module.exports = router;



pages


index.vue


index.vue

<template>

<v-container fluid>
index
</v-container>
</template>

<script>

export default {
// middlewareにauthを追加することで、
// ログインしていないとログイン画面にリダイレクトされる
middleware: ['auth'],
head() {
return {
title: 'ホーム'
};
}
};
</script>

<style scoped>
</style>



login.vue


login.vue

<template>

<v-container>
<v-layout justify-center>

<v-flex xs12 sm4>

<v-toolbar color="primary" dark>
<v-toolbar-title>ログイン</v-toolbar-title>
</v-toolbar>

<v-card>
<v-container fluid>
<v-form ref="form" v-model="valid" lazy-validation>

<v-layout row wrap>
<v-flex xs12>
<v-alert v-if="error" :value="true" type="error" outline>
{{ error }}
</v-alert>
</v-flex>
</v-layout>

<v-layout row wrap>
<v-text-field type="text" v-model="username" label="ログイン名" required></v-text-field>
</v-layout>

<v-layout row wrap>
<v-text-field type="password" v-model="password" label="パスワード" required></v-text-field>
</v-layout>

<v-layout row wrap justify-end>
<v-btn color="success" :disabled="!valid" @click="login">ログイン</v-btn>
</v-layout>

</v-form>
</v-container>
</v-card>

</v-flex>

</v-layout>
</v-container>
</template>

<style scoped>
</style>

<script>

export default {
layout: 'blank', // layouts/blank.vueを使用
middleware: ['auth'],
head() {
return {
title: 'ログイン'
}
},
data() {
return {
valid: true,
username: '',
password: '',
error: null
};
},
methods: {

async login() {

this.error = null;

if (this.$refs.form.validate()) {

return this.$auth
.loginWith('local', {
data: {
username: this.username,
password: this.password
}
})
.catch(e => {
this.error = 'ログインに失敗しました。IDかパスワードが間違っている可能性があります。';
});

}
}
}
}
</script>



使い方

ソースのダウンロード

$ git clone git://github.com/tonio0720/nuxt_login_template.git .

依存のインストール

$ npm i

開発環境に実装

$ npm run dev

※username:xxx、password:xxxでログインできます。(api/routes/auth.js)

login.PNG


最後に

いかがでしたでしょうか。

不明点等あれば、コメントにお願いいたします!