Migration to Vue 2.7 ESlint error in <script setup>

Lastor
Code 隨筆放置場
9 min readJun 10, 2023

想將一個老 Vue2 專案升級到 v2.7,雖已安裝 @vue/composition-api,但還是想享受一下 Vue3 <script setup> 語法糖的寫法。

原以為該專案 Vue2 應該比較舊,結果查一下發現居然是 v2.6 還頗新的。可能以前有人升級過一次,這樣直上 v2.7 應該問題不大。

果然,不出意外的話,就要出意外了。升上去之後居然碰到問題的是 ESLint。來稍微記錄一下採坑過程。

更新依賴套件

第一步先更新依賴,這專案不知道為啥居然同時存在 package-lock.jsonyarn-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 設定給妨礙了。

--

--

Lastor
Code 隨筆放置場

Web Frontend / 3D Modeling / Game and Animation. 設計本科生,前遊戲業 3D Artist,專擅日本動畫與遊戲相關領域。現在轉職為前端工程師,以專業遊戲美術的角度涉足 Web 前端開發。