package.jsonの^(caret)にハマった話
背景
- vue-cliを3系から4系にアップデートしたらビルドに失敗した
ERROR Failed to compile with 1 errors Module build failed (from ./node_modules/eslint-loader/index.js): Error: Cannot find module 'eslint/lib/formatters/stylish' at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15) at Function.Module._load (internal/modules/cjs/loader.js:562:25) at Module.require (internal/modules/cjs/loader.js:692:17) at require (internal/modules/cjs/helpers.js:25:18) at Object.module.exports (.../node_modules/eslint-loader/index.js:196:28)
- vue-cli 4かつESLint 6で
vue-cli-service lint
を実行するとエラー
結論
- dependenciesはpinしようよ
- vue-cliにPR投げた💪
chore(eslint): bump minimum required eslint-loader version to support ESLint 6 by megos · Pull Request #5273 · vuejs/vue-cli · GitHub - cli-plugin-eslintはeslint-loaderの^2.1.2に依存
- eslint-loaderがESLint 6をサポートしたのは2.2.0から
- eslint-loaderの2.2.0が公開される前にロックファイルを作っていた場合、eslint-loaderが更新されない
気づくまでの流れ
vue-cliを3系から4系にアップデートしたところ、stylishが見つからないというエラーが発生(上記エラーメッセージ)
調べると以下のようなissueを発見
ざっくりまとめると、ESLint 6には対応していないから5を使おうという感じでした
Cannot find module 'eslint/lib/formatters/stylish' when using ESLint ^6.0 · Issue #916 · vuejs/eslint-plugin-vue · GitHub
Error: Cannot find module 'eslint/lib/formatters/stylish' · Issue #271 · webpack-contrib/eslint-loader · GitHub
New vue-cli application fails to compile due to eslint-loader · Issue #4231 · vuejs/vue-cli · GitHub
個人的には新しいものを使いたいので調査を続けることに
エラーが出ているのはeslint-loader/index.js
なのでeslint-loaderを見ます
ローカルに入っているeslint-loaderは2.1.2です
eslint-loader@^2.1.2: version "2.1.2"
eslint-loaderのリリースノートを見ると、ESLint 6に対応している様子
Release v2.2.0 · webpack-contrib/eslint-loader · GitHub
それならばと自分でeslint-loaderを追加することに
$ yarn add -D eslint-loader
単純に追加してもcli-plugin-eslintで使うeslint-loaderと別々のバージョンが入ってしまうので、resolutionsで固定します
package.json
"resolutions": { "eslint-loader": "3.0.3" }
再度ビルドするとようやく通りました🎉
しかし、ここで1つ疑問が。それではvue-cli 4を使っているプロジェクトは今もESLint 5を使っているのか?と
新規にvue createして確認してみましょう
$ vue create hoge
vue-cli 4.2.2のデフォルトプリセットで出力されたpackage.jsonは以下の通りです
ESLintは6ですし、lintもbuildもできます
"scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" }, "dependencies": { "core-js": "^3.6.4", "vue": "^2.6.11" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.2.0", "@vue/cli-plugin-eslint": "~4.2.0", "@vue/cli-service": "~4.2.0", "babel-eslint": "^10.0.3", "eslint": "^6.7.2", "eslint-plugin-vue": "^6.1.2", "vue-template-compiler": "^2.6.11" },
ロックファイルを見てみましょう
eslint-loader@2.2.1, eslint-loader@^2.1.2: version "2.2.1"
ESLint 6に対応したバージョンが入っている!!
@vue/cli-plugin-eslintを見てみると、eslint-loader "^2.1.2"となっていますね
"@vue/cli-plugin-eslint@4.2.3": version "4.2.3" resolved ... integrity ... dependencies: "@vue/cli-shared-utils" "^4.2.3" eslint-loader "^2.1.2" globby "^9.2.0" inquirer "^6.3.1" webpack "^4.0.0" yorkie "^2.0.0"
^(caret)
指定だと、一番左の数字が同じ最新のバージョンがインストールされます
npm-semver | npm Documentation
eslint-loaderは、ESLint 6
- 2.1.2 未対応
- 2.2.0 対応
なので、ロックファイルが生成されたタイミングによっては、ESLint 6未対応の2.1.2を抱えたままになってしまいます…
というわけでPRを投げました
chore(eslint): bump minimum required eslint-loader version to support ESLint 6 by megos · Pull Request #5273 · vuejs/vue-cli · GitHub
こうして私の休日が半分消えたのでした