# [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
:::