🌊

頑張らない Vue3 開発環境構築

2021/12/26に公開

あんまり頑張らずに開発できる環境を目標にする。実現したいのはこれくらい。
最終的な構築結果は https://github.com/toruuetani/vue3starter にある。

  • Vue3 + VSCode + TypeScript + Vuex + VueRouter で開発する。
  • Vue3.2 から使える <script setup> 構文を使えるようにする。
  • ビルドツールには Vue/CLI ではなく Vite を使う。
  • 現代のプログラミングにおいて Linter や formetter は当然なので、 ESLint + Prettier を導入する。

前提とするバージョンは以下の通り。

  • Windows 10 20H2
  • nvm-windows 1.1.8
  • Node.js 14.18.2 ※ v14 は特に意味はない。 v16 でも問題ないはず。
  • npm 6.14.15 ※ yarn を使うメリットが特に見出せないため npm を使う。
  • Vue.js 3.2.26
  • Vuex 4.0.2
  • Vue Router 4.0.12
  • Vite 2.7.6
  • TypeScript 4.5.4
  • ESLint 8.5.0
  • Prettier 2.5.1

あくまで開発テンプレート的に使うことを想定していて、 UI フレームワークなどは導入しない。

なぜ頑張らないのか

フロントエンドの経験がないのに Vue のベストプラクティスを探すのに疲れたから。
そもそも既存資産が Vue2 (Options API) + Vuetify で構築されていたと理由だけで、
新システムも同じ構成で開発しようとしたのが間違いだった。
開発を始めたのは2021年7月で、 Options API は古く、これからは Composition API だ、
という情報も出回っていた。そのため Vue3 で開発しようとも検討したが、 Vuetify が Vue3 に対応していないという理由で、 Vue2 + Composition API plugin for Vue 2 という構成で開発することにした。これが2番目の間違い。

そこまで複雑なフロントエンド開発ではないため、特に問題なく開発は進んでいた。
が、 Vuex を使おうとして問題が発生した。 Composition API に対応する Vuex4 は Vue3 が必要。
Vue3 に対応した Vuetify はまだ α 状態。詰んだ。

初心者がここまで考慮して構成を検討するのはムリゲー過ぎる。
かつ TypeScript や ESLint, Prettier で lint, format できるようにしなければいけない。
ビルドツールはバンドラーはどうするのか?とにかく解決すべき課題が多すぎて手に負えない。
だからあまり頑張らないことにした。

VSCode

まず開発には VSCode を使うため、必要な拡張をインストールする。

extensions.json

.vscode\extensions.json を以下のように作っておく。
そうすれば、開発ディレクトリを VSCode でオープンするとインストールするか聞かれるため、
開発チームで環境をそろえることが容易になる。

{
  "recommendations": [
    "dbaeumer.vscode-eslint",
    "editorconfig.editorconfig",
    "esbenp.prettier-vscode",
    "johnsoncodehk.volar",
  ],
}

settings.json

ESLint, Prettier を動かすための .vscode\settings.json は以下の通り。

{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "editor.defaultFormatter": null,
  "editor.formatOnPaste": true,
  "editor.formatOnSave": true,
  "editor.insertSpaces": true,
  "editor.renderWhitespace": "all",
  "editor.rulers": [119],
  "eslint.validate": ["javascript", "vue"],
  "files.exclude": {
    "**/node_modules": true
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

ちなみに Prettier は幅広くフォーマットしてしまうため、場合によっては邪魔になることがある。
言語ごとにフォーマッタを指定すれば十分なため、 "editor.defaultFormatter": null としておく。

Node.js ライブラリの導入

拡張をいれただけでは ESLint も Prettier も動いてくれないので、 Node.js ライブラリを順次導入していく。

Node.js インストール

まず Node.js および npm が使えるようにパッケージマネージャ Scoop を使う。( Scoop の導入は割愛)

  • scoop install nvm
  • nvm install 14.18.2 && nvm use 14.18.2

プロジェクトテンプレート

プロジェクトの開始にはビルドツール Vite を使う。
npm init vite@latest コマンドでテンプレートを生成してくれる。
コミュニティテンプレートを使ってもいいのだが、欲しい構成とピタリと一致しない限りは不要だろう。
質問には vuevue-ts で回答する。

npm init vite@latest vue3starter
√ Select a framework: » vue
√ Select a variant: » vue-ts
cd vue3starter
npm install

この時点でプロジェクトテンプレートが出来上がり、 npm run dev で開発サーバーが起動するようになる。
テンプレートが作成したアプリは http://localhost:3000 で確認できる。

ちなみにライブラリをインストールするだけなら以下のコマンドと同じ。

npm i    --save-exact vue
npm i -D --save-exact vite
                      typescript
		      vue-tsc
                      @vitejs/plugin-vue

npm のオプションについて

ちなみに npm も古い書き方が混在してる。

  • install は単純に i だけでもいい。本記事はショートバージョンを使う。
  • --save は古い書き方のため不要。本記事では使用しない。
  • --save-dev は長いので -D で代用できる。本記事はショートバージョンを使う。
  • --save-exact は正確なバージョンを記録するためにつける。

ESLint & Prettier インストール

ESLint と Prettier を使うために必要なライブラリは以下のようにしてインストールする。

npm i -D --save-exact eslint
                      eslint-plugin-vue
                      @typescript-eslint/eslint-plugin
                      @typescript-eslint/parser
                      @vue/eslint-config-typescript
                      prettier
                      eslint-config-prettier

eslint-plugin-vue@vue/eslint-config-typescript は Vue の SFC に対して Lint するため必要。

Vuex & Vue Router

Vue3 に対応した Vuex と Vue Router は以下のようにしてインストールする。

npm i    --save-exact vuex@next
npm i    --save-exact vue-router@4

ESLint & Prettier 設定

ESLint と Prettier はバッティングしてしまうため、設定に注意が必要。

ESLint 設定

ESLint の設定 .eslintrc.js は以下の通り。
肝心なのは extends で、上から順に適用されるらしい。
eslint-config-prettier を最後に記述すると Prettier とバッティングしなくなるとか。
これ以上追及するのは面倒なので追及しない。

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
    "vue/setup-compiler-macros": true,
  },
  extends: [
    "plugin:vue/vue3-essential",
    "eslint:recommended",
    "@vue/typescript/recommended",
    "eslint-config-prettier",
  ],
  parserOptions: {
    ecmaVersion: 13,
    parser: "@typescript-eslint/parser",
    sourceType: "module",
  },
  plugins: ["vue", "@typescript-eslint"],
  rules: {},
}

※1 eslint-config-prettier/vueeslint-config-prettier/@typescript-eslinteslint-config-prettier にマージされたのでもう不要らしい。
※2 .eslintrc.js 自体に 'module' is not defined. というエラーが出ることがある。これは envnode: true を追加すると解決する。
※3 'defineProps' is not defined. と言われるため、 "vue/setup-compiler-macros": true を追加する。

Prettier 設定

Prettier の設定 .prettierrc.js は以下の通り。

module.exports = {
  printWidth: 120,
  semi: false,
  singleQuote: false,
  tabWidth: 2,
  trailingComma: "es5",
  vueIndentScriptAndStyle: true,
}

さらに Prettier は .editorconfig の設定も見てくれるため用意しておく。

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml,json,scss,html,js,ts,vue}]
indent_size = 2

ここまでで目標通りの開発環境が手に入るはず。
あとは好きな UI フレームワークを入れるなりしていけば問題ないだろう。

その他 tips

開発しているときにこまったものをいくつか。

環境変数

Vue/CLI のときは dotenv を使っていたが、 Vite では不要となったようだ。 → https://ja.vitejs.dev/guide/env-and-mode.html
.env ファイルに定義する変数は VUE_APP_ で始まる値だったが、 Vite の場合は VITE_ で始まる値だけ使える。
また、 Vue/CLI では process.env で取得できていたが、 Vite では import.meta.env で取得できる。

エイリアス

Vue/CLI では以下のように src 以下を @ で置き換えることができていた。

import HelloWorld from "@/components/HelloWorld.vue"

これを Vite でも実現するには vite.config.ts を以下のようにする。

import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"
import path from "path"

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: [
      {
        find: "@/",
        replacement: `${path.resolve(__dirname, "src")}/`,
      },
    ],
  },
})

ただしこれだけだと path__dirname で ESLint がエラーを出す。これを回避するには tsconfig.json を以下のようにする。

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "types": ["node"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

さらに以下のライブラリをインストールすれば解決できる。

npm i -D --save-exact @types/node

Discussion