浅谈EditorConfig、Prettier以及Eslint的使用

EditorConfig、Prettier以及Eslint都用于实现前端代码规范化的工具,它们的功能分别如下:

 EditorConfig: 专注于统一编辑器编码风格配置

 Prettier: 专注于检查并自动更正代码风格,美化代码

 Eslint: 专注于 JavaScript 代码质量检查, 编码风格约束等

下面将简要介绍一下这三种工具:

1. EditorConfig

由于不同开发人员可能使用不同的编辑器,而不同编辑器有不同的编程风格,如有的编辑器使用空格缩进、有的使用Tab键缩进;有的编辑器Tab键表示2个空格缩进,有的编辑器Tab键表示4个空格缩进。因此,同一份代码在不同编辑器可能会呈现不同表现形式,如本地整齐的代码,在远端或同事编辑器上会变得异常难看,进而影响代码可读性和开发人员的情绪。为了解决编辑器配置层面的编码风格不一致问题,我们就需要使用到Editorconfig文件。

EditorConfig就是用于实现在跨不同的编辑器和IDE的同时,为多个开发人员提供一致编码风格的配置文件。EditorConfig项目由定义编码样式的文件格式和一组文本编辑器插件组成,编辑器插件通过读取文件并以已定义的样式格式化指定文件。

EditorConfig 可配置的编码风格条目包括:

 indent_style:  设置缩进为 tab 或 space

 tab_width:  设置 tab 所占列数。默认是 indent_size

 indent_size:  设置缩进所占列数,如果 indent_style 为 tab,则以 tab_width 值作为缩进宽度

 end_of_line:  设置换行符,值为 lf(换行)、cr(回车) 和 crlf(回车换行)

 charset:  设置编码,值为 latin1、utf-8、utf-8-bom、utf-16be 和 utf-16le,不建议使用 utf-8-bom

 trim_trailing_whitespace:  设为 true 表示会去除行尾的空白字符

 insert_final_newline:  设为 true 表示使文件以一个空白行结尾

 root:  表示是最顶层的配置文件,设为 true 时,停止向上查找

目前所有的属性名和属性值都是大小写不敏感的。编译时都会将其转为小写。通常,如果没有明确指定某个属性,则会使用编辑器的配置,而 EditorConfig 不会处理。

editorconfig通配符:

 * :  匹配除路径分隔符“/”以外的任意字符

 **: 匹配任意字符

 ?: 匹配任意单个字符

 [name]: 指定匹配字符

 [!name]: 指定非匹配字符

 {s1,s2,s3} :  匹配多个指定字符,以分号“,”分隔

 {num1..num2} :  匹配num1和num2之间的任意整数,num1和num2可以是正数,也可以是负数;特殊字符可以用反斜杠""转义,避免被解释为通配符模式

示例配置:

root = true  //表示为最顶层的配置文件,不会再向上查找

[*]  //对所有文件生效

indent_style = space  //设置缩进为空格

indent_size = 2 // 设置缩进所占列数为2

end_of_line = lf //表示\n 转义字符、换行

charset = utf-8 //设置为utf-8编码

trim_trailing_whitespace = true //设置去除行尾的空白字符

insert_final_newline = true //设置文件空白行结尾

[*.md] //以.md结尾的文件生效

trim_trailing_whitespace = false //设置不去除行尾的空白字符

[Makefile] //对Makefile文件生效

indent_style = tab //设置缩进为回车

EditorConfig 解决的只是编辑器配置层面的编码风格一致性问题。对于代码风格的部分并未涉及,比如是否「需要在语句末尾添加分号」,「字符串使用单引号还是双引号包裹」,「多行对象的书写规范」等等。这一类代码风格问题,则是由Prettier来规范。

2. Prettier

Prettier通过解析代码并匹配自己的一套规则,来强制执行一致的代码展示格式,在美化代码方面有很大的优势。Prettier 通过语法分析将代码解析为 AST 树(抽象语法树(Abstract Syntax Tree,AST),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构,在 AST 树上应用代码风格规范重新生成代码。

Prettier 使用 cosmiconfig 支持配置文件,cosmiconfig 是一种常用的配置文件读取工具,按照下述顺序沿文件树寻找配置文件,找到则停止:

 package.json 中的 prettier 字段

 .prettierrc 文件

 .prettierrc.json 文件

 .prettierrc.js 文件

 .prettierrc.toml 文件

选择上述任一方式进行自定义配置 Prettier,如不存在配置文件,Prettier 将依照默认值处理。

Prettier 处理的范围包含如:

 字符串引号风格

 空行处理

 多行对象格式

 分号处理

 打印宽度:

 控制换行

 通过换行控制评论影响范围

示例配置:

printWidth: 80,  // 打印宽度,默认是 80 列

tabWidth: 2,  // 缩进所占列数,默认是 2 列

useTabs: false,  // 缩进风格是否是Tab,默认是 false ,使用空格缩进

semi: true,  // 在语句末尾添加分号,默认是 true

singleQuote: false,  // 使用单引号,默认是 false

quoteProps: "as-needed",  // 对象中的属性使用引号, "as-needed" (默认)只对需要的属性加引号; "consistent" 同一对象中属性引号保持统一;"preserve" 强制使用引号。

jsxSingleQuotes: false,  // JSX中使用单引号,默认是 false

trailingComma: "es5",  // 多行时是否结尾添加逗号; "es5" (默认)ES5中允许逗号的容器中添加逗号; "all" 尽可能添加逗号;"none" 不允许添加逗

bracketSpacing: true,  // 是否保留对象内侧两端的空格,比如 { foo: bar } 和 {foo:bar} 的区别

jsxBracketSameLine: false,  // 多行 JSX 的元素是否能和属性同行,在多行JSX元素的最后一行追加 >, 默认是 false

arrowParens: "always",  // 箭头函数参数使用圆括号包裹 比如 (x) => x 和 x => x 的区别,"always"( 默认) 总是包裹; "avoid" 尽可能避免包裹

rangeStart: 0,  // 只格式化文件中的一部分,范围开始于第几行

rangeEnd: Infinity,  // 只格式化文件中的一部分,范围结束于第几行

parser: "none", // 指定解析器,根据文件路径推断解析器,比如 .js 文件使用 babel 解析;.scss 文件使用 post-scss 解析

filepath: "none",  // 指定用于推断使用那个解析器的文件名

requirePragma: false,  // 限制只格式化在文件顶部做了需格式化标识的文件,适用于在大型未格式化项目中,先指定少量文件格式化

insertPragma: false, //在文件的第一个docblock注释中插入@format pragma

proseWrap: "preserve", //默认为’ preserve’, 还有’nerver’和’always’

htmlWhitespaceSensitivity: "css",  // HTML 文件的空格敏感度,"css"(默认) 和 css 的 display 属性保持一致;"strict" 空格敏感; "ignore" 空格不敏感

vueIndentScriptAndStyle: false,  // 是否对 Vue 文件中 <script> 和 <style> 标签内的代码应用缩进

endOfLine: "lf",  // 换行符

embeddedLanguageFormatting: "auto",  // 是否格式化嵌入引用代码,比如 markdown 文件中嵌入的代码块; "auto" Prettier 自动识别并格式化; "off" 关闭自动格式化

    Prettier 专注于统一代码样式,并不具有 lint 检查语法等能力。而 Eslint 专注于找到代码存在的问题避免错误。

3. Eslint

Eslint 的关注点是代码质量,通过配置 .eslintrc.* 制定团队代码规范。

在代码编写的过程中,Eslint通过规则模式匹配实现识别和报告的不符合规范的代码的功能,并对不符合规范的代码进行红线提示。它的目的是保证代码规范的一致性和及时发现代码问题、提前避免错误发生。同时,Eslint提供命令行检查规范及 auto-fix 能力,并具有一部分代码格式化的功能。

Eslint支持的配置文件格式 :

 javascipt - 使用 .eslintrc.js 然后输出一个配置对象。

 yaml - 使用 .eslintrc.yaml 或 .eslintrc.yml 去定义配置的结构。

 json - 使用 .eslintrc.json 去定义配置的结构,ESLint 的 JSON 文件允许 JavaScript 风格的注释。

 package.json - 在 package.json 里创建一个 eslintConfig 属性,在那里定义你的配置。

如果同一个目录下有多个配置文件,Eslint只会使用一个。遇到项目内有多个层叠配置时,采用就近原则作为高优先级。优先级顺序如下:

.eslintrc.js  .eslintrc.yaml  .eslintrc.yml  .eslintrc.json  package.json

Eslint配置文件:

 extends: 指定扩展的配置,配置支持递归扩展,支持规则的覆盖和聚合。extends 数组的顺序非常重要。基本上,每次一个新配置添加到这个数组中,它都会覆盖前面的配置。

 ignorePatterns:  忽略特定的文件和目录

 rules: 启用的规则及其各自的错误级别,可以覆盖掉extends的配置。你可以使用注释或配置文件修改你项目中要使用的规则。要改变一个规则设置,你必须将规则 ID 设置为下列值之一:"off" (0)- 关闭规则;"warn"(1)- 开启规则,使用警告级别的错误: "error" (2)- 开启规则,使用错误级别的错误,此时程序会退出

 plugins: 配置想要使用的Linting规则的第三方插件名字列表。插件名称可以省略 eslint-plugin- 前缀。

 env: 指定脚本的运行环境,每种环境都有一组特定的预定义全局变量。如 brower、node、es6 等。

 parser: 默认Eslint使用Espree作为解析器,如果使用babel的话,我们需要用babel-eslint。

 parserOptions: 当默认解析器从Espree改为babel-eslint时,必须指定parseOptions

 globals: 配置额外的全局变量。启用 Eslint规则后,当访问当前源文件内未定义的变量时,no-undef 规则将发出警告。 而有时候,我们是需要在其他文件访问一些全局变量的,且保证能正常取到值。这时可以在 Eslint中定义这些全局变量,这样 Eslint就不会发出警告了。

 settings:该字段定义的数据可以在所有的插件中共享。这样每条规则执行的时候都可以访问这里面定义的数据

4. EditorConfig、Prettier以及Eslint 之间的协作

Prettier 和 EditorConfig 共享一些配置项,我们不希望在两个单独的文件中重复这些配置项,并让二者保持同步(比如:尾行配置)。Prettier 的最新版本通过解析 .editorconfig 文件来确定要使用的配置选项解决了此问题。

这些选项仅限于:

end_of_line

indent_style

indent_size/tab_width

max_line_length

这些配置选项将覆盖以下 Prettier 选项(如果未在 .prettierrc 中定义它们):

"endOfLine"

"useTabs"

"tabWidth"

"printWidth"

解决prettier和eslint间冲突的插件,有如下几种:

 eslint-config-prettier: 会禁用掉所有非必须或者和prettier冲突的规则,以符合eslint规则的方式格式化代码并提示对应的修改建议。

 eslint-plugin-prettier: 该插件辅助Eslint可以平滑地与Prettier一起协作,并将Prettier的解析作为Eslint的一部分,在最后的输出可以给出修改意见。这样当Prettier格式化代码的时候,依然能够遵循我们的Eslint规则。

 prettier-eslint:可以让prettier和eslint结合起来。输入代码,执行prettier后再eslint --fix输出格式化后的代码。但该工具只支持输入代码字符串,不支持读取文件。

 prettier-eslint-cli:在prettier-eslint的基础上支持读取文件,支持CLI命令执行prettier-eslint的操作。

5. Lint-staged和Husky

 Lint-staged

Lint-staged帮助你在暂存文件的时候能够让错误格式代码不会提交到你分支。

由于提交代码前的检查是最后一个管控代码质量的一个环节,所以在提交代码之前进行lint检查意义重大。这样可以确保没有错误的语法和代码样式被提交到仓库上。但是在整个项目上执行Lint进程会很低效,所以最好的做法就是检查那个被改动的文件。而Lint-staged就是做这个的。

在package.json中配置该字段:

"lint-staged": {

      "*.{tsx,ts}": [ // 这里的文件后缀可以修改成自己需要的文件后缀

    "prettier-eslint --write",

    " eslint --fix --max-warnings=0 --no-ignore",

        "git add"

      ]

}

通过该配置,去实现由prettier-eslint-cli将代码prettier一遍后,再eslint --fix,如果没有错误,那么就会直接执行git add,否则报错退出。

 Husky

为了保证每次commit的时候会执行lint操作,我们需要借助git的钩子功能,而提供钩子功能的就是Husky,该工具提供了git在多个阶段前执行的操作。

在package.json中配置该字段:

"husky": {

    "hooks": {

        "pre-commit": "lint-staged",  //预提交的时候进行Lint检查

        "pre-push": "npm run test:unit" //代码推送到远端时运行单元测试

    }

},

6. 总结

EditorConfig、Prettier以及Eslint的引入,可以提高代码的可读性、可维护性。使项目更好管理,成员之间合作更顺畅。同时,我们也应该清楚认识到工具的局限性,不要做严格代码规范的强迫症患者,过于严格的规则,会限制代码的灵活性,每个规则是否应存在,应根据具体项目具体分析。我们应借助EditorConfig、Prettier以及Eslint帮助我们养成良好的编码习惯,培养写优质代码的意识,而不是完全依赖他们。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容