1 在VSCode中單獨使用Prettier儲存程式碼自動格式化的配置方法
1.1 為什麼要使用Prettier?
手動調整程式碼格式,不僅低效,而且在團隊協作開發中,無法保證程式碼風格統一,所以需要引入自動格式化程式碼工具。Prettier不僅可以格式化js, jsx, vue,angular,ts,flow,還適用於HTML, CSS/Less,/Sass,Markdown, YAML, GraphQL程式碼的格式化,
1.2 Prettier程式碼格式化規則有哪些?
{ printWidth: 80, // 超過最大值換行 tabWidth: 2, // 縮排位元組數 useTabs: false, // 縮排不使用tab,使用空格 semi: true, // 句尾新增分號 singleQuote: false, // 使用單引號代替雙引號 quoteProps: 'as-needed', // 物件的key是否用引號括起來,有三種選項 "as-needed"|"consistent"|"preserve" jsxSingleQuote: false, // 在jsx中使用單引號代替雙引號 trailingComma: 'es5', // 選項:none|es5|all, 在物件或陣列最後一個元素後面是否加逗號(在ES5中加尾逗號) bracketSpacing: true, // 是否在物件的{}內部兩側加空格 true - { foo: bar } false - {foo: bar}. jsxBracketSameLine: false, // 在jsx中把'>' 是否單獨放一行 arrowParens: 'avoid', // (x) => {} 箭頭函式引數只有一個時是否要有小括號。avoid:省略括號 'bracketSpacing': true, // 在物件,陣列括號與文字之間加空格 "{ foo: bar }" rangeStart: 0, // 僅格式化選中文字 選中文字格式化的起始位置 rangeEnd: Infinity, // 選中文字格式化的結束位置 parser: 'babylon', // 格式化的解析器,預設是babylon,會自動根據輸入檔案推斷,不用更改設定 requirePragma: false, // 若為true,檔案頂部加了 /*** @prettier */或/*** @format */的檔案才會被格式化 insertPragma: false, // 當requirePragma引數為true時,此引數為true將向@format標記後面新增一個換行符 proseWrap: 'preserve', // 有效選項[always|never|preserve]。當Markdown文字超過printWidth時,是否換行,always-換行 never-不換行 preserve保持原樣 endOfLine: 'lf', // 結尾是 lf-\n cr-\r lfcr-\n\r auto-保持現有的行尾設定 htmlWhitespaceSensitivity: 'css', // 是否顯示HTML檔案中的空格。 有效選項: 'css' - 尊重CSS display屬性的設定。 'strict' - 空格被認為是敏感的。 'ignore' - 空格被認為是不敏感的 vueIndentScriptAndStyle: false, // 是否給vue中的 <script> and <style>標籤加縮排 embeddedLanguageFormatting: 'auto', // 是否格式化嵌入到JS中的html標記的程式碼段或者Markdown語法 auto-格式化 off-不格式化 }
1.3 如何開啟儲存時程式碼自動格式化?
1.3.1 下載Prettier外掛
在vscode的配置檔案中,設定儲存程式碼時使用prettier自動進行程式碼格式化
{ "javascript.format.enable": false, // 禁用vscode預設的js格式化外掛 "editor.formatOnSave": true, // 儲存程式碼的時候格式化 "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" // js檔案採用prettier進行格式化 }, }
配置完之後,儲存程式碼時,就有自動格式化的效果。
2.ESLint程式碼校驗配置
2.1 有了Prettier之後,為什麼還需要ESLint?
prettier只關心程式碼格式,這顯然是不夠的,我們追求的目標不僅僅是程式碼風格統一,還要在書寫的時候,避免一些常見的低階的錯誤。所以,就要引入ESlint。ESLint也有許多與程式碼規則有關的配置項,那你可能要問,我只用eslint就好了,既能規範編碼風格,也能提升程式碼質量。何必兩個都用,用了還容易起衝突,這是因為eslint的程式碼格式化有盲區,只針對js,jsx,ts,tsx,不能格式化HTML, CSS/Less,/Sass,Markdown, YAML, GraphQL,以及vue中的html和css。
2.2 Prettier和ESLint為什麼會衝突?
Prettier的功能比較專一,是專門用來格式化程式碼的,格式化程式碼的範圍比ESLint廣泛。
ESLint的功能相對綜合,大體可以分為類,一類是規範程式碼風格(見下圖),一類是規範程式碼質量。
它們之所以會衝突,就是因為井水犯了河水,功能有交叉,而且規則不同,比如Prettier格式化程式碼,預設每行後面加分號,而ESLint的規則是不加,再比如Prettier格式化程式碼時,字串會用雙引號包起來,而ESLint的規則是單引號,由此就產生的衝突。
2.3 如何解決兩者的衝突?
要麼修改Prettier的規則,使之與ESLint保持一致,要麼修改ESLint的校驗規則,使之與Prettier的程式碼格式化風格一致,究竟要改哪一個,都可以。個人傾向於改ESlint的規則,因為Prettier的程式碼格式化規則是普適的,而ESLint的程式碼校驗規則是針對特定語言的,特定的遵從普適的原則上好一些。
ESLint有關程式碼風格的設定,有些是和Prettier衝突的,安裝eslint-config-prettier npm工具包,就可以關閉eslint程式碼風格部分與prettier衝突的設定。
yarn add -D eslint-config-prettier
在.eslintrc.js中新增
{ "extends": [ "some-other-config-you-use", "prettier" ] }
2.3 vscode 儲存時自動修復eslint報錯的配置
2.3.1 安裝ESLint外掛
2.3.2 在.vscode中setting.json中開啟程式碼儲存自動修復eslint告警功能
"editor.codeActionsOnSave": { "source.fixAll.eslint": true },
2.3.3 安裝 eslint npm包
# 檔案中使用 npm install -D eslint # 命令列使用 npm install -g eslint
2.3.4 在專案下新增.eslintrc.js檔案,內容如下:
module.exports = { parser: 'babel-eslint', parserOptions: { // 想使用的額外的語言特性 ecmaFeatures: { legacyDecorators: true, // 裝飾器 }, }, // 新增共享設定 settings: { polyfills: ['fetch', 'promises', 'url', 'object-assign'], }, // extends 屬性值可以省略包名的字首 eslint-config- // 你可能想要將你的配置資訊分享給其他專案或人。可分享的配置允許你在 npm 釋出你的配置設定並且其他人可以在他的 ESLint 專案中下載使用這些配置。 // 可共享的配置 是一個 npm 包,它輸出一個配置物件。 extends: ['airbnb', 'prettier', 'plugin:compat/recommended'], // 外掛一般是輸出規則,一些外掛也可以輸出一個或多個命名的 配置 plugins: ['react'], // 指定指令碼的執行環境。每種環境都有一組特定的預定義全域性變數。 env: { browser: true, node: true, es6: true, mocha: true, jest: true, jasmine: true, }, globals: { localStorage: true, sessionStorage: true, WeixinJSBridge: true, screen: true, wx: true, qq: true, alert: true, Image: true, File: true, FormData: true, IntersectionObserver: true, fiboSDK: true, }, rules: { // 規則集,會覆蓋extends中的規則 'react/jsx-filename-extension': [1, { extensions: ['.js'] }], 'react/jsx-wrap-multilines': 0, 'react/prop-types': 0, 'react/forbid-prop-types': 0, 'react/jsx-one-expression-per-line': 0, 'import/no-unresolved': [2, { ignore: ['^@/', '^umi/'] }], 'import/no-extraneous-dependencies': [0], 'jsx-a11y/no-noninteractive-element-interactions': 0, 'jsx-a11y/click-events-have-key-events': 0, 'jsx-a11y/no-static-element-interactions': 0, 'jsx-a11y/anchor-is-valid': 0, 'linebreak-style': 0, 'no-console': 0, 'import/prefer-default-export': 0, 'react/destructuring-assignment': 0, 'consistent-return': 0, 'no-return-assign': 0, 'no-case-declarations': 0, 'react/no-array-index-key': 0, 'no-plusplus': 0, 'no-param-reassign': 0, 'no-useless-escape': 0, 'array-callback-return': 0, 'no-unused-expressions': 0, 'no-underscore-dangle': 0, 'no-lonely-if': 0, 'func-names': 0, 'react/no-access-state-in-setstate': 0, 'react/no-did-update-set-state': 0, 'no-restricted-syntax': 0, 'no-nested-ternary': 0, 'no-restricted-globals': 0, 'react/jsx-props-no-spreading': 0, 'class-methods-use-this': 0, 'global-require': 0, 'react/state-in-constructor': 0, 'import/no-dynamic-require': 0, 'react/no-danger': 0, 'react/sort-comp': 0, 'no-shadow': 0, camelcase: 0, // 不檢驗函式入參是否被使用 'no-unused-vars': ['warn', { args: 'none' }], }, };
參考文獻