---
# System prepended metadata

title: '如何整合ESlint, Prettier, VSCode？'
tags: [ESlint, VSCode, Prettier, Vue]

---

# 如何整合ESlint, Prettier, VSCode？
###### tags: `VSCode` `ESlint` `Prettier` `Vue`

先說結論：無法同時使用ESlint和Prettier，ESlint是調整coding的style，Prettier是用來規範coding的嚴謹度，兩者做的事會有衝突。

### 問題：同時使用ESlint和Prettier，會出現格式衝突
在Vue專案中，想使用[vue/max-attributes-per-line](https://eslint.vuejs.org/rules/max-attributes-per-line.html)，但會和Pretter衝突，造成每次存擋時，都無法如預期效果。

expected when formatOnSave:
```htmlmixed
<template>
  <div v-show="test"
       v-if="on"
       id="123"
       class="test">
    {{ quote }}
    <p id="1"
       class="123">
      1234
    </p>
  </div>
</template>
```
actually happened when formatOnSave:
```htmlmixed
<template>
  <div v-show="test" v-if="on" id="123" class="test">
    {{ quote }}
    <p id="1" class="123">
      1234
    </p>
  </div>
</template>
```

查完GitHub的issues和StackOverFlow之後，結論就是如上，關掉vue/max-attributes-per-line或是關掉Prettier，但無論如何兩者都想使用的話，有找到一個lib應該還算堪用。



---


### 解法
[官方建議](https://prettier.io/docs/en/integrating-with-linters.html#disable-formatting-rules)
formatOnSave時，eslint會調整code為我們希望的風格，而semi column和spance等Prettier的工作則透過[prettier-eslint-cli](https://github.com/prettier/prettier-eslint-cli)去完成，prettier-eslint每次只能prettier一行或一個檔案，要使用在整個專案，便需要prettier-eslint-cli。看了下[prettier-eslint的npm](https://www.npmjs.com/package/prettier-eslint)，每週下載次數三十幾萬(2020/08時)，最新更新在2020/06，且官方文件也有列入，可以放心使用。

共有3個地方需處理: 1. VScode 2. eslintrc.js 3. package.json



---
#### VScode

在VScode的setting要調整，如下：

因為我們是要透過eslint去調整code，因此請把editor.formatOnSave關掉：
```javascript
"editor.formatOnSave": false
```

但我們希望每次儲存時可以自動使用eslint：
```javascript
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
```
設定希望eslint調整的檔案，因為是用Vue專案，所以有放vue：
```javascript
  "eslint.alwaysShowStatus": true,
  "eslint.options": {
    "extensions": [".html", ".js", ".vue"]
  },
  "eslint.validate": ["html", "vue", "javascript"],
```

當然也不希望Vetur去format
```javascript
  "vetur.validation.template": false,
  "vetur.validation.script": false,
```
---

#### eslintrc.js 

不希望將settings和rule都放在package.json中，故在根目錄建立eslintrc.js，若使用vue-cli的話它會幫你內建此檔案。

extends裡代表的是一個大範圍的規範，裡面有許多rules，只要放入`plugin:vue/recommended`，你就可以使用vue風格全部的規範，並且在rules中客製化自己或是團隊的style，不需要逐條設定。recommended是最嚴謹的風格也是最不需動腦的設定，相反的，vue/base是最基本也是最不嚴謹的。在extends中，我們只需要vue和eslint的style，有關prettier的都可以先移除。
parserOptions是因為我們有使用較新的js語法(如es6+)，因此需設定在這。

```javascript
module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: [
    'plugin:vue/recommended',
    'eslint:recommended',
  ],
  parserOptions: {
    parser: 'babel-eslint'
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',

    'vue/max-attributes-per-line': [
      'error',
      {
        singleline: 1,
        multiline: {
          max: 1,
          allowFirstLine: true
        }
      }
    ]
  }
}
```

---
#### package.json

打開terminal，用npm安裝在專案中的devDependencies

`npm install --save-dev prettier-eslint-cli`

確認安裝完成在devDependencies：

`"prettier-eslint-cli": "^5.0.0",`

在package.json中的script設定指令
```javascript
{
  "scripts": {
    "format": "prettier-eslint \"src/**/*.js\""
  }
}
```

由於目前使用的是Vue專案，故修改如下：
```javascript
"format": 
"prettier-eslint --write \"$(pwd)/src/**/*.js\" \"$(pwd)/src/**/*.vue\" 
[--semi false --single-quote true]"
```

`--write` : 讓prettier-eslint-cli可以直接修改你的檔案，沒有加的話，只會將修改的結果log在terminal上，不管跑幾次你的code實際上都不會改變


`\"$(pwd)/src/**/*.js\" \"$(pwd)/src/**/*.vue\"` 
$(pwd)是指Pathname of the current Working Directory
要format複數檔案的話，以空格分開，再放上路徑及檔名

`[--semi false --single-quote true]`: option設定的地方，如文件中所寫的prettier-eslint <globs>... [--option-1 option-1-value --option-2]，其他設定可以看[這裡](https://github.com/prettier/prettier-eslint-cli#cli-options)或是下指令`prettier-eslint --help`



---

#### 測試

create一個vue component

```javascript
<template>
  <div v-show="test"
       v-if="on"
       id="123"
       class="test">
    {{ quote }}
    <p id="1"
       class="123">
      1234
    </p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      quote: "test"
    }
  }
};
</script>

<style>
.a {
  color: black
}
</style>

```
可以看到上面幾個故意打錯不符合先前設定的Prettier規則：
"test"沒有使用singleQuate
export default結尾放了semicolumn
css的black沒有semicolumn

此時在terminal中run: `npm run format`應該會出現類似下圖
![](https://i.imgur.com/noVshzs.png)

便表示成功讓prettier-eslint幫你使用了prettier且沒有更改eslint調整的code。

```htmlmixed
<template>
  <div v-show="test"
       v-if="on"
       id="123"
       class="test">
    {{ quote }}
    <p id="1"
       class="123">
      1234
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      quote: 'test'
    }
  }
}
</script>

<style>
.a {
  color: black;
}
</style>
```



---

為了讓Prettier和ESlint同時使用，重點是想要符合Vue的style指引，花了不少時間爬文和測試設定，也剛好更了解這兩個套件彼此的關係。

如內容有誤或有其他想法歡迎交流！

refference:
https://eslint.vuejs.org/user-guide/#installation
https://pjchender.github.io/2019/07/26/vue-%E6%95%B4%E5%90%88-vue-style-guide-eslint-%E5%92%8C-vscode/
https://github.com/prettier/prettier-eslint-cli
https://github.com/prettier/eslint-plugin-prettier/issues/289
https://eslint.vuejs.org/rules/html-closing-bracket-newline.html