Closed11

Vue + Vite + TypeScript + ESLintのセットアップメモ

basyoubasyou

まずはVite公式ドキュメントを読みつつ、アプリケーションの雛形を作成
公式ページ

$ yarn create vite

フレームワークやバリアントを聞かれるので、今回はVueとvue-tsを選択

初期のpackage.json

{
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "serve": "vite preview"
  },
  "dependencies": {
    "vue": "^3.0.5"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.2.5",
    "@vue/compiler-sfc": "^3.0.5",
    "typescript": "^4.3.2",
    "vite": "^2.4.2",
    "vue-tsc": "^0.0.24"
  }
}⏎

初期のtsconfig.json

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

初期のvite.config.ts

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()]
})

ここからいい感じにゴニョゴニョしていく

basyoubasyou

まずはESLintから導入していく
導入方法は公式ページを参考する

yarn add eslint --dev
package.json
.....
.....
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.2.5",
    "@vue/compiler-sfc": "^3.0.5",
    "eslint": "^7.31.0",
    .....
    .....
  }
}

続いて便利なセットアップコマンドがあるようなのでそれを使用する

yarn run eslint --init 

いろいろ聞かれるので回答は以下の通り

✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · vue
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser, node
✔ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:
eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
✔ Would you like to install them now with npm? · No / Yes

typescriptのパーサーなどはnpm経由でインストールされるためpackage-lock.jsonが作成されてしまう。
今回はyarnで管理したいのでファイルを削除しyarn installする

.eslintrc.jsは現在以下の通り

.eslintrc.js
module.exports = {
  env: {
    'browser': true,
    'es2021': true,
    'node': true
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/essential',
    'plugin:@typescript-eslint/recommended'
  ],
  parserOptions: {
    'ecmaVersion': 12,
    'parser': '@typescript-eslint/parser',
    'sourceType': 'module'
  },
  plugins: [
    'vue',
    '@typescript-eslint'
  ],
  rules: {
  }
};

basyoubasyou

追加でESLint用のパッケージを追加していく

先程のyarn run eslint --init コマンドで

eslint-plugin-vue
@typescript-eslint/eslint-plugin
@typescript-eslint/parser@latest

がインストールされている。
パッケージを追加していく前にひとまずこれらのパッケージが何者なのかまとめてみる(間違っていたらすいません...)

eslint-plugin-vue

公式ドキュメント
Vue.js用の公式ESLintプラグイン
.vueファイルのコードをチェックしてくれる

eslintrc.jsのextendsを修正する

eslintrc.js
'extends': [
  'plugin:vue/vue3-recommended',
  'plugin:vue/vue3-strongly-recommended',
  'plugin:@typescript-eslint/recommended'
],

追加ルールは下記ページを参考
eslint-plugin-vue Available rules

@typescript-eslint/eslint-plugin

@typescript-eslint/eslint-plugin
ESLintでTypeScriptのコードもチェックしてくれるようにするプラグイン

@typescript-eslint/parser

"@typescript-eslint/parser"
@typescript-eslint/eslint-pluginを使用したい時に一緒にインストールするパッケージ

parserOptionに記述を追加する

eslintrc.js
'parserOptions': {
  'ecmaVersion': 12,
  'parser': '@typescript-eslint/parser',
  'sourceType': 'module'
  // ここから追加
  'project': './tsconfig.json',
  'extraFileExtensions': [
    '.vue',
  ],
},

parserOptions.projectについては下記参照
parserOptions.project

parserOption.extraFileExtensionsについてはこちら
parserOption.extraFileExtensions

basyoubasyou

いろいろ追加していく

vue-eslint-parser

vue-eslint-parser
.vueファイルの<template>タグ内をlintしてくれる

$ yarn add -D eslint vue-eslint-parser

.eslintrc.jsに記述を追加する

eslintrc.js
{
.....
.....
  'parser': 'vue-eslint-parser',
.....
.....
}
basyoubasyou

eslint-config-airbnb-base

eslint-config-airbnb-base
airbnbのルールを使用したいのでインストール

$ yarn add -D eslint-config-airbnb-base

また、eslint-config-airbnb-baseにはeslint-plugin-importが必要なのでこちらもインストール

$ yarn add -D eslint-plugin-import

.eslintrc.jsに記述を追加する

.eslintrc.js
'extends': [
  'plugin:vue/vue3-recommended',
  'plugin:vue/vue3-strongly-recommended',
  'plugin:@typescript-eslint/recommended',
  // ↓こいつを追加
  'airbnb-base'
    ],
basyoubasyou

eslint-plugin-vue-scoped-css

eslint-plugin-vue-scoped-css
Vue.jsでScoped CSSを使う際にいい感じにLintしてくれる

$ yarn add -D eslint-plugin-vue-scoped-css

.eslintrc.jsに記述を書き換える

.eslintrc.js
'extends': [
  // 'plugin:vue/vue3-recommended', <= 消す
  // ↓に置き換え
  'plugin:vue-scoped-css/vue3-recommended',
  'plugin:vue/vue3-strongly-recommended',
  'plugin:@typescript-eslint/recommended',
  'airbnb-base'
    ],

公式のセットアップを読んでみた感じ、vue/vue3-recommendedをベースに拡張しているっぽいので置き換えて良さそうだと判断

basyoubasyou

sass

sass
現状Vueコンポーネントのstyleタグにlang="scss"と書きyarn devすると、「sassなんてないぞ」と怒られるのでインストールする

$ yarn add -D sass 
basyoubasyou

tslib

tslib
tsconfig.jsonのコンパイラオプションに"importHelpers": true,を指定するためにインストール

TypeScriptがJavaScriptにコードをコンパイルする際、TypeScriptのランタイムはヘルパー関数を生成する

ファイルごとにヘルパー関数を生成する(=ヘルパー関数の重複)のでパッケージのサイズが大きくなる

嫌な気持ちになるので、importHelpersやnoEmitHelpersを使ってヘルパー関数の生成を抑える

ヘルパー関数がないとJavaScriptにコンパイルできないやんけとなる

tslibを使用してパッケージ内のヘルパー関数を使用して解決

ということらしい

超参考にした記事
外部ヘルパーライブラリ(tslib)のサポート
オプションを知り己のコードを知れば百戦危うからず
typescriptのtscのimportHelpersオプションの詳細や用途を教えてください!

というわけで早速インストール

$  yarn add -D tslib 

tsconfig.jsonのcompilerOptionsに"importHelpers": trueを追加

"compilerOptions": {
    .....
    .....
    "importHelpers": true,
    .....
basyoubasyou

eslint-import-resolver-alias & eslint-import-resolver-typescript

プロジェクト内でimport文にエイリアスを使いたいのでインストールする

インストールする前にtsconfig.jsonとvite.config.tsを書き換える

tsconfig.json
"compilerOptions": {
    .....
    .....
    "baseUrl": "./",
    "paths": {
      "*": ["*"],
      "/@/*": ["src/*"]
    },
    ......
    ......
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 追加
import * as path from "path"

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
// 追加
  resolve: {
    alias: {
      '/@': path.resolve(__dirname, 'src'),
      '/assets': path.resolve(__dirname, 'src/assets'),
    }
  }
})

import * as path from "path"の部分で怒られるので、

$  yarn add -D @types/node    

を実行して@types/nodeをインストールし、Node.jsの型定義ファイルを用意しておく

こうすることで例えば、src/components/atoms/Hoge.vueコンポーネントを作成し、他のコンポーネントで使用する際に以下のように書けるようになる

Fuga.vue
import AppHoge from '/@/components/atoms/Hoge.vue';

ただしESLIntが「絶対パスを使うんじゃねーぞ」「なんだそのパスは」と怒ってくる
なので.eslintrc.jsにルールを追加して大人しくしてもらう
そこで活躍するのがeslint-import-resolver-alias と eslint-import-resolver-typescript

力尽きたので今回はここまで

basyoubasyou

余談:
久しぶりに当スクラップを更新するためサンプルアプリケーションを開くと以下のように怒られた(再起動あるある)

Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: .eslintrc.js.
The file must be included in at least one of the projects provided.

ファイルがどこにもimportされてないぞと怒っているみたいです。
.eslintrc.jsはどこにもimportしないのでeslintIgnoreでLintの除外対象にします。

参考記事

今回は.eslintignoreファイルを新しく用意せず、package.jsonファイルに書いていきます。

package.json
"eslintIgnore": [
  ".eslintrc.js",
  "vite.config.ts"
]

※ついでにvite.config.tsも追加

basyoubasyou

気を取り直してeslint-import-resolver-alias と eslint-import-resolver-typescriptをインストールする

$ yarn add -D eslint-import-resolver-alias
$ yarn add -D eslint-import-resolver-typescript

インストールしたら.eslintrc.jsをいじる

.eslintrc.js
rules: {
  'import/no-absolute-path': 'off',
  'import/extensions': [
    'error',
    'ignorePackages',
    {
      js: 'never',
      jsx: 'never',
      ts: 'never',
      tsx: 'never',
    }
  ]
},
settings: {
  'import/resolver': {
    node: {
      extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
    },
    typescript: {},
      alias: {
      map: [
        ['/@', './src'],
      ],
      extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
    }
  }
}

絶対パスを許したり、エイリアスを有効にしたりしている

rules: {
  'import/no-absolute-path': 'off',
  'import/extensions': [
    'error',
    'ignorePackages',
    {
      js: 'never',
      jsx: 'never',
      ts: 'never',
      tsx: 'never',
    }
  ]
},

'import/extention'以下の設定はこちらを参考
github
stack overflow

settings: {
  'import/resolver': {
    node: {
      extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
    },
    typescript: {},
      alias: {
      map: [
        ['/@', './src'],
      ],
      extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
    }
  }
}

'import/resolver'以下についてはこちらを参考
eslint-import-resolver-alias
eslint-plugin-import#setting

hoge.tsをimportするときはこのような書き方になる

import { hoge } from '/@/hogehoge/hoge';

import周りの設定は完了していると思うので、あとは好きなルールを組み込んでいけばいいと思います!!

このスクラップは2021/09/14にクローズされました