バックエンドエンジニアがVue.jsとTypeScriptに入門して10日ほど勉強した内容をまとめてみました。

普段の業務では主にサーバーサイドを担当することが多いのですが、Vue.jsとTypeScriptを使ったフロントエンドの作業を担当する機会がありましたので、10日ほどの間でざっと勉強した内容をまとめてみました。

(フロントエンドに関しては初学者のため理解の浅い部分が多々あると思います。誤り等ありましたらご指摘頂けますと大変ありがたいです)

# ES5

ECMAScript5。要するに古いJavaScript。モダンなブラウザであればほとんど動作する。モジュールという概念が存在しないので、ファイルの依存関係の管理がとても大変。

# CommonJS/AMD

ES5の欠点を補うため、つまりJavaScriptのコードをモジュールとして扱えるようにするために、CommonJSやAMDという`仕様`が作成された。CommonJSは主にサーバーサイドでの用途を想定(node.jsもCommonJS方式)。AMDはブラウザでの使用を前提としているらしい。

```js:CommonJS
// hello.js
module.exports.greet = function () {
  console.log('Hello!');
};
							
// index.js
var hello = require('hello');
hello.greet(); // Hello!
```

```js:AMD
// hello.js
define(function () {
  return function greet() {
    console.log('Hello!');
  };
});

// index.js
define(["hello"], function (hello) {
  hello.greet(); // Hello!
});
```

AMDに関しては、依存するモジュールの数が多くなると記述が大変になる。AMDに対応しているライブラリであるRequireJSはこの問題に対応しており、下記のような記法を使用可能。

```js:RequireJS
define(function(require, exports, module) {
  var hello = require('hello');
  var foo = require('foo');
  var bar = require('bar');
  ...
  hello.greet(); // Hello!
});
```

- [JavaScriptのモジュール管理(CommonJSとかAMDとかBrowserifyとかwebpack) | tsuchikazu blog](https://tsuchikazu.net/javascript-module/)
- [AMD & RequireJS - Qiita](https://qiita.com/nanocloudx/items/70f1316debf05b93ac82)
[RequireJS使い方メモ - Qiita](https://qiita.com/opengl-8080/items/196213867b859daea719)

CommonJSは(Webpack等を使用した)ビルド時に依存関係を解決する方式だが、AMD(RequireJS)は実行時に依存関係を解決する方式である。

CommonJSはツールやライブラリではなく`仕様`のため、ビルド時に依存関係を解決する何らかのツールが必要となる。それが後述する`Browserify`や`Webpack`である。

AMDも`仕様`のため、それに対応するライブラリが必要である。それがRequireJSであり、さらにRequireJSはAMDには存在しない便利記法を導入している。

コードの中で`module.exports`と`require`が使われていたらCommonJS形式、`define`が使われていたら`RequireJS(AMD)`と考えて良いのだが、両方に`require`という用語が登場するので初学者にはここがちょっと分かりにくい。(学習を始めた当初は、requireというキーワードが使われていたらRequireJSが使われているのだと勘違いしていました)

最近は後述のWebpackを使ってビルド＆バンドルする方式が主流になっており、AMDやRequireJSに関してはあまり使われなくなっているようなので、Webpackだけ勉強しておけば良いようである。

# ES6(ES2015)

新しいバージョンのJavaScript。一部の機能はモダンなブラウザでも動作しないため、後述する`babel`等の`トランスパイラ`を使用して、ES2015で記述したコードをES5に変換する方式が主流になっている。

ES6で導入された機能は色々あるが、モジュール管理用に導入された`import/export`機能の理解と、CommonJSの`module.exports/require`との区別が初学者にとっては重要。(Vue.jsのコードの中でも両方のキーワードが登場するので混乱するが、設定ファイル系はCommonJS方式の`module.exports/require`、コンポーネント等のコードはES2015の`import/export`を使うと考えておけば良いと思われる)

- [ES2015(ES6) 入門 - Qiita](https://qiita.com/soarflat/items/b251caf9cb59b72beb9b)

# babel

ES2015のコードをES5にトランスパイルする際に使用される。設定ファイルとして`.babelrc`が使用される。

`preset`という概念がある。要するに`新しいJavaScriptの機能をコード内でどこまで使用可能にするか`をこれで決定するようである。(指定したpresetで対応出来ている機能であれば問題なくES5形式にトランスパイルしてくれるが、そうでなければエラーになるようである)

Vue.jsの場合は`stage-2`と`env`というpresetが`.babelrc`内でデフォルトで指定されている。`babel-preset-stage-2`に関しては、下記の記事で記載されているような機能がES2015のコード内で使用可能になるようである。(`babel-preset-env`等とは異なり、一部の最新機能だけをチェックするpresetだと思われる)

- [babel の preset-stage-n の内訳 - Qiita](https://qiita.com/yancya/items/b50f236de34d0ea1f52d)

`babel-preset-env`に関しては少々分かりにくいが、`targets`を指定しない場合は`babel-preset-latest`と同様な挙動になるらしい。(`babel-preset-latest`は、最新のES6の構文を認識してES5に変換してくれるが、ターゲットブラウザやnode.jsのバージョン等は指定出来ないので、既にほとんどのブラウザが対応済みな機能であっても全て古いES5に変換すると考えてよいらしい)

`targets`で例えばターゲットブラウザとバージョンを指定した場合は、そのブラウザのバージョンが対応している機能に関しては、(機能の対応テーブルを見て)その機能に関してはコードを古くし過ぎないように変換してくれるようである。多分。

- [babel-preset-envで環境に合わせてJavaScriptをトランスパイルする | KEYPOINT – キー・ポイント株式会社 開発日誌](https://www.key-p.com/blog/staff/archives/105449)

ちなみに、Vue.jsのデフォルトの`.babelrc`では、`babel-preset-env`に関して、下記のように`"modules": false`という指定が行われている

```
  "presets": [
    ["env", {
      "modules": false
    }],
    ...
  ],
```

これは何かというと、下記の記事で説明されているように、Webpackの`Tree Shaking`を有効にするためである。babelはデフォルトの設定だと、ES2015の`import/export`をCommonJSの`module.exports/require`に変換してしまうので、`"modules": false`を指定することでこの挙動を防止しているようである。

- [Webpack2のTree Shakingを試す - Qiita](https://qiita.com/pirosikick/items/863830856891d40308cb)

# Browserify/Webpack

基本的には、JavaScriptモジュールやCSS等のアセットのバンドル(ファイルを一つにまとめる)を行うためのツールである。

babelはES2015からES5への変換は行うが、JavaScriptのモジュール管理システムには対応していないため、モジュール間の依存関係の解決等は別のツールが行う必要がある。それを行うのがBrwoserifyやWebpack。

Browserifyと異なり、WebpackはAMD(RequireJS)形式の記述にも対応していたり、JavaScriptに加えてCSS等のアセットのバンドル、および単一でなく複数ファイルへの出力にも対応している等の違いがあるようである。ローカルWebサーバー使用時のLive Reload的な機能も備わっている。

Vue.jsではデフォルトでWebpackが使用されるので、特別な理由が無ければWebpackだけ勉強しておけば良いと思われる。

Gulp等のタスクランナーとの違いはなにかという点に関してはいまいち理解出来ていない。タスクランナーと一緒に使うことも可能なようであるが、Vue.jsではタスクランナーは使用せずに`npm-scripts`を使用している。下記の記事にも記載されているが、タスクランナーは使わずに`npm-scripts`と`Webpack`だけでタスクを管理するのが主流(?)になってきているのかもしれない。

- [今時のフロントエンド開発2017 (1. 愚痴編) - Qiita](https://qiita.com/Lyude/items/783a972bace33002455c)

# Vue.js

ReactやAngular等と同じく、JavaScriptのフロントエンドのフレームワーク。MVVMパターンを採用している。

- [はじめに — Vue.js](https://jp.vuejs.org/v2/guide/)

- [Vue.jsではじめるMVVM入門 | DeNA DESIGN BLOG](http://design.dena.com/engineering/vue-js%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8Bmvvm%E5%85%A5%E9%96%80/)

初学者の学習リソースとしては下記がお薦めと思われる。(ステップバイステップ形式の公式チュートリアル等があると助かるのですが、そういうものはまだ存在していないようです)

(追記：ドットインストールさんで[Vue.jsのバージョン2.5対応の動画](https://dotinstall.com/lessons/basic_vuejs_v2)が公開されましたので、初学者の方はそちらから学習するのが良いかもしれません)

- [Vue.js入門 ―最速で作るシンプルなWebアプリケーション：連載｜gihyo.jp … 技術評論社](http://gihyo.jp/dev/serial/01/vuejs)

(私の場合は、とりあえず[Vue.js入門](http://gihyo.jp/dev/serial/01/vuejs)でざっと勉強した後は、実際に手を動かしてアプリケーションを作りつつ、分からないことは逐次ネットで調べていくというスタイルで覚えていきました)

エディタとしては、TypeScriptを使うことが前提であれば、公式ドキュメントもお薦めしている`VSCode`と`Vetur`プラグインの組み合わせが無難と思われる。

- [TypeScript のサポート — Vue.js](https://jp.vuejs.org/v2/guide/typescript.html#開発ツール)

現時点ではまだ`TypeScript`用のscaffoldは用意されていないので、`vue-cli`によるプロジェクト作成後に、独自にTypeScript化を行う必要がある。

Vue.js用のボタンやDatetimePicker等のUIライブラリに関しては、[ElemeFE/element](https://github.com/ElemeFE/element)というパッケージが広く使われているようである。

- [Vue.js製のUIフレームワーク「Element」の使い方 - SCOUTER開発者ブログ](http://techblog.scouter.co.jp/entry/2017/11/14/120000)

ステート管理には`Vuex`というライブラリを使用する。`Flux`パターンの実装であるとのこと。`Redux`に似ているらしい。とりあえず下記等でざっと勉強しておけばよいと思われる。

- [Vuex とは何か? · Vuex](https://vuex.vuejs.org/ja/intro.html)

- [Fluxデザインパターンの勉強 - Qiita](https://qiita.com/kikurage/items/49828b270b73dd0fbbb8)

- [Vue.js + Vuexで開発をしてみよう！ - Tech Blog - Recruit Lifestyle Engineer](https://engineer.recruit-lifestyle.co.jp/techblog/2016-09-15-try-vue-flux/)

- [Vue + Vuex を使ってみた感想と、Redux との比較 – Toro_Unit](https://torounit.com/blog/2016/11/29/2495/)

Vuexと`LocalStorage`を連携させたい場合は、[robinvdvleuten/vuex-persistedstate](https://github.com/robinvdvleuten/vuex-persistedstate)というライブラリが使える。(`LocalStorage`は、[こちら](http://perutago.seesaa.net/article/206013819.html)の記事でも記載されているように、モダンブラウザであれば基本的に問題なく使用可能なようである)

[Vue.jsでSPAなBingoカードアプリを作ってみてわかったこと - Qiita](https://qiita.com/ma2shita/items/993758c9f9ab942a0a2a)

# TypeScript

TypeScriptの学習リソースに関しては色々あると思いますが、私はとりあえずドットインストールさんの動画でざっと学習しました。

- [TypeScript入門 (全19回) - プログラミングならドットインストール](https://dotinstall.com/lessons/basic_typescript)

TypeScriptには`型定義ファイル`というものが存在する。当初からTypeScriptで記述されているモジュールであれば不要だが、JavaScriptで記述されたモジュールをTypeScriptから使用するためには型定義ファイルが必要。

型定義ファイルに関しては初学者向けの学習リソースが見当たらなかったが、下記の記事をじっくりと読んで内容を理解出来れば大体オッケーではないかと思われる。

- [TypeScript の型定義ファイルと仲良くなろう - Hatena Developer Blog](http://developer.hatenastaff.com/entry/2016/06/27/140931)

下記の記事等で説明されているようにTypeScript2からは`tsd`や`typings`等の型定義ファイル管理ツールは不要になり、npmだけで型定義ファイルが使用出来るようなったようである。

- [TypeScript2.0時代の、型定義ファイル - Qiita](https://qiita.com/kohashi/items/d7a8ff57fe3a3e4c95f4)

- [TypeScript 2 のモダンな書き方 - Qiita](https://qiita.com/karak/items/ef69aa71c19932fa5c1b)

Vue.jsのTypeScript化に関しては、下記のチュートリアルや記事でざっと学習すればおおよその手順は理解出来ると思われる。

- [Microsoft/TypeScript-Vue-Starter](https://github.com/Microsoft/TypeScript-Vue-Starter)

- [VueJS+TypeScript の開発環境を作ってみた - IT探検記](http://itexplorer.hateblo.jp/entry/20170807-vuejs-typescript-dev-env)

- [Vue.jsを使ったTypeScriptとwebpackの設定](https://www.tmp1024.com/programming/vue-typescript-webpack)

- [vue-cliを使ってとにかく楽してVue.jsでTypeScriptを使いたい | Black Everyday Company](https://kuroeveryday.blogspot.jp/2017/09/how-to-use-vuejs-with-typescript.html)

# Tips

## Vue.jsをTypeScript化する際のwebpack.base.conf.jsの設定

```js:webpack.base.conf.js
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: [
          'babel-loader',
          {
            loader: 'ts-loader',
            options: {
              appendTsSuffixTo: [/\.vue$/]
            }
          },
          {
            loader: 'tslint-loader',
            options: {
              configFile: 'tslint.json'
            }
          }
        ],
        include: [resolve('src'), resolve('test')]
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
```

```js:vue-loader-conf.js
module.exports = {
  loaders: Object.assign(
    { ts: 'ts-loader!tslint-loader' },
    utils.cssLoaders({
      sourceMap: sourceMapEnabled,
      extract: isProduction
    })
  ),
```

色々な方式があると思われるが、とりあえず上記のような設定を採用した。

この設定の場合、`*.ts`ファイルに関するローダーは`tslint-loader -> ts-loader -> babel`の順に適用される。

`ts-loader`の`appendTsSuffixTo`の部分は、`*.ts`ファイルと`*.vue`ファイルの依存関係を解決する際に必要なようである。`ts-loader`以外に`babel-loader`も使っている理由は、`ts-loader`では`ES5`までの変換は行わずに`ES6`までの変換だけを行って、`ES6`から`ES5`への変換は`babel`を使用したいため。

`vueLoaderConfig`変数には`vue-loader-conf.js`の中身が適用されますが、ここで`{ ts: 'ts-loader!tslint-loader' }`を指定することで、`*.vue`ファイル内のTypeScriptの部分にも`tslint-loader`と`ts-loader`が適用される(はず)。

# 本文中に記載されていない参考資料

- [ES2015(ES6)な時代だからこそ、ES5を改めて調べたJavaScript初級者のメモ - Qiita](https://qiita.com/zaru/items/d833dca52962c3f7770f)
- [ES5とES6の違いをまとめてみた(メモ) - Qiita](https://qiita.com/rifutan/items/a55f132d4dae7e2f1941)
- [ES6の概要と、最新ブラウザに対応させる「Babel」の使い方 | ES6のある星に生まれて](https://liginc.co.jp/260178)
- [JavaScriptのモジュールシステムに関するまとめ - Qiita](https://qiita.com/kami_zh/items/f093c34906d14ba65ad3)
- [JavaScriptのモジュールシステムの歴史と現状 - Qiita](https://qiita.com/mizchi/items/6b569cc75dbcc26a1f15)
- [いまどきなフロントエンド開発者になる！JSのモジュール管理ってこういうこと - WPJ](https://www.webprofessional.jp/javascript-modules-bundling-transpiling/)
- [フロントエンド開発の基本知識（2017年夏） - Qiita](https://qiita.com/norioxkimura/items/1dc1cea1c0a8ea7adf31)

# おまけ

Youtubeの方で、ITエンジニアやIT業界に興味のある方たち向けの[雑食系エンジニアTV](https://www.youtube.com/channel/UC_HLK-ksslL-Z_2wiIZDlMg)というチャンネルを始めました。もしご興味ございましたらチャンネル登録してみて頂けると大変嬉しいです(^.^)