tmegos blog

Web developer

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を実行するとエラー

結論

気づくまでの流れ

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

こうして私の休日が半分消えたのでした