关于css:一键格式化代码带来的快感你还在为每个项目配置Stylelint和Eslint吗

4次阅读

共计 9742 个字符,预计需要花费 25 分钟才能阅读完成。

前言

大部分前端我的项目都配置 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及其相干依赖 ( 看看即可,不要装置,重点在后头)。笔者有个习惯,就是喜爱将依赖更新到最新版本,在享受新性能的同时也顺便填坑。

# Stylelint
npm i -D stylelint stylelint-config-standard stylelint-order
# Eslint
npm 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 Eslint
npm 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.git
cd vscode-lint
npm 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+浏览量

结语

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

正文完
 0