Shin x Blog

PHPをメインにWebシステムを開発してます。Webシステム開発チームの技術サポートも行っています。

Vue.js + Vuex + TypeScript ファーストインプレッション

日頃は、サーバサイドの開発が主なのですが、その UI として フロントエンドの開発も行うことがあります。最近話題の Vue.js を試してみたのでその感想などを。

前提

これまで利用した構成

ベースとして、これまでプロダクションで利用したことがある構成は以下です。いずれも、フォームベースの SPA で、現在も稼働しています。

  • AngularJS 1.x
  • AngularJS 1.x + TypeScript
  • React + Redux
  • React + MobX + TypeScript

Vue.js 構成

以下の構成で、ログイン、一覧表示、フォームを API サーバと通信して動作させるところまで実装してみました。

  "dependencies": {
    "axios": "^0.18.0",
    "bootstrap": "^4.1.3",
    "jquery": "^3.3.1",
    "popper.js": "^1.14.5",
    "vue": "^2.5.17",
    "vue-class-component": "^6.0.0",
    "vue-property-decorator": "^7.0.0",
    "vue-router": "^3.0.1",
    "vuex": "^3.0.1",
    "vuex-class": "^0.3.1",
    "vuex-router-sync": "^5.0.0"
  },

雑感

ちょっと試す、がすぐにできる

本家マニュアルのサンプルがそうですが、Vue.js 本体を script タグで読み込むだけで利用できます。SPA ではなくても、ページの一部に動的な要素を組み込む場合にすぐに使えるので、これだけでも道具箱に入れておくと良いですね。

https://jp.vuejs.org/v2/guide/index.html#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB

vue-cli が楽

まず、何はともあれ開発環境の構築から。これまで経験してきた構成でもそうでしたが、ここに苦労することが多くて、開発にたどり着くまでに手間がかかり、慣れていない構成だと腰が重くなることがありました。

ただ、時代は進み、現在では、vue-cli や create-react-app などコマンドでベースは自動生成できるようになったので、かなり楽になりました。

特に vue-cli は良く出来ており、Vue.js 本体だけでなく、vue-router や Vuex、TypeScript などの組み込みも簡単にできました。初期状態では、シンプルですが、ちゃんと vue-router や Vuex を組み込んだアプリケーションも含まれるので、実装サンプルとしても参考になります。

$ vue cli sample
Vue CLI v3.1.1
? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

https://cli.vuejs.org/

vue ファイル

Vue コンポーネントを記述する .vue ファイルは、3 つのパートで構成されています。パートの指定にタグを使っているので、初見では戸惑ったのですが、意味が分かれば問題ありません。

React の JSX のように全てが JavaScript で表現できるというのも好きなのですが、これはこれで View / Script / Style が分離できているので分かりやすいです。デザイナさんと協業する場合は、JSX より vue ファイルの方が触ってもらいやすそうですね。

<template>
  View(HTML)
</template>

<script>
  Config, Logic(JavaScript / TypeScript)
</script>

<style>
  CSS
</style>

ちなみに、vue ファイルは、Single File Component と呼ばれるのですが、これの略称が SFC で、React 界隈で呼ばれる Stateless Functional Component の略称と同じで、はじめは戸惑いました ;)

https://jp.vuejs.org/v2/guide/single-file-components.html

template ディレクティブ

テンプレートで値のバインドや動的な操作を行いたい場合は、v-ifv-for などのディレクティブを利用します。AngularJS を使っていたので、これは特に違和感無いです。

状態によって、ビューを出し分けたい時、JSX だと、早期リターンが使えたのが楽だったのですが、Vue.js には v-else があるので、わりとすっきり書けます*1

ただ、書き方が AngularJS に似ているので、うっかり ng-if と書いて、v-if に書き直すというのも何度もやってしまいます :)

scoped css

<style scoped> と宣言するだけで、コンポーネントに閉じた CSS を適用できます。最終的にどのような形式になるかは別にして、ただ宣言するだけで実現できるというのはホント楽です。

今回は、bootstrap を利用したので、全体のスタイルとしてはこれを利用し、差分を style タグ内で指定するという形を取りました。

vue-router / Vuex 連携

SPA を実装するとなるとルータやストア(ステート)管理が欲しくなります。Vue.js ではこうした機能は別パッケージとなっていますが、公式のパッケージとして扱われており、導入もスムーズに行えます。

vue-cli でインストールすれば、単にオプションを選択するだけなので、別パッケージということを意識する必要もなく利用できます。このあたりの連携も苦労するポイントだったりするので、簡単に導入できるのは良いですね。

React のようにそれぞれのパッケージが独立しているのは利点でもあるので、一長一短はありますが、導入が楽なのは Vue.js でした。

Vuex

Flux アーキテクチャが導入したかったので、Vuex を組み込みました。さらっとドキュメントを見ると、reducer が mutation になっているくらいで概ね同じなのかなと思っていました。

触った感触では、以下のような違いを感じました。

mutation を直接呼んで、state を変更

Redux では、コンポーネントから store を変更する際は、action を発行して、対応する reducer が変更後の store を返し、それが反映されるという流れでした。

Vuex では、コンポーネントから直接 mutation を呼んで、state を変更するようです。もちろん、action を呼んで、そこから mutation を呼ぶこともできるのですが、非同期処理などが無い場合は、mutation を呼べば ok です。

サイクルは同じ方向を回るので問題は無いですし、非同期処理などが絡まない場合は action を経由しない分、実装は楽かもしれません。

コンポーネントから直接 state を操作

コンポーネントでは、state を this.$store.state.foo のように直接参照できます*2。これは値の読み取りだけでなく、代入も出来てしまうので、やりようによっては、ただのグローバル変数となります。

このあたりは開発者やチームに自制心が求められるところで、せっかく Flux アーキテクチャのライブラリを採用しているのに、サイクルとは別にあちらこちらで state が変更されると、かえって悲惨なことにも成りかねません。

コードレビューでコンポーネントからは state を直接参照しない、少なくとも値の変更はしないなどのチェックは必要そうです。lint ツールでこういうチェックができるといいですね。

mapGetters() や mapActions() のようなヘルパー関数を使って、必要なもののみコンポーネントにマップする方法もあるので、こちらの方が行儀は良さそうです。

TypeScript

TypeScript 自体の導入は簡単です。初期設定が終わっていれば、コンポーネントでも <script lang="ts"> を宣言するだけで、その中のスクリプトは TypeScript で書くことができます。

ただ、テンプレートは TypeScript では無いので、補完や型チェックが不十分だったり、Vuex の連携でもその恩恵が薄かったりします。

完全な型チェックを求めると不満があるかもしれませんが、JavaScript よりはチェックが機能しますし、導入も簡単なので、TypeScript で書くつもりです。このあたりは、フレームワーク、ライブラリ、ツールの進化で改善していきそうですしね。

Vue.js 入門

Vue.js 触るにあたって、Vue.js入門 基礎から実践アプリケーション開発まで を読みました。これはいいですね。

この手のフレームワークのサンプルは、1 画面で完成するカウンターや Todo アプリが多く、一覧画面とフォーム画面で構成するようなサンプルは意外と少なかったりします。

その点、この本では、まさにこうした構成のサンプルアプリケーションを題材として扱っており、完全に自分のニーズにフィットした内容でした。タイトルに「入門」とは付いています*3が、開発現場で Vue.js を導入する際に使える内容がふんだんに盛り込まれています。

Vue.js を試すなら、まずはこの本からはじめるのがオススメです!

Vue.js入門 基礎から実践アプリケーション開発まで

さいごに

そんな感じで、Vue.js を試してみた感触を書いてみました。導入の障壁が低いので、ページの一部から SPA まですぐに試せるのが良いですね。Laravel が採用しているのも分かる気がします :)

React も良いので、それはそれで継続して使っていこうとは思いますが、ツールの一つとして Vue.js も触っておいて損は無さそうです。React やっていれば、キャッチアップは楽なので、試してみるのも良いですよ。

*1:AngularJS だと ng-if が複数並ぶのがウーンという感じでした。

*2:公式ドキュメントにも記載されている方法です。

*3:書名を決めるには色々な要素があるので、著者陣の思ったとおりになるとは・・・おっと、誰か来たようだ