そうだ、教祖になろう。出エジプト記 第4章4節 ESLint設定を整える
我々の街と塔を作ろう。塔の先が天に届くほどの。
これまで第4章1節 Cloud9にVue.js開発環境を導入するなどでトランスパイラに触れました。
Vue.jsのトランスパイラは「Babel」です。
BabelはJavaScriptトランスパイラで、本家サイトでは「次世代JavaScriptのコンパイラ」と説明されています。
"babble"と発音するらしいです。
見よ、その塔はシナルの地、アッシリアとバビロンの中間にあった。
第4章3節 Vue.jsでAjax通信するで出たWarningを解消するのに、このBabelが関係してきます。
Vue.jsプロジェクトをトランスパイルする前にESLintというリンタを使います。
リンタとは、プログラムソースがコーディング規約に則しているかチェックするツールです。
vue create プロジェクト名
でVue CLIを導入したときにESLint + Prettierを導入しました。
Prettierはコードフォーマッターです。
登場人物が多いですね。
Prettierはコーディング規約に沿うようにコードを整形してくれます。
ESLintもオプションでコードを整形できますが、Prettierの方が簡単により見やすくしてくれるといったところです。
とりあえずPrettierのことはおいといて、ESLintを使ってWarningが出ないようにコードを修正していきます。
参考にさせていただいたサイトです。
.vue
ファイルでESLintが利くようにeslint-config-vue
パッケージを導入します。
参考サイトにある他のパッケージはvue create
で入っているようです。
$ cd clientside/ $ yarn add -D eslint-config-vue $ ./node_modules/.bin/eslint src/**/*.js src/**/*.vue
デフォルト設定だとこんな感じの結果になります。
設定をカスタマイズするため、プロジェクト直下に'.eslintrc.js`というファイルを作ります。
Vueの推奨設定を読み込みます。
module.exports = { "extends": ["vue", "plugin:vue/recommended"], "env": { "browser": true }, "rules": {} }
これで走らせると80個ほどエラーと警告が出ます。
1つずつエラーを確認しながら修正したいので、今出たエラーと警告の右側に表示されているルール名を全部”rules”
に"off"
で追加します。
module.exports = { "extends": ["vue", "plugin:vue/recommended"], "env": { "browser": true }, "rules": { "indent": "off", "semi": "off", "space-in-parens": "off", "quotes": "off", "vue/html-closing-bracket-newline": "off", "vue/html-indent": "off", "vue/html-self-closing": "off", "vue/max-attributes-per-line": "off", "vue/name-property-casing": "off", "vue/require-default-prop": "off", } }
一回走らせます。
まだ1つ出てます。
これは”rules”
では消せないのでbabel-eslintで抑止します。
babel-eslintはESLintのためのBabel Parserのラッパーです。
Babel ParserはBabelの中にあるJavaScriptパーサーで、昔はBabylonと呼ばれていたそうです。
いよいよ混乱してきましたね。
"parserOptions"
を追加してもう一回走らせます。
module.exports = { … "parserOptions": { "parser": "babel-eslint", }, … }
babel-eslintはデフォルトで"allowImportExportEverywhere": false
になっており、Import
に対するエラーが消えます。
これで一旦エラーがない状態になりました。
その為に、この街はバベルと名付けられた。
では、ルールを1つずつ修正していきたいと思います。
デフォルト以外にしたい設定は"off"
の部分を修正したい設定値に変えていきます。
インデントは2にしてみます。
"indent": "indent": ["error", 2],
リントします。
$ ./node_modules/.bin/eslint src/**/*.js src/**/*.vue
17か所エラーになってますね。
--fix
オプションをつけて修正します。
$ ./node_modules/.bin/eslint --fix src/**/*.js src/**/*.vue
これが、
... const routes = [{ path: "/", name: "home", component: Home }, ...
こうなりました。
... const routes = [{ path: "/", name: "home", component: Home }, ...
続いて、セミコロンをなしにします。
"semi": ["error", "never"],
import Vue from "vue"; import VueRouter from "vue-router"; import Home from "../views/Home.vue";
↓
import Vue from "vue" import VueRouter from "vue-router" import Home from "../views/Home.vue"
どんどんいきます。
好き嫌いが分かれるでしょうが、複数行の場合の末尾のカンマを必須にします。
"comma-dangle": ["error", "always-multiline"],
export default new Vuex.Store({ state: {}, mutations: {}, actions: {}, modules: {} })
↓
export default new Vuex.Store({ state: {}, mutations: {}, actions: {}, modules: {}, })
()
の内側のスペースなしはデフォルトなのでこの行は消します。
"space-in-parens": "off",
component: () => import ( /* webpackChunkName: "about" */ "../views/About.vue"),
↓
component: () => import (/* webpackChunkName: "about" */ "../views/About.vue"),
クォーテーションはダブルクォーテーション。
"quotes": ["error", "double"],
これはエラーなし。シングルクォーテーションはなかったようです。
ここから.vue
ファイルのHTML部分の規則です。
HTMLの>
位置はデフォルトなので削除。
"vue/html-closing-bracket-newline": "off",
<a href="https://cli.vuejs.org" target="_blank" rel="noopener" >vue-cli documentation</a >.
↓
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
HTML属性位置はデフォルトなので削除。
"vue/max-attributes-per-line": "off",
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
↓
<a href="https://cli.vuejs.org" target="_blank" rel="noopener" >vue-cli documentation</a>.
HTMLのインデントもデフォルトで削除。
"vue/html-indent": "off",
<li> <a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener" >babel</a> </li>
↓ 微妙!(>
が2つ上がってる)
<li> <a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener" >babel</a> </li>
HTMLタグの閉じタグ許可。
"vue/html-self-closing": ["error", { "html": { "normal": "always", "void": "always", "component": "always" }, }],
これもエラーなし。
プロパティ名はデフォルト(キャメルケース)なので削除。
"vue/name-property-casing": "off",
name: "ajax",
↓
name: "Ajax",
プロパティのrequired属性必須はデフォルトなので削除。
"vue/require-default-prop": "off",
props: { msg: String }
あれ、これは--fix
で修正されないようです。
手で修正。
msg: { type: String, required: true }
最終的に.eslintrc.js
はこうです。
module.exports = { "extends": ["vue", "plugin:vue/recommended"], "env": { "browser": true }, "parserOptions": { "parser": "babel-eslint", }, "rules": { "comma-dangle": ["error", "always"], "indent": ["error", 2], "semi": ["error", "never"], "quotes": ["error", "double"], "vue/html-self-closing": ["error", { "html": { "normal": "always", "void": "always", "component": "always" }, }], } }
主がそこで、全地の言葉を乱し、そこから人を全地に散らされたからである。
手間はかかりましたが一応設定が整いましたね。
では改めてsrc/router/index.js
をいじって保存すると、
おっと、設定と異なるインデントで自動フォーマットされてエラーが大量発生しますね。
あれ、これ涙?
Cloud9のJSBeutify設定とESLintの設定が合っていないからっぽいです。
ので、保存時にESLintを使ってフォーマットしてくれるように変更します。
PreferenceのProject Setting > JavaScript Support > Custom Code Formatterの欄に以下のコマンドを設定します。
保存したファイルのディレクトリに下りてって、eslint --fix
を実行するコマンドです。
npmのパッケージ実行コマンドであるnpxで起動しています。
うまく動いてないときのトレースのためにホームディレクトリにログファイルを吐いてます。
cd `dirname "$file"`;npx eslint --fix `basename "$file"` &> ~/eslint.log
これでsrc/router/index.js
を保存しなおすと、エラーがなくなりました。
npxを起動するのが遅いのか、若干タイムラグがあるのが気になります。
Cloud9にJavaScriptと認識されてるファイルでしかフォーマッタのトリガがかからないので、.vue
ファイルのエディタの右下にあるファイル種別を「JavaScript」に変更します。
これで保存時に.vue
ファイルもフォーマットされますが、JavaScriptファイルには存在しない<script>
のあたりでParsing error
が発生します。
ので、Hints&Warning > Ignore Messages Matchingの欄にParsing error
と入力して無視します。
これやっちゃうと例えば<script>
が抜けたりしてもコーディング時点では分からないのですが、ビルド時点で気づけるのでまあよしとしましょう。
ついでに、Mark missing semicolonsを外してエディタの横に出ている「i」マークが表示されないようにします。
見よ、人の子らはシナルの地に自分たちの都市と塔を建てようというそのふとどきなはかりごとのゆえに邪悪になった。
なんとかESLintの設定を整えてきたのですが、はっきり言って結構手間です。
Prettierだともちょっと楽に設定できるようで、今後のためにPrettier設定をESLintに読ませる形に全面見直したいと思います。
つまり、今の設定はほぼ全部壊します。
大変参考になりました。
修正した.eslintrc.js
がこれ。
ESLint、Prettier、Vueの推奨を利用。
module.exports = { parser: 'vue-eslint-parser', parserOptions: { parser: 'babel-eslint', sourceType: 'module', }, env: { browser: true, node: true, }, extends: [ 'eslint:recommended', 'plugin:prettier/recommended', 'plugin:vue/recommended', 'prettier/vue', ], rules: {}, }
新規作成したPrettierの設定である.prettierrc.js
がこれ。
シングルクォーテーションにしました。
module.exports = { printWidth: 80, tabWidth: 2, singleQuote: true, semi: false, trailingComma: 'es5', bracketSpacing: false, }
上記の2ファイルも整形できるよう、PreferenceのCustom Code Formatterに--ignore-pattern
オプションを追加しました。
デフォルトだと対象外のファイルもリントしてくれます。
cd `dirname "$file"`;npx eslint --fix `basename "$file"` --ignore-pattern '!.*.js' &> ~/eslint.log
苦労しましたが、これでやっとESLint設定が整いました。
次回はHTMLをスッキリ書けるPugを入れたかったので、またフォーマッタ設定を変えないといけないんかいとビクビクでしたが、色々サポートが利かなくなるし、特段コーディング量も減らないし、あまりメリットがなさそうなのでやめておこうと思います。
2019/12/27追記
Pugをちょっと入れてみましたが、eslint --fix
が利かないようで断念しました。残念。
yarn add -D pug pug-plain-loader eslint-plugin-pug
plugins: ['pug'],
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png" /> <HelloWorld msg="Welcome to Your Vue.js App" /> </div> </template>
↓
<template lang="pug"> div.home img(alt="Vue logo" src="../assets/logo.png" HelloWorld(msg="Welcome to Your Vue.js App") </template>