Migration to Vue 2.7 ESlint error in <script setup>
想將一個老 Vue2 專案升級到 v2.7,雖已安裝 @vue/composition-api
,但還是想享受一下 Vue3 <script setup> 語法糖的寫法。
原以為該專案 Vue2 應該比較舊,結果查一下發現居然是 v2.6 還頗新的。可能以前有人升級過一次,這樣直上 v2.7 應該問題不大。
果然,不出意外的話,就要出意外了。升上去之後居然碰到問題的是 ESLint。來稍微記錄一下採坑過程。
更新依賴套件
第一步先更新依賴,這專案不知道為啥居然同時存在 package-lock.json
與 yarn-lock
。
它是前後端共構的,主框架為 Ruby on Rails,追了一下看到 Rails 那邊會檢查有無 yarn-lock
存在,並且 README
也寫明要用 yarn 安裝套件。估計這個 package-lock.json
是其他人沒搞清楚環境,不小心 git 弄上去的。先無視,以 yarn 為主。確定沒問題後應該是可以移除的。
個人對 yarn 不熟,相關指令就直接問 chatGPT 搭配 google 搜尋驗證,畢竟有時候問法不對 chatGPT 會瞎掰亂回,容易被坑。
首先參照官方 Vue 2.7 遷移指南。
更新 vue 到 2.7。由於不是用 vue-cli
起的專案,所以不用管 cli 那塊。
# Windows
$ yarn upgrade vue@^2.7 --latest
# Mac
$ yarn upgrade "vue@^2.7" --latest
yarn upgrade
是參照 package.json
的設定去更新,未必會一併更新 package.json
的紀錄,加上 --latest
可以強制更新紀錄文件。
另外要注意 Mac 終端機似乎有用 ^
來作為命令使用,需加上字串的引號才能正確執行。
vue 2.7 多了一些需要編譯的語法糖,所以非常理所當然的需要更新 webpack 的 loader。(此專案是 webpack@4.41)
$ yarn upgrade vue-loader@^15.10.0 --latest
如果原本已有安裝 @vue/composition-api
,可將其移除,然後把原本有引用的地方改為直接拉 vue
。接著去 js 進入點,把相關程式碼移除。
// Delete these
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI)
這樣其實就算升級完成,可以加入一個使用 setup 語法糖的檔案,嘗試 run dev
以及 build
。
// Foo.vue
<script setup>
import { ref } from 'vue'
const name = ref('Tom')
</script>
<template>
<div>
<div>Hello {{ name }}</div>
<input v-model="name" type="text" />
</div>
</template>
處理 ESLint Error
完成上述更新之後,就可以 work 了。但在 VScode 裡面查看,lint 會報錯。
錯誤內容由上往下依序是:
(第一個紅線有兩個錯誤)
Component name “Foo” should always be multi-word.
eslint(vue/multi-word-component-names)Definition for rule ‘vue/name-property-casing’ was not found.
eslint(vue/name-property-casing)‘name’ is assigned a value but never used.
eslint(no-unused-vars)
解決 ESLint no-unused-vars 誤判
先解決最坑的第三項 name 變數的錯誤 no-unused-vars
,這是 eslint 檢查未使用變數的規則,它無法正確理解 setup 的變數有被 template 使用。
依照 Vue 官方遷移文件,更新 eslint-plugin-vue
到 v9 以上版本。
$ yarn upgrade eslint-plugin-vue@^9 --latest
然後會發現錯誤依然存在,沒有任何用處……
去 google 搜尋 eslint-plugin-vue
,可以看到 Vue 有相關的官方文件。
裡面有寫說需要 ESLint 6.2.0 以上版本。
Requirements
ESLint v6.2.0 and above
可是我怕 6.2 可能也太舊,但直接升到最新估計也會有很多鳥問題,所以用 vue-cli
建立一個新的 vue 2.7 專案,看看它裡面是用幾版的 ESlint,順便對照其他設定。
當前 vue-cli@5.0.8
使用的是 eslint@7.32.0
,就無腦用跟他一樣的。
$ yarn upgrade eslint@^7.32.0 --latest
但 lint 報錯依然存在,問 chatGPT 它只會要我把 no-unused-vars
這規則關掉,一點用都沒有。google 查了半天,發現有一個 eslint-plugin-vue
相關設定 vue/script-setup-uses-vars
。
上面雖然寫說已經棄用,現在改用 vue-eslint-parser
,但這要另外裝一個套件,不知道會不會有其他問題。而且 eslint 跟 vue 插件我並不是用最新版的,所以反而應該要用這個 vue/script-setup-uses-vars
舊設定才對。
在 eslint 設定檔追加該規則。
// .eslintrc.js
module.exports = {
// ...
extends: [
'eslint:recommended',
'plugin:vue/recommended',
'prettier',
],
rules: {
'vue/script-setup-uses-vars': 2, // add this
'no-unused-vars': 2,
// ...
}
}
注意,如果原本有聲明 no-unused-vars
的話,vue 的這條規則要加在它上面才行。
接著重起 VScode 的 ESlint Server,可以看到該報錯消失了。如果將 template 的引用給註解掉,也能正確判斷 name 變數是 unused vars。
解決 ESLint vue/multi-word-component-names
這個其實不像 no-unused-vars
那條是個坑,單純是新版的 Vue eslint 插件為了讓組件與原生 HTML Element 有更好的區分 (原生都會是一個單字),所以除了 App
之外,希望你組件名都要是兩個單字以上。
這個見仁見智,鑒於老專案已經有不少這樣的命名,而且英文命名真的很難想…… 我個人傾向關掉。
// .eslintrc.js
rules: {
'vue/multi-word-component-names': 'off',
}
解決 ESLint vue/name-property-casing
這錯誤單純是說沒有定義這規則,它需要被定義。
Definition for rule ‘vue/name-property-casing’ was not found.
但是去查文件會發現在 eslint-plugin-vue 9+ 版本已經棄用,那為啥這還會跑出這錯誤?
翻一下發現是舊專案有寫這條規則,大概是衝突到了,根據文件將其改用新規則 vue/component-definition-name-casing
。
// .eslintrc.js
rules: {
// remove this line
'vue/name-property-casing': ['error', 'PascalCase'],
// change to this line
'vue/component-definition-name-casing': ['error', 'PascalCase'],
}
將這些改正之後,就能正常使用 <script setup> 語法糖,並且不會被舊版本的 ESLint 設定給妨礙了。