Try   HackMD

如何整合ESlint, Prettier, VSCode?

tags: VSCode ESlint Prettier Vue

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

問題:同時使用ESlint和Prettier,會出現格式衝突

在Vue專案中,想使用vue/max-attributes-per-line,但會和Pretter衝突,造成每次存擋時,都無法如預期效果。

expected when formatOnSave:

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

<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應該還算堪用。


解法

官方建議
formatOnSave時,eslint會調整code為我們希望的風格,而semi column和spance等Prettier的工作則透過prettier-eslint-cli去完成,prettier-eslint每次只能prettier一行或一個檔案,要使用在整個專案,便需要prettier-eslint-cli。看了下prettier-eslint的npm,每週下載次數三十幾萬(2020/08時),最新更新在2020/06,且官方文件也有列入,可以放心使用。

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


VScode

在VScode的setting要調整,如下:

因為我們是要透過eslint去調整code,因此請把editor.formatOnSave關掉:

"editor.formatOnSave": false

但我們希望每次儲存時可以自動使用eslint:

  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },

設定希望eslint調整的檔案,因為是用Vue專案,所以有放vue:

  "eslint.alwaysShowStatus": true,
  "eslint.options": {
    "extensions": [".html", ".js", ".vue"]
  },
  "eslint.validate": ["html", "vue", "javascript"],

當然也不希望Vetur去format

  "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+),因此需設定在這。

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設定指令

{
  "scripts": {
    "format": "prettier-eslint \"src/**/*.js\""
  }
}

由於目前使用的是Vue專案,故修改如下:

"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],其他設定可以看這裡或是下指令prettier-eslint --help


測試

create一個vue component

<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應該會出現類似下圖

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

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

<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-整合-vue-style-guide-eslint-和-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