前言

大部分前端我的项目都配置StylelintEslintTslintPrettier四大前端代码校验工具。代码校验工具以下简称Lint,为了解决代码不谨严,通过预设规定校验代码,检测其是否存在谬误/破绽,并对谬误/破绽提醒修复计划并尽可能根据修复计划格式化出正确代码。该性能称为格式化代码,基本上所有编辑器都需配置该性能。

Lint其实就是编辑器里运行的一个脚本过程,将代码解析成形象语法树,遍历形象语法树并通过预设规定做一些判断和批改,再将新的形象语法树转换成正确代码。整个校验过程都跟形象语法树相干,若暂未接触过形象语法树,可浏览babel源码eslint源码理解其工作原理。

开发过程中启用Lint能带来以下益处。

  • 可强制标准团队编码标准,让新旧组员编码习惯失去统一晋升
  • 可灵便定制团队编码格调,让预设规定合乎新旧组员心理预期
  • 减少我的项目代码的可维护性可接入性,让新组员能疾速适应我的项目的架构与需要
  • 保障我的项目整体品质,可缩小无用代码反复代码错误代码破绽代码的产生几率
千万不能自私

有些同学可能一时适应不了Lint带来的强制性操作,会在本人编辑器里敞开我的项目所有校验性能,这种自私行为会带来很重大的结果。

若上传无任何校验痕迹的代码块,当其余组员将该代码块更新合并到原有代码上时,因为编辑器始终配置着团队编码标准,导致被拉下来的代码块立马报错甚至产生抵触。

上述情况会让其余组员破费更多工夫解决因为你不恪守规矩而带来的问题,还节约团队为了钻研如何让整体编码格调更适宜组员的精力。

这种自私行为不可取,若团队无任何编码标准可随便编码,若已认可团队编码标准那就致力恪守,不给团队带来麻烦。

背景

本文着重解说一键格式化代码的部署,像Lint罕用配置就不会解说,毕竟百度谷歌一搜一大堆。这个一键当然是ctrl+scmd+s保留文件啦。在保留文件时触发Lint主动格式化代码,这个操作当然不能100%保障将代码格式化出最正确代码,而是尽可能根据修复计划格式化出正确代码。言下之意就是可能存在局部代码格式化失败,但将鼠标移至红色下划线上会提醒修复计划,此时可根据修复计划自行修改代码。

为何写下本文?笔者有着谨严的代码逻辑和优雅的编码格调,所以特地喜爱格式化代码。然而又不想为每个我的项目配置Lint,这些反复无脑的复制粘贴让笔者很恶感,所以笔者只想一次配置全局运行Lint,这样就无需为每个我的项目配置Lint。在大量百度谷歌都未能搜到一篇相干文章(搜到的全副文章都是独自为一个我的项目配置,害),笔者就花了半年多工夫探讨出本计划,真正做到一次配置全局运行。若应用本计划,置信能将所有我的项目的StylelintEslintTslintPrettier相干依赖和配置文件全副移除,使我的项目目录变得超级简洁,如同下图。

笔者选用VSCode作为前端开发的编辑器,其余编辑器不是性能差就是配置麻烦,所以通通放弃,只认VSCode

在此强调两个重要问题,这两个问题影响到前面是否胜利部署VSCode一键格式化代码

  • Tslint官网已发表废除Tslint,改用Eslint代替其所有校验性能
  • Eslint局部配置与Prettier局部配置存在抵触且相互影响,为了保障格式化性能就放弃接入Prettier

所以部署VSCode一键格式化代码只需装置StylelintEslint两个插件。为了不便表述,对立以下名词。

  • 以下提及的StylelintEslint均为VSCode插件
  • 以下提及的stylelinteslint均为NPM依赖

步骤

后方高能,两大步骤就能为VSCode部署一键格式化代码,请认真浏览喔!

装置依赖

为了搞清楚两个插件集成哪些NPM依赖,以下辨别装置stylelinteslint及其相干依赖(看看即可,不要装置,重点在后头)。笔者有个习惯,就是喜爱将依赖更新到最新版本,在享受新性能的同时也顺便填坑。

# Stylelintnpm i -D stylelint stylelint-config-standard stylelint-order
# Eslintnpm i -D eslint babel-eslint eslint-config-standard eslint-plugin-html eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-react eslint-plugin-standard eslint-plugin-vue vue-eslint-parser
# TypeScript Eslintnpm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser typescript eslint-config-standard-with-typescript

装置实现后需配置多份对应配置文件,CSS方面有css/scss/less/vue文件,JS方面有js/ts/jsx/tsx/vue文件。查看插件文档,发现Stylelint只能在settings.json上配置,而Eslint可配置成多份对应配置文件,并在settings.json上通过特定字段指定Eslint配置文件门路。

settings.json是VSCode的配置文件,用户可通过插件裸露的字段自定义编辑器性能。

因为配置文件太多不好治理,笔者开源了本人平时应用的配置文件汇合,详情可查看vscode-lint。

  • demo:轻易捣鼓几个Demo用于测试格式化代码
  • eslintrc.js:校验js文件
  • eslintrc.react.js:校验jsx文件
  • eslintrc.vue.js:校验vue文件
  • tsconfig.json:配置TypeScript
  • tslintrc.js:校验ts文件
  • tslintrc.react.js:校验tsx文件
  • tslintrc.vue.js:校验vue文件

配置文件里的rule可依据本人编码标准适当调整,在此不深刻解说,毕竟简略得来谁都会。倡议应用vscode-lint,若校验规定不喜爱可自行调整。

  • 配置Stylelint请戳这里
  • 配置Eslint请戳这里
  • 配置TypeScriptEslint请戳这里
  • 配置VueEslint请戳这里

以下会基于vscode-lint部署VSCode一键格式化代码,找个目录通过git克隆一份vscode-lint,并装置其NPM依赖。若应用vscode-lint,上述依赖就不要装置了????。

git clone https://github.com/JowayYoung/vscode-lint.gitcd vscode-lintnpm i
配置插件
  • 关上VSCode
  • 抉择右边工具栏插件,搜寻并装置StylelintEslint,装置实现后重启VSCode
  • 抉择文件 → 首选项 → 设置设置里可选用户工作区

    • 用户:配置失效后会作用于全局我的项目(若大部分我的项目都是繁多的React利用或Vue利用举荐应用全局配置)
    • 工作区:配置失效后只会作用于以后关上我的项目
  • 点击设置右上角两头图标关上设置(json),关上的对应文件是settings.json(上述有提及)
  • 插入以下配置:若在用户选项下插入以下配置,遇到其余我的项目需笼罩配置时在工作区选项下插入eslint.options.configFile指定Eslint配置文件门路
  • 重启VSCode:为了保障每次批改配置后都能失常格式化代码,必须重启VSCode
{    "css.validate": false,    "editor.codeActionsOnSave": {        "source.fixAll.eslint": true,        "source.fixAll.stylelint": true    },    "eslint.nodePath": "path/vscode-lint/node_modules",    "eslint.options": {        "configFile": "path/vscode-lint/eslintrc.js"    },    "less.validate": false,    "scss.validate": false,    "stylelint.configBasedir": "path/vscode-lint",    "stylelint.configOverrides": {        "extends": "stylelint-config-standard",        "plugins": [            "stylelint-order"        ],        "rules": {            "at-rule-empty-line-before": "never",            "at-rule-no-unknown": [                true,                {                    "ignoreAtRules": [                        "content",                        "each",                        "error",                        "extend",                        "for",                        "function",                        "if",                        "include",                        "mixin",                        "return",                        "while"                    ]                }            ],            "color-hex-case": "lower",            "comment-empty-line-before": "never",            "declaration-colon-newline-after": null,            "declaration-empty-line-before": "never",            "function-linear-gradient-no-nonstandard-direction": null,            "indentation": "tab",            "no-descending-specificity": null,            "no-missing-end-of-source-newline": null,            "no-empty-source": null,            "number-leading-zero": "never",            "rule-empty-line-before": "never",            "order/order": [                "custom-properties",                "declarations"            ],            "order/properties-order": [                // 布局属性                "display",                "visibility",                "overflow",                "overflow-x",                "overflow-y",                "overscroll-behavior",                "scroll-behavior",                "scroll-snap-type",                "scroll-snap-align",                // 布局属性:浮动                "float",                "clear",                // 布局属性:定位                "position",                "left",                "right",                "top",                "bottom",                "z-index",                // 布局属性:列表                "list-style",                "list-style-type",                "list-style-position",                "list-style-image",                // 布局属性:表格                "table-layout",                "border-collapse",                "border-spacing",                "caption-side",                "empty-cells",                // 布局属性:弹性                "flex-flow",                "flex-direction",                "flex-wrap",                "justify-content",                "align-content",                "align-items",                "align-self",                "flex",                "flex-grow",                "flex-shrink",                "flex-basis",                "order",                // 布局属性:多列                "columns",                "column-width",                "column-count",                "column-gap",                "column-rule",                "column-rule-width",                "column-rule-style",                "column-rule-color",                "column-span",                "column-fill",                "column-break-before",                "column-break-after",                "column-break-inside",                // 布局属性:格栅                "grid-columns",                "grid-rows",                // 尺寸属性                "box-sizing",                "margin",                "margin-left",                "margin-right",                "margin-top",                "margin-bottom",                "padding",                "padding-left",                "padding-right",                "padding-top",                "padding-bottom",                "border",                "border-width",                "border-style",                "border-color",                "border-colors",                "border-left",                "border-left-width",                "border-left-style",                "border-left-color",                "border-left-colors",                "border-right",                "border-right-width",                "border-right-style",                "border-right-color",                "border-right-colors",                "border-top",                "border-top-width",                "border-top-style",                "border-top-color",                "border-top-colors",                "border-bottom",                "border-bottom-width",                "border-bottom-style",                "border-bottom-color",                "border-bottom-colors",                "border-radius",                "border-top-left-radius",                "border-top-right-radius",                "border-bottom-left-radius",                "border-bottom-right-radius",                "border-image",                "border-image-source",                "border-image-slice",                "border-image-width",                "border-image-outset",                "border-image-repeat",                "width",                "min-width",                "max-width",                "height",                "min-height",                "max-height",                // 界面属性                "appearance",                "outline",                "outline-width",                "outline-style",                "outline-color",                "outline-offset",                "outline-radius",                "outline-radius-topleft",                "outline-radius-topright",                "outline-radius-bottomleft",                "outline-radius-bottomright",                "background",                "background-color",                "background-image",                "background-repeat",                "background-repeat-x",                "background-repeat-y",                "background-position",                "background-position-x",                "background-position-y",                "background-size",                "background-origin",                "background-clip",                "background-attachment",                "bakground-composite",                "mask",                "mask-mode",                "mask-image",                "mask-repeat",                "mask-repeat-x",                "mask-repeat-y",                "mask-position",                "mask-position-x",                "mask-position-y",                "mask-size",                "mask-origin",                "mask-clip",                "mask-attachment",                "mask-composite",                "mask-box-image",                "mask-box-image-source",                "mask-box-image-width",                "mask-box-image-outset",                "mask-box-image-repeat",                "mask-box-image-slice",                "box-shadow",                "box-reflect",                "filter",                "mix-blend-mode",                "opacity",                "object-fit",                "clip",                "clip-path",                "resize",                "zoom",                "cursor",                "pointer-events",                "user-modify",                "user-focus",                "user-input",                "user-select",                "user-drag",                // 文字属性                "line-height",                "line-clamp",                "vertical-align",                "direction",                "unicode-bidi",                "writing-mode",                "ime-mode",                "text-overflow",                "text-decoration",                "text-decoration-line",                "text-decoration-style",                "text-decoration-color",                "text-decoration-skip",                "text-underline-position",                "text-align",                "text-align-last",                "text-justify",                "text-indent",                "text-stroke",                "text-stroke-width",                "text-stroke-color",                "text-shadow",                "text-transform",                "text-size-adjust",                "src",                "font",                "font-family",                "font-style",                "font-stretch",                "font-weight",                "font-variant",                "font-size",                "font-size-adjust",                "color",                // 内容属性                "tab-size",                "overflow-wrap",                "word-wrap",                "word-break",                "word-spacing",                "letter-spacing",                "white-space",                "caret-color",                "quotes",                "content",                "content-visibility",                "counter-reset",                "counter-increment",                "page",                "page-break-before",                "page-break-after",                "page-break-inside",                // 交互属性                "will-change",                "perspective",                "perspective-origin",                "backface-visibility",                "transform",                "transform-origin",                "transform-style",                "transition",                "transition-property",                "transition-duration",                "transition-timing-function",                "transition-delay",                "animation",                "animation-name",                "animation-duration",                "animation-timing-function",                "animation-delay",                "animation-iteration-count",                "animation-direction",                "animation-play-state",                "animation-fill-mode",                // Webkit专有属性                "-webkit-overflow-scrolling",                "-webkit-box-orient",                "-webkit-line-clamp",                "-webkit-text-fill-color",                "-webkit-tap-highlight-color",                "-webkit-touch-callout",                "-webkit-font-smoothing",                "-moz-osx-font-smoothing"            ]        }    }}

以上配置的pathvscode-lint所在的根目录,若方才的vscode-lint克隆到E:/Github,那么path就是E:/Github

示例

上述步骤实现后就可欢快敲代码了。每次保留文件就会主动格式化CSS代码JS代码,这个格式化代码不仅会将代码依照标准整顿排序,甚至尽可能根据修复计划格式化出正确代码。

这样就无需为每个我的项目配置Lint,将所有我的项目的StylelintEslintTslintPrettier相干依赖和配置文件全副移除,使我的项目目录变得超级简洁。

css/scss/less/vue文件

js/ts/jsx/tsx/vue文件

疑难

更新eslint到v6+就会生效

很多同学反映eslint v6+VSCode上生效,最高版本只能管制在v5.16.0。其实这自身就是配置问题,跟版本无关。vscode-linteslint应用v7照样能应用Eslint,只有配置正确就能失常应用。

上述装置行为应用了NPM,那么settings.jsoneslint.packageManager必须配置为npm(小写),但最新版本Eslint已默认此项,所以无需配置。若上述装置行为变成yarn install,那么必须在settings.json里增加以下配置。

{    "eslint.packageManager": "yarn"}

这个配置就是解决该问题的要害了。

首次装置Eslint并执行上述配置就会生效

首次装置Eslint可能会在js/ts/jsx/tsx/vue文件里看到以下正告。

Eslint is disabled since its execution has not been approved or denied yet. Use the light bulb menu to open the approval dialog.

阐明Eslint被禁用了,尽管配置里无明确的禁用字段,但还是被禁用了。此时移步到VSCode右下角的工具栏,会看到禁用图标+ESLINT的标红按钮,单击它会弹出一个弹框,抉择Allow Everywhere就能启用Eslint所有校验性能。

总结

整体过程看似简略,其实笔者这半年填了很多坑才有了vscode-lint,两头已省略了很多未记录的问题,这些疑难不重要却影响到很多中央。置信本文能让很多同学体验VSCode一键格式化代码所带来的快感,最要害的局部还是无需为每个我的项目配置Lint,这省下多少工夫和精力呀!感觉牛逼给vscode-lint点个Star吧!

回看笔者往期高赞文章,兴许能播种更多喔!

  • 《1.5万字概括ES6全副个性》:4200+点赞量,15.6w+浏览量
  • 《灵活运用CSS开发技巧》:4300+点赞量,13w+浏览量
  • 《中高级前端必须留神的40条挪动端H5坑位指南 | 网易三年实际》:3300+点赞量,4.5w+浏览量
  • 《灵活运用JS开发技巧》:1600+点赞量,5w+浏览量
  • 《25个你不得不晓得的数组reduce高级用法》:700+点赞量,2.3w+浏览量
  • 《8个硬核技巧带你迅速晋升CSS技术|掘金直播总结》:700+点赞量,1.8w+浏览量
  • 《妙用CSS变量,让你的CSS变得更心动》:500+点赞量,1.6w+浏览量

结语

❤️关注+点赞+珍藏+评论+转发❤️,原创不易,激励笔者创作更多高质量文章