1. はじめに
社内で Nuxt.js
+ TypeScript
+ Vuetify
の構成で、SPAを開発しました。
その際に開発効率が高くて良いと感じたので、環境構築や開発の方法をご紹介します。
良いなと思ったことは下記の3点です。
- Nuxt.jsを使うことで環境構築が簡単に行える
- TypeScriptを使うことで型の恩恵を受けながら開発を行える
- Vuetifyを使うことでマテリアルデザインのUIを手軽に扱える
今回は下の画像のようなSPAを作成するところをゴールとします。
現在の時刻から、今年が何%進んでいるかをプログレスバーで表示します。
![]() |
---|
※この記事ではSSRは取り扱いません。ご了承ください。
2. 技術紹介
この記事で取り扱う下記の言語やフレームワークについて概要をご紹介します。
- Nuxt.js
- TypeScript
- Vuetify
2.1. Nuxt.js
Nuxt.js
は、 Vue.js
のアプリケーションを構築するためのフレームワークです。
Vue.js
で開発する際に必要になることが多い、下記のようなフレームワークを含んでいます。
- Vue-Router
- Vuex
- Vue Server Renderer
本来であれば上記のフレームワークが必要かどうか検討し、必要なものを組み合わせる設定をしなければいけないのですが、 Nuxt.js
を使用すればこれらの面倒から開放されます。
2.2. TypeScript
TypeScript
はマイクロソフトによって開発された言語で、 JavaScript
に静的型付けやクラスベースのオブジェクト指向といった機能を追加したような言語です。
2.3. Vuetify
Vue.js
をベースに開発されたUIフレームワークで、下記のような特徴があります。
- マテリアルデザインを手軽に扱える
- ドキュメントやサンプルのソースコードが豊富
特に後者の「サンプルが豊富」である点が、他のフレームワークに比べていいところだと思います。
3. 構築手順
上記でご紹介した技術が使えるような環境を構築する手順をご紹介します。
下記の4つの手順に分けてご紹介します。
- テンプレートのプロジェクトから始める
- UIのソースコードを削除する
- Vuetifyを導入する
- 自分のアプリを実装する
手順1と2でプロジェクトの準備、手順3と4でアプリの実装を進めます。
3.1. テンプレートのプロジェクトから始める
Nuxt.js
では環境構築を簡単にするめにいくつかのテンプレートが準備されています。
今回は TypeScript
用のテンプレートを使用します。
まずは vue-cli
のインストールです。
この記事ではグローバルにインストールします。
コマンドを実行してバージョン番号が表示されたら問題なしです。
$ npm install -g @vue/cli
$ vue --version
> 3.5.1
$ npm install -g @vue/cli-init
$ vue init --version
> 3.5.1
vue-cli
の準備が整ったら、いよいよテンプレートからプロジェクトを作成します。
下記ページを参考に進めます。
https://github.com/nuxt-community/typescript-template
$ vue init nuxt-community/typescript-template my-project
プロジェクト名などを聞かれますので適宜答えてください。
プロジェクトが作成されたら早速ローカルで動かしてみましょう。
$ cd my-project
$ npm install
$ npm run dev
ブラウザで localhost:3000 に接続してページが表示されたら成功です。
![]() |
---|
3.2. UIのソースコードを削除する
次に、UIのソースコードを削除して自分のアプリを作る準備をします。
現在はロボットの顔が表示されているので、これが表示されないようにします。
言語が TypeScript
なので、エディタはVisual Studio Codeがおすすめです。
https://code.visualstudio.com/
この記事の対象外になっているSSRの記述部分を削除します。
my-project/store/index.ts
の nuxtServerInit()
を削除してください。
その際に不要になった import
もあれば削除してください。
// 中略
export const actions: ActionTree<RootState, RootState> = {
// ここから下を削除
async nuxtServerInit({ commit }, context) {
let people: Person[] = []
people = context.isStatic ?
localRandomData :
await context.app.$axios.$get("./random-data.json")
commit("setPeople", people.slice(0, 10))
}
// ここから上を削除
}
コードを削除して保存すると、自動で再ビルドが走り、すぐにブラウザで変更を確認できます。
変更が反映されていないと思ったら念の為リロードしてみてください。
Nuxt TypeScript Template
の文字だけがページに表示されていたら成功です。
3.3. Vuetifyを導入する
次にUIフレームワーク Vuetify
を導入していきます。
まずは Ctrl + c
で npm run dev
を停止させ、下記コマンドで Vuetify
を依存性に追加します。
$ npm install @nuxtjs/vuetify
次に設定ファイルに @nuxtjs/vuetify
を追記します。
export default {
// 中略
modules: [
"@nuxtjs/axios",
// 以下の行を追記
"@nuxtjs/vuetify"
],
}
なんとこれだけで Vuetify
が使えるようになっています。
導入が簡単なフレームワークは嬉しいです。
早速 Vuetify
を使ってみるために、ページを編集していきます。
my-project/pages/index.vue
を編集します。
<template>
内を下記のように書き換えます。
少し行数が多いですが、ほとんど Vuetify
のドキュメントやサンプルのページに載っているものなので安心してください。
https://vuetifyjs.com/ja/components/navigation-drawers
<template>
<v-app>
<v-navigation-drawer app permanent>
<v-toolbar flat>
<v-list>
<v-list-tile>
<v-list-tile-title class="title">
Sample App
</v-list-tile-title>
</v-list-tile>
</v-list>
</v-toolbar>
<v-divider></v-divider>
<v-list dense class="pt-0">
<v-list-tile
v-for="item in items"
:key="item.title"
>
<v-list-tile-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-content>
<h1 class="header">Nuxt TypeScript Starter</h1>
</v-content>
</v-app>
</template>
<v-xxx>
のように、 v
から始まる要素は Vuetify
で準備されている要素です。
これらを組み合わせることで簡単にマテリアルデザインのUIを構築することができます。
保存すると、これだけでナビゲーションドロアーが実装できました。
手軽にUIを構築できるので Vuetify
はいいですね。
![]() |
---|
3.4. 自分のアプリを実装する
最後に目標の、今年のプログレスバーを実装したいと思います。
まずはナビゲーションドロアーのメニューを作ります。
今回はVueコンポーネントにメニューに関するデータをもたせたいと思います。
my-project/pages/index.vue
を下記のように編集します。
// 中略
@Component({
components: {}
})
export default class extends Vue {
items: Object[] = []
mounted() {
this.items = [
{
title: 'Progress',
icon: 'timer'
}
]
}
}
ビューコンポーネントに items
というフィールドを持たせ、 mounted()
が実行された時点で初期化しています。
mounted()
は特別なメソッドで、ビューコンポーネントがページにロードされた時に実行されるライフサイクルです。
実は 3.3 で書いた <template>
の中に、この items
を参照する記述があります。
v-for="item in items"
や {{ item.title }}
がこれに該当します。
この様に「データや処理に関する記述」と「デザインに関する記述」を分けて書くことができるのが、 Vue.js
や Nuxt.js
のいいところだと思います。
次にプログレスバーを準備し、UIを作っていきます。
下記のように <v-content>
内を書き換えます。
// 中略
<v-content class="bar-container">
<p class="title">
This year progress
</p>
<v-progress-linear
v-model="yearProgress"
></v-progress-linear>
<p class="percentage">
{{ `${this.yearProgress.toFixed(6)}%` }}
</p>
</v-content>
<v-progress-linear>
という要素を書くだけでプログレスバーを実現できます。
さすが Vuetify
、便利です。
このままだと yearProgress
が定義されていないというエラーになってしまいます。
ビューコンポーネントにフィールドを追加し、初期化するようにしましょう。
@Component({
components: {
}
})
export default class extends Vue {
items: Object[] = []
yearProgress: number = 20
mounted() {
this.items = [
{
title: 'Progress',
icon: 'timer'
}
]
}
}
最後にCSSを整えましょう。
// 中略
<style scoped>
.title {
font-family: 'Roboto', sans-serif;
font-size: 20px;
text-align: center;
}
.percentage {
font-family: 'Roboto', sans-serif;
font-size: 18px;
text-align: center;
}
.bar-container {
margin: 40px;
}
</style>
ここまでの記述で20%のプログレスバーができました。
![]() |
---|
あとはこの yearProgress
を動的に計算していくだけです。
ビューコンポーネントを下記のように書き換えます。
@Component({
components: {}
})
export default class extends Vue {
items: Object[] = []
yearProgress: number = 0
mounted() {
this.items = [
{
title: 'Progress',
icon: 'timer'
}
]
this.start()
}
start() {
setInterval(() => {
const date: Date = new Date()
const numDaysOfMonth: number = this.calculateDaysOfMonth(date.getFullYear(), date.getMonth())
const seconds: number = date.getSeconds() + date.getMilliseconds() / 1000.0
const minutes: number = date.getMinutes() + seconds / 60.0
const hours: number = date.getHours() + minutes / 60.0
const days: number = date.getDate() + hours / 24.0
const months: number = 1.0 * date.getMonth() + days / numDaysOfMonth
this.yearProgress = 100.0 * months / 12
}, 100)
}
calculateDaysOfMonth(year: number, month: number) {
return new Date(year, month, 0).getDate()
}
}
start()
が実行されると、その後100msごとに今年の進捗を計算するように実装しました。
計算結果は yearProgress
に格納しています。
もしこの実装中に型を間違えるような記述をすると、ビルド時にエラーとなります。
TypeScript
を採用したことで、型の間違いを早く知ることができます。
ここまでで下記のような、今年の進捗を表示するアプリが完成しました。
![]() |
---|
4. まとめ
この記事では Nuxt.js
, TypeScript
, Vuetify
の環境構築方法と、簡単なアプリケーションの実装をご行いました。
モダンなフレームワークを取り入れることで下記のようなメリットを享受できました。
- Nuxt.jsとそのテンプレートによる簡単な環境構築
- TypeScriptによる静的型付けの恩恵
- Vuetifyによる簡単でリッチなUIの組み立て
現在Web開発のフレームワークは他にもありますが、この記事を読んで Nuxt.js
, TypeScript
, Vuetify
を使ってみようと思ってくださる方がいらっしゃれば幸いです。