ナウい kintone カスタマイズ (1) 環境構築編

# 目次

(1) 環境構築編（この記事）
[(2) アプリ構築・設定編](https://qiita.com/iShinkai/items/f832ffd0436a3630832e)
[(3) アプリ実装編 part1](https://qiita.com/iShinkai/items/e2c808767b74451ab1b0)
[(4) アプリ実装編 part2](https://qiita.com/iShinkai/items/5ffedbe041741e541d1e)
[(5) ユニットテスト編](https://qiita.com/iShinkai/items/aab151b012bd96325812)

一連のソースは [GitHub](https://github.com/iShinkai/kintone-vue-ts-lead-management) で公開しています。

# 前置き

昨今の一般的な Web システムの開発者の皆さんにおかれましては今更かよとおっしゃる向きもあるかも知れませんが、**kintone** カスタマイズ界隈でも `Vue.js` とか `React` などのフロントエンドフレームワークが採用されている事例が増えて来ているかと思います。
公式の [GitHub](https://github.com/kintone) でも様々な言語向けに開発キットが公開されており、特に kintone が主戦場とする `JavaScript / TypeScript` 回りでは多くの便利なツール類が利用可能になっています。
kintone は[公式の開発者向けドキュメント](https://developer.cybozu.io/hc/ja)がけっこう充実しているものの、公式以外の（Qiita やはてなのような）ユーザー発信の技術記事ってそれほど多くない気がします。
そう言う背景もあり、一般的には広く採用され市民権を得ているフレームワークやトレンドの類が kintone カスタマイズ界隈に広まるまでタイムラグがあると言うか、情報の成熟が遅いように感じます。
と言うわけで、この記事では kintone カスタマイズにもモダンな開発手法を導入する手順を解説していきます。

# 前提

以下の環境で作業しています。

- macOS Catalina
- Homebrew 2.1.16
- Node.js 13.1.0
- VisualStudio Code 1.40.1

もう少し古い環境（Node.js 10.x とか）でもほとんど変わらないかと思いますし、Windows だって別に構いません。
未だに生の JavaScript を書く文化のカスタマイズをやっているような開発者の皆さんも割と多いと思われますが、`Node.js` くらいはなんとか自前で用意してください。

# 今回のゴール

上述の「モダンな開発手法」と言うのは、具体的には以下の通りです。

- [Vue.js](https://jp.vuejs.org/index.html) （フロントエンドフレームワーク）
- [TypeScript](https://www.typescriptlang.org/) （静的型付け・クラスベースの開発言語）
- [Prettier](https://prettier.io/) （コードフォーマッタ）
- [ESLint](https://eslint.org/) （静的コード検証）
- [Sass / SCSS](https://sass-lang.com/) （CSSプリプロセッサ）
- [Pug](https://pugjs.org/api/getting-started.html) （HTMLプリプロセッサ）
- [Jest](https://jestjs.io/ja/) （単体テストツール）
- [Babel](https://babeljs.io/) （トランスパイラ）
- [Webpack](https://webpack.js.org/) （モジュールバンドラ）

これらを利用して kintone カスタマイズの開発を便利に進め、かつ高品質な開発成果を出せるような環境を構築するのがこの記事の目的です。
フロントエンド界隈でバリバリやってる人たちにとっては今更そんな話？と言うレベルかも知れませんが。

それぞれがどのようなものかと言うのは省くか最低限の説明に留めます。
他所様に素晴らしい記事がたくさんありますので。

記事分量が多くなりそうなので、回数を分けて書いていきたいと思います。
今回は

- `Vue CLI` をインストール
- `Vue CLI` でプロジェクトを作る
- `Pug` をインストール
- デフォルトのコンテンツを `Pug` で書き直してみる

までを説明します。
この記事ではまだ kintone 関係ないですね。

# (1) 環境構築編

## Vue CLI をインストールする

上記のツール類を 1 つ 1 つ準備していくのは大変面倒なので、コマンド一発でよしなにしてくれる [Vue CLI](https://cli.vuejs.org/) を利用します。
執筆時点の最新バージョンは `Vue CLI 4.0.5` です。
少し前までは `3.x` でしたが、今のところ大きな違いは実感していません。

インストールは[公式](https://cli.vuejs.org/#getting-started)で説明されている手順通りにやるだけです。
ターミナル（Windows の人ならコマンドプロンプトなり PowerShell なり Git Bash なり）で作業します。

```bash
% yarn global add @vue/cli
```
![00-001-vue-cli.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/16a7a351-3554-92bf-e25b-777ff005bdd2.png)

正しくインストールされたかどうかは以下のコマンドで確認できます。

```bash
% vue --version
@vue/cli 4.0.5
```

正しく 4.0.5 がインストールされました。

## Vue プロジェクトを作成する

これも[公式](https://cli.vuejs.org/#getting-started)の説明通りです。
`Vue UI` はちゃんと使えば便利なのかも知れませんがコマンドで事足りるしなーとは思っています。

```bash
% vue create (プロジェクト名)
```

言わずもがなですが、カレントディレクトリにプロジェクトが作成されます。

今回は **kintone-vue-ts** と言うプロジェクトを作ることにしましょう。
なお、プロジェクト名には大文字を使う事はできません。単語区切りはハイフンかアンダースコアを用いれば良いでしょう。

```bash
% vue create kintone-vue-ts
```

ここからウィザード形式でいろいろ訊かれていきます。
以下では筆者がよく使う設定で進めますが、組織やチームの方針で定めがあればそれに従うべきです。
ソロ活動ならお好みで。

**Please pick a preset:**

プリセットに沿ってプロジェクトを作るか、アラカルト的に機能を選んでいくかを選択します。
**Manually select features** を選択して（下キーでフォーカスを移動して） Enter します。
![01-001-pick-a-preset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/f07dd645-cf9b-9111-dfb5-930f134bec2c.png)

**Check the features needed for your project:**

利用する機能を選択します。
下キーでカーソルを移動させ、スペースでオン／オフを切り替えられます。（緑がオン）
今回は

- Babel
- TypeScript
- CSS Pre-processors
- Linter / Formatter
- Unit Testing

にチェックを入れて進みます。
![01-002-check-the-features.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/9f704f67-a288-e320-aaa8-868a33da8734.png)

**Use class-style component syntax?**

`TypeScript` でクラス形式の記法を使用するかどうかの選択です。
**Y** として次に進みます。
![01-003-use-class-style.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/40826b70-f4ca-0c3e-764b-1ffe8ea9439c.png)

**Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?**

`TypeScript` はそれ自体に `JavaScript` へのコンパイラが含まれていますが、`Babel` でトランスパイルを担当させるかどうかを選択します。
**Y** として次に進みます。
![01-004-use-babel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/895210c7-c09c-57a4-39e7-ab25fde9abd4.png)

**Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):**

CSS プリプロセッサとして何を使用するかの選択です。
初期値の **Sass/SCSS (with dart-sass)** のまま次に進みます。
![01-005-pick-a-css-preprocessor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/c94b195a-6660-acb8-2ea9-bad3a2c9070d.png)

**Pick a linter / formatter config:**

コードの静的解析とフォーマッタとして何を使用するかの選択です。
ここでは初期値の **ESLint with error prevention only** のまま次に進みますが、ここは地味に組織やチームの方針が影響するところかと思います。
![01-006-pick-a-linter-formatter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/8a19b909-7437-294d-2e5b-5bedf0c730f8.png)

**Pick additional lint features:**

自動的なコードの静的解析・フォーマット処理をどのタイミングでやるかの選択です。
最初の選択は**保存時に実行**、2 つ目の選択肢は**コミット時に実行**です。
保存時の自動補正はして欲しいがコミット時にコードをいじられるのは嫌なので、（初期値の）1 つ目だけにチェックを入れた状態で次に進みます。
![01-007-pick-additional-lint-features.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/8af3a56c-1380-4d50-4f72-7cc31f775367.png)

**Pick a unit testing solution:**

単体テストツールとして何を使用するかの選択です。
**Jest** を選択して次に進みます。
![01-008-pick-a-unit-testing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/f01e0087-ca9d-3e26-164e-6e2b19e57310.png)

**Where do you prefer placing config for Babel, PostCSS, ESLint, etc.?**

`Babel` や `ESLint` などの設定を `package.json` に持たせるか、個別の設定ファイルとして持たせるかの選択です。
`package.json` に設定を記述していくとぐちゃぐちゃのスパゲティになるのは目に見えているので初期値の **In dedicated config files** を選択したまま次に進みます。
![01-009-placing-config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/df5ab4d1-5c31-43c4-581c-30b65073311f.png)

**Save this as a preset for future projects?**

今回作成した一連の設定をプリセットとして保存するかどうかの選択です。
今回は **N** として保存せずに進めますが、同じ設定でプロジェクトを開始する事が見込まれるなら分かりやすい名前をつけて保存しても良いでしょう。
![01-010-placing-config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/ca0ca620-5ba0-3301-7970-bea3e040e8eb.png)


選択はこれで終了です。
設定に応じて関連ライブラリ等がまとめてインストールされ、初期設定まで勝手にやってくれます。便利ですね！
![01-011-successfully-created.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/c20a2a0a-e84e-ec00-2c1a-3fbed13a71c3.png)

## プロジェクトを実行してみる

カレントディレクトリの下に、今作成したプロジェクト **kintone-vue-ts** のフォルダができています。
これを VS Code で開いてみます。
![02-001-project-files.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/e0caedf6-a92d-472c-713f-52ba68fd9555.png)

この状態で、既に動作確認ができます。
VS Code 上で新しいターミナルを開いて、以下のようにしてみましょう。

```bash
% yarn serve
```
![02-002-yarn-serve.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/67d986e4-57e7-b762-9f4b-5d8877ba0865.png)

ブラウザで http://localhost:8080/ を開くとビルドされた内容が確認できます。
![02-003-welcome-to-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/54ebef6a-0f4e-a7da-b316-349530c01e21.png)

また、この状態ではソースの変更にリアルタイムに追従してコンテンツがリフレッシュされます。
試しに `App.vue` の4行目の `HelloWorld` に渡している `msg` 属性の値を、

```html:App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="はじめての Vue.js + TypeScript App です！"/>
  </div>
</template>
```

と編集して保存してみると、
![02-004-welcome-to-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162138/54109ddb-b5f2-f783-ed6b-e1dd08049325.png)

ブラウザが自動的にリロードされて変更点が反映されます。すごいですね！

## プロジェクトを紐解く

いろいろファイルが作成されていますが、触っていくのは基本的に `src` フォルダの中のファイルが中心です。
（そのほかのファイルは必要に応じて触れていきます）

エントリポイントになるファイルが `main.ts` です。

```typescript:main.ts
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
```

同じフォルダの `App.vue` と言うファイルをインポートして、レンダリングしたものを `#app` と言う要素にマウントしますぜ、と言う記述です。

次にその `App.vue` を見てみます。

```Vue:App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import HelloWorld from './components/HelloWorld.vue';

@Component({
  components: {
    HelloWorld,
  },
})
export default class App extends Vue {}
</script>

<style lang="scss">
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

コードの細かい解説はしませんが、1 つの `.vue` ファイル内に見慣れた HTML ソースと TypeScript のスクリプトと CSS が混在して 1 つの **コンポーネント** を構成しているのが分かると思います。
また、ソース中程では `./components/HelloWorld.vue` と言うファイルをインポートしているのも確認できます。
インポートした `HelloWorld` コンポーネントは HTML の 4 行目で `msg` と言う属性を渡しつつ使用されています。

`Vue.js` ではこんな風に構成要素をコンポーネントとして分割して独立性を高めた形で実装していきます。

## Pug を導入する

HTML を簡単に書くためのプリプロセッサである `Pug` を導入します。

`Vue CLI` のプラグインとして導入するのが簡単です。

```bash
% vue add pug
```

最終的に以下のように出れば OK です。

```bash
📦  Installing vue-cli-plugin-pug...

yarn add v1.19.1
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
success Saved 31 new dependencies.
info Direct dependencies
└─ vue-cli-plugin-pug@1.0.7
info All dependencies
（中略）
✨  Done in 15.92s.
✔  Successfully installed plugin: vue-cli-plugin-pug
```

この後に

```bash
 ERROR  Error: Plugin vue-cli-plugin-pug does not have a generator.
 ```

と出ることもあるかもですが、とりあえずインストール自体はできているので大丈夫です。

それでは、`App.vue` の HTML 部分を `Pug` で書き直してみましょう。

変更前のコードはこうですが、

```html:App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
  </div>
</template>
```

`Pug` で書き換えるとこうなります。

```html:App.vue
<template lang="pug">
  #app
    img(alt="Vue logo" src="./assets/logo.png")
    HelloWorld(msg="Welcome to Your Vue.js + TypeScript App")
</template>
```

`template` タグに対して属性 `lang="pug"` と書くことで、 `Pug` による記述であることを明示します。

ざっくり `Pug` の記法を説明すると、

- タグは <> で囲わずにそのまま書く
- タグの階層構造はインデントで記述する
- `div` は省略できる
- `id="hoge"` は `#hoge` と記述する
- `class="fuga"` は `.fuga` と記述する
- クラスが複数ある場合（`class="fuga piyo"`）は `.fuga.piyo` と記述する
- 属性はカッコで囲って記述する
- 終了タグは不要

と言う感じです。
この程度の短いコードだと `Pug` の導入効果は今ひとつ実感しづらいですが、数 10 行とか 100 行レベルのコードになると特に終了タグが不要と言う特性が格段に効いて来ます。

# 次回は

とりあえず今回は下準備と言う事でここまで。kintone の話ほんと全然出て来ませんでしたすみません。
次回はいよいよこう言うモダンな開発環境をどう kintone にはめていくかをお話ししたいと思います。