# [ESLint] Vite + Vue 3 + TypeScript + Airbnb ###### tags: `ESLint` `Vite` `Vue.js` `TypeScript` ## 基本配置 :::info 編輯器使用 Visual Studio Code,且已安裝 [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) extension ::: 使用 `npm create vue@latest` 創建專案,選擇的功能如下 ``` Add TypeScript? … Yes Add JSX Support? … No Add Vue Router for Single Page Application development? … Yes Add Pinia for state management? … Yes Add Vitest for Unit Testing? … No Add an End-to-End Testing Solution? › No Add ESLint for code quality? … Yes Add Prettier for code formatting? … No ``` ### 初始化的 .eslintrc.cjs 內容 :::spoiler 點我看詳細資料 ```javascript /* eslint-env node */ require('@rushstack/eslint-patch/modern-module-resolution') module.exports = { root: true, 'extends': [ 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-typescript' ], parserOptions: { ecmaVersion: 'latest' } } ``` ::: ### 初始化的 vite.config.ts 內容 :::spoiler 點我看詳細資料 ```typescript import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } } }) ``` ::: ## Style Guide 選 Airbnb :::info * [GitHub:eslint-config-airbnb-base](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base "javascript/packages/eslint-config-airbnb-base at master · airbnb/javascript · GitHub") ::: 1. 安裝 `npx install-peerdeps --dev eslint-config-airbnb-base` * `package.json` 的 `devDependencies` 會新增 `eslint-config-airbnb-base`、`eslint-plugin-import` 3. 修改 `.eslintrc.cjs` * `extend` 內的 `'plugin:vue/vue3-essential'` 改成 `'plugin:vue/vue3-recommended'` * `extend` 最後新增 `'airbnb-base'` * 修改內容以符合規範 ```javascript /* eslint-env node */ require('@rushstack/eslint-patch/modern-module-resolution'); module.exports = { root: true, extends: [ 'plugin:vue/vue3-recommended', 'eslint:recommended', '@vue/eslint-config-typescript', 'airbnb-base', ], parserOptions: { ecmaVersion: 'latest', }, }; ``` 這時不符規範的程式碼會出現紅色提示,但執行 `npm run dev` 時可正常瀏覽網頁,終端機也不會顯示提示訊息 ## 開發時在網頁及終端機顯示提示訊息 :::info * [GitHub:vite-plugin-eslint](https://github.com/gxmari007/vite-plugin-eslint "GitHub - gxmari007/vite-plugin-eslint: 🚨 ESLint plugin for vite") ::: 1. 安裝 `npm i vite-plugin-eslint -D` * `package.json` 的 `devDependencies` 會新增 `vite-plugin-eslint` 3. 修改 `vite.config.ts` * 加上 `import eslint from 'vite-plugin-eslint'` * `plugins` 新增 `eslint()` * 修改內容以符合規範 ```typescript import { fileURLToPath, URL } from 'node:url'; import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import eslint from 'vite-plugin-eslint'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), eslint(), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, }); ``` 執行 `npm run dev` 時就會在網頁及終端機上看到提示訊息 ## 問題 ### import/no-unresolved 找不到檔案 :::info * [Using eslint with typescript - Unable to resolve path to module](https://stackoverflow.com/questions/55198502/using-eslint-with-typescript-unable-to-resolve-path-to-module "Using eslint with typescript - Unable to resolve path to module - Stack Overflow"):有提到其他解法,例:安裝 `eslint-import-resolver-typescript`、改 `import` 寫法等 * [zhbhun 的笔记:eslint-plugin-import Unable to resolve path to module](https://segmentfault.com/a/1190000042003904#item-2 "javascript - eslint-plugin-import Unable to resolve path to module - zhbhun 的笔记 - SegmentFault 思否") * [GitHub:Airbnb ESLint configurations](https://github.com/airbnb/javascript/blob/11ab37144b7f846f04f64a29b5beb6e00d74e84b/packages/eslint-config-airbnb-base/rules/imports.js#L16C22-L16C44 "javascript/packages/eslint-config-airbnb-base/rules/imports.js at master · airbnb/javascript · GitHub") ::: ```typescript // main.ts import router from './router'; // Unable to resolve path to module './router' import/no-unresolved ``` #### 原因 `eslint-plugin-import` 解析 module 時在沒有後綴名時會先找 `.js` 檔案,若找不到會找同名資料夾,並找該資料夾是否有 `package.json` 或 `index.js`,而在 `router` 資料夾內的是 `index.ts`,因找不到檔案而出現問題 #### 解法一 修改 `.eslintrc.cjs`,在 `extends` 內的 `'airbnb-base'` 後面加上 `plugin:import/typescript` ```javascript module.exports = { extends: [ 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-typescript', 'airbnb-base', 'plugin:import/typescript', ], }; ``` #### 解法二 修改 `.eslintrc.cjs`,設定 `settings` 內的 `import/resolver` ```javascript module.exports = { settings: { 'import/resolver': { node: { extensions: ['.mjs', '.js', '.json', '.ts'], }, }, }, }; ``` --- ### import/no-unresolved 無法解析@ :::info * [Absolute Imports and Module Path Aliases](https://pjchender.dev/webdev/webdev-note-absolute-imports/ "Absolute Imports and Module Path Aliases | PJCHENder 未整理筆記") * [Vue 3 on Vite.js with Eslint — Unable to resolve path to module eslint(import/no-unresolved)](https://stackoverflow.com/a/69640843 "javascript - Vue 3 on Vite.js with Eslint — Unable to resolve path to module eslint(import/no-unresolved) - Stack Overflow") * [GitHub:eslint-plugin-import](https://github.com/import-js/eslint-plugin-import#typescript "GitHub - import-js/eslint-plugin-import: ESLint plugin with rules that help validate proper imports.") ::: ```typescript import '@/assets/style/reset200802.css'; // Unable to resolve path to module '@/assets/style/reset200802.css'. import/no-unresolved ``` #### 原因 [跟 `eslint-plugin-import` 有關](https://github.com/eslint/eslint/discussions/14667#discussioncomment-828441) #### 解法 1. 安裝 `eslint-import-resolver-typescript` 2. 修改 `tsconfig.json`,加上下方內容 ```json "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] } } ``` 3. 修改 `.eslintrc.cjs` ```javascript settings: { 'import/resolver': { typescript: { alwaysTryTypes: true, project: 'tsconfig.json', }, }, }, ``` --- ### import/extensions :::info * [GitHub:Airbnb ESLint configurations](https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/imports.js#L140 "javascript/packages/eslint-config-airbnb-base/rules/imports.js at master · airbnb/javascript · GitHub") ::: ```typescript // main.ts import router from './router'; // Missing file extension "ts" for "./router" import/extensions ``` #### 原因 `.ts` 檔案沒有寫出副檔名,和 Airbnb ESLint configurations 的規則不同 #### 解法 修改 `.eslintrc.cjs`,設定 `rules` 內的 `import/extensions` ```javascript module.exports = { rules: { 'import/extensions': ['error', 'ignorePackages', { js: 'never', mjs: 'never', jsx: 'never', ts: 'never', }], }, }; ``` --- ### import/no-extraneous-dependencies :::info * [Typescript, Airbnb and eslint import/no-extraneous-dependencies with alias](https://stackoverflow.com/questions/66773043/typescript-airbnb-and-eslint-import-no-extraneous-dependencies-with-alias "Typescript, Airbnb and eslint import/no-extraneous-dependencies with alias - Stack Overflow") * [GitHub:eslint-plugin-import import/core-modules](https://github.com/import-js/eslint-plugin-import#importcore-modules "GitHub - import-js/eslint-plugin-import: ESLint plugin with rules that help validate proper imports.") ::: ```typescript // vite.config.ts import { defineConfig } from 'vite'; // 'vite' should be listed in the project's dependencies, not devDependencies. import/no-extraneous-dependencies import vue from '@vitejs/plugin-vue'; // '@vitejs/plugin-vue' should be listed in the project's dependencies, not devDependencies. import/no-extraneous-dependencies ``` #### 解法 修改 `.eslintrc.cjs`,設定 `settings` 內的 `import/core-modules` ```javascript module.exports = { settings: { 'import/core-modules': [ 'vite', '@vitejs/plugin-vue', ], }, }; ``` --- :::info 建立日期:2023-09-21 更新日期:2023-09-22 :::