引言

最近做的一个组件库项目要求比较高,需要对其代码进行规范。要求文档中提到了很多我之前没有见过的工具和专业术语,于是打算写几篇文章来解决一下。首先抛出问题,为什么要对组件库项目制定规范?

制定规范的目的在于保证质量、方便业务方使用和增加组件库的可扩展性。比如对于样式的封装、常用Mixin封装,强制使用颜色变量等。还有设计统一的组件库API风格规范,能降低业务方的使用成本。

将规范拆解来看,主要包括以下几个方面:

  1. 代码风格:eslintprettierstylelint
  2. 代码提交:huskycommitlintlint-staged
  3. 文档风格:remark-lint
  4. 组件模板:plop.js
  5. 依赖管理:lint-deps
  6. 目录规范

本文围绕 代码风格 规范,来仔细学习一下 eslintprettierstylelint 分别是什么。


简短概述

Prettier / ESlint / Stylelint 都是用来处理代码格式的。

Prettier 和 Lint 可以单独用,也可以一起用。它们的区别是什么?

  • Prettier
    1. 侧重代码格式化检查:如 printWidth、semi、singleQuote…
    2. 支持处理多种语言:html、css、js、ts、json…,即可以对这些语言进行格式处理
  • Lint(eslint,stylelint)
    1. 侧重代码质量检查,例如 Eslint:no-var、eqeqeq、no-multiple-empty-lines
    2. 不支持处理多种语言,如 Eslint 处理 JS;Stylelint 处理 CSS

结合以上两者有助于我们在开发过程中保持代码风格统一以及代码质量检查。


EditorConfig 使用

这是用来统一不同IDE之间的配置的文件。目前前端群体基本都用vscode,如果团队有人还在用webstorm等,建议统一成vscode(参考:http://editorconfig.org

  • .editorconfig
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 统一不同IDE之间的配置的文件:http://editorconfig.org

    root = true # 表示是最顶层的配置文件,发现值为true时,才会停止查找.editorconfig文件

    [*]
    charset = utf-8 # 设置编码格式,值为latin1、utf-8、utf-8-bom、utf-16be和utf-16le
    indent_style = space # 设置使用那种缩进风格(tab是制表符,space是空格)
    indent_size = 2 # 定义用于每个缩进级别的空格数
    # tab_width = 2 # 用一个整数来设置tab缩进的列数
    end_of_line = lf # 设置换行符,值为lf、cr、crlf和auto
    trim_trailing_whitespace = true # 设置为true会删除每一行后行符之前的任何空格空白字符
    insert_final_newline = true # 设置为true以确保文件(包括最后一行)在保存时以换行符结尾,最后一行会强制换行到下一行

该文件是用来统一其他IDE的,咱们使用 VS Code 开发默认不支持 EditorConfig,需要自行在编辑器扩展商店中搜索 EditorConfig(即 EditorConfig for VS Code)。打开项目时,EditorConfig 插件会在打开文件的目录和每个父目录中查找 .editorconfig 文件,如果到达根文件路径或 EditorConfig 文件 root = true,则文件搜索将停止。EditorConfig 文件从上到下读取,最先发现的规则优先。当配置好了需要的文件或者编辑器格式,就可以正常进行开发使用了。


Volar 使用

在 Vue2 项目中一般我们使用的是 Vetur 插件,但是 Vue3 项目推荐使用 Vue Language Features (Volar) 插件。

Volar 插件提供了更加强大的功能,但由于会与 Vetur 出现冲突,所以启用 Volar 插件的同时需要禁用 vetur 插件。


Prettier 使用

负责各文件代码格式检查、修复
Prettier官方文档:https://prettier.io/docs/en/index.html
GitHub:https://github.com/prettier/prettier

  • 首先,在 VS Code 搜索安装扩展插件 Prettier - Code formatter

  • 安装依赖(以pnpm为例)

    1
    2
    # npm install -D prettier
    pnpm add -D prettier
  • 项目根目录创建 .prettierrc.cjs 配置文件,让编辑器和其他工具知道你在使用 Prettier。配置参数可以参考文档 Options格式选项

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // Prettier代码格式化配置项:https://prettier.io/docs/en/options.html

    module.exports = {
    printWidth: 120, // 一行最多 120 字符
    tabWidth: 2, // 使用 2 个空格缩进
    useTabs: false, // 不使用缩进符,而使用空格
    semi: true, // 行尾需要有分号
    singleQuote: true, // 使用单引号
    quoteProps: 'as-needed', // 对象的 key 仅在必要时用引号
    jsxSingleQuote: false, // jsx 不使用单引号,而使用双引号
    trailingComma: 'all', // 末尾需要有逗号
    bracketSpacing: true, // 大括号内的首尾需要空格
    bracketSameLine: false,
    arrowParens: 'always', // 箭头函数,只有一个参数的时候,也需要括号
    rangeStart: 0, // 每个文件格式化的范围是文件的全部内容
    rangeEnd: Infinity,
    requirePragma: false, // 不需要写文件开头的 @prettier
    insertPragma: false, // 不需要自动在文件开头插入 @prettier
    proseWrap: "preserve", // 使用默认的折行标准
    htmlWhitespaceSensitivity: 'css', // 指定HTML文件的全局空格敏感度,根据显示样式决定 html 要不要折行
    vueIndentScriptAndStyle: false, // vue 文件中的 script 和 style 内不用缩进
    endOfLine: 'lf', // 换行符使用 lf
    embeddedLanguageFormatting: 'off', // 不格式化 Markdown 中的嵌入式代码块
    singleAttributePerLine: false // 不要强制在 HTML、Vue 和 JSX 中每行使用单个属性
    };
  • 下一步,创建 .prettierignore 文件,让 Prettier CLI 和编辑器知道哪些文件不用格式化。比如:

    1
    2
    # Node modules
    node_modules/

    提示:如果有 .gitignore.eslintignore 文件的话,.prettierignore 可以基于它们来编写。
    另一个提示!如果您的项目还没有准备好格式化超文本标记语言文件,请添加*.html

  • package.json 文件配置脚本

    1
    2
    3
    "scripts": {
    "lint:fix": "prettier packages/**/* --write"
    }

Stylelint 使用

Stylelint官网:https://stylelint.io/
Stylelint中文网:https://stylelint.bootcss.com/

  • 首先,在 VS Code 搜索安装扩展插件 Stylelint

  • 安装依赖(以pnpm为例)

    1
    2
    # npm install -D stylelint stylelint-order stylelint-config-standard stylelint-config-prettier stylelint-config-recommended-vue postcss-html stylelint-less stylelint-config-recommended-less
    pnpm add -D stylelint stylelint-order stylelint-config-standard stylelint-config-prettier stylelint-config-recommended-vue postcss-html stylelint-less stylelint-config-recommended-less

    除了安装 eslint外,其他几个是待会用到的依赖,作用分别如下:

    1. stylelint-config-standard:该风格是 Stylelint 的维护者汲取了 GitHub、Google、Airbnb 多家之长生成的官方 css 代码风格标准配置。之所以更推荐安装这个standard标准配置作为自己的配置基础,是因为它扩展了recommended推荐配置并添加了一些规则来执行通用约定。
    2. stylelint-config-prettier: 关闭所有不必要的或可能与Prettier冲突的规则,确保将其放在配置文件 extends 队列最后,这样它将覆盖其他配置。
    3. stylelint-order:样式自定义排序,作用是强制你按照某个顺序编写 css。例如先写定位,再写盒模型,再写内容区样式,最后写 CSS3 相关属性。这样可以极大的保证我们代码的可读性。
    4. stylelint-config-recommended-vue该依赖是stylelint的官方推荐,扩展了stylelint-config-recommended共享配置并为 Vue 配置其检验规则。
    5. postcss-html:需要安装该依赖,是因为stylelint-config-recommended-vue文档中说明了其捆绑了postcss-html自定义语法(社区编写的PostCSS语法),并将它作为了peerDependencies对等依赖,不安装会警告。该依赖是用来解析类 HTML 文件里<style>标签中的样式。所以安装后可以将带有Stylelint的linting应用于HTML(和类HTML)中的<style>标签和<div style="*">属性。
    6. postcss postcss-less:由于运行stylelint检查less文件时提示 When linting something other than CSS, you should install an appropriate syntax, e.g. "postcss-less", and use the "customSyntax" option,在stylelint文档中也有说明,Stylelint 不再包含类CSS的语言(如SCSS/SASS/LESS/SugarSS),如果要支持相应语法,需要安装相应的依赖。也有教程中说,若项目中存在scss文件需安装postcss-scss,若项目中存在less文件需安装postcss-less。根据对等依赖关系警告信息,除了安装postcss-less,还得安装postcss
    7. stylelint-less stylelint-config-recommended-less:经过我粗略研究发现Stylelint生态是建立在Postcss之上的,这也就是为什么不安装postcss-less插件也可以检查出一些less单文件中的规范错误。于是参考stylelint文档中安装stylelint-config-standard-scss,我们可以安装 stylelint-config-recommended-less 来扩展Stylelint配置,从而支持对LESS进行lint的能力。安装 stylelint-config-recommended-less 的步骤中需要安装 stylelint-less,通过stylelint-less自述文件可以得知Stylelint确实支持 less 语法,但是 stylelint 中的一些规则没有按预期工作,所以创建了这个插件来支持 less 那些规则,因为 Stylelint 通常专注于标准 CSS 语法。
  • 创建 .stylelintrc.cjs 文件,其中rules部分在开发过程中可以参考英文官网或寻找中文翻译来修改或禁用相应规则,从而消除对应报错。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // Stylelint 样式格式化配置:https://stylelint.bootcss.com/user-guide/get-started

    module.exports = {
    // 插件
    plugins: [
    'stylelint-order',
    ],
    // 扩展
    extends: [
    'stylelint-config-standard',
    'stylelint-config-recommended-vue',
    'stylelint-config-recommended-less',
    'stylelint-config-prettier',
    ],
    // 覆盖配置中基于文件全局模式的设置 https://stylelint.io/user-guide/configure#overrides
    overrides: [
    {
    files: ['**/*.{html,vue}'],
    customSyntax: 'postcss-html'
    },
    {
    files: ['**/*.less'],
    customSyntax: 'postcss-less'
    }
    ],
    // 规则(值为 null 时表示禁用该规则)
    rules: {
    'no-invalid-double-slash-comments': null, // 禁止 CSS 不支持的双斜线注释
    },
    ignorePath: '.stylelintignore',
    };

    至于为什么不是以.js结尾,我试过了会再执行命令时报错。好像是因为在package.json中指定"type":"module"的JavaScript包中运行ESLint时要使用.eslintrc.cjs(官方文档中也提到了,注意ESLint目前不支持ESM配置)。或者你直接创建.stylelintrc文件,里边用json格式书写也可以,由于我希望包含一些必要注释所以我还是用.cjs文件吧。

  • 创建 .stylelintignore 忽略文件

    1
    2
    # Node modules
    node_modules/
  • package.json 添加 stylelint 脚本(随项目情况自行修改其中的路径)

    1
    2
    3
    "scripts": {
    "lint:style": "stylelint packages/**/*.{vue,css,less,scss,sass} --fix"
    }

    这样以后可以运行 npm run lint:stylepnpm lint:style 即可自动修复不符合规定的样式,但个别报错需要自行修复


ESLint 使用

负责 js 文件代码检查、修复
Eslint官网:https://eslint.org/
Eslint中文网:https://zh-hans.eslint.org/

  • 首先,在 VS Code 搜索安装扩展插件 ESLint,它会在 VS Code 中集成 ESLint。

  • 安装依赖(以pnpm为例)

    1
    2
    # npm install -D eslint eslint-plugin-vue eslint-plugin-prettier eslint-config-prettier
    pnpm add -D eslint eslint-plugin-vue eslint-plugin-prettier eslint-config-prettier

    除了安装 eslint外,其他几个是待会用到的依赖,作用分别如下:

    1. eslint-plugin-vue: 使用 ESLint 检查 .vue 文件的 <template><script>
    2. eslint-plugin-prettier:将 Prettier 的规则设置到 ESLint 的规则中。
    3. eslint-config-prettier:关闭 ESLint 中与 Prettier 中会发生冲突的规则。最后形成优先级:Prettier 配置规则 > ESLint 配置规则,代码检查规则顺从格式化规则,也就是以格式化为准。(需要写在配置文件extends最后,这样方便它覆盖其他配置)
  • 项目根目录创建 .eslintrc.cjs 配置文件,配置参数可以参考文档 ELint 配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    // EsLint 代码检查配置:

    module.exports = {
    // 指定本文件为项目根层配置 https://zh-hans.eslint.org/docs/latest/user-guide/configuring/configuration-files#-4
    root: true,
    // 环境配置,指定代码运行环境,提供其预设的全局变量
    env: {
    browser: true,
    node: true,
    es6: true,
    jest: true,
    },
    // 自定义解析器
    // parser: 'esprima',
    // 解析器参数配置
    // parserOptions: {
    // ecmaVersion: 6,
    // sourceType: 'module', // 设置为 script(默认),或者 module(如果你的代码是 ECMAScript 模块)
    // },
    // 插件配置,使用插件为 ESLint 添加各种扩展功能
    plugins: ['vue'],
    // 扩展配置,继承另一个配置文件的所有特征 https://zh-hans.eslint.org/docs/latest/user-guide/configuring/configuration-files#-5
    extends: [
    'plugin:vue/vue3-recommended', // 继承 Vue3 语法检查规范,使用 eslint-plugin-vue 插件提供的规则
    'plugin:prettier/recommended', // 继承 prettier 配置,使用 eslint-plugin-prettier 插件提供的规则
    'prettier', // 禁用 eslint 冲突配置,需要写在extends最后面
    ],
    // 规则配置
    rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    },
    }
  • 最后,可以在项目根目录创建 .eslintignore 文件来忽略对一些内容的规则校验

    1
    2
    3
    4
    5
    # Node modules
    node_modules/

    # pnpm
    pnpm-lock.yaml
  • package.json 文件配置lint脚本检测代码(随项目情况自行修改其中的路径)

    1
    2
    3
    4
    "scripts": {
    "lint:script": "eslint --ext packages/**/* .js,.jsx,.ts,.tsx,.vue --fix",
    "lint": "npm run lint:style && npm run lint:script"
    }
    • --ext选项示指 ESLint 在指定的目录下查找 JavaScript 文件时要使用的文件扩展名
    • --fix选项用来自动修复规则所报告的问题。当使用 extends: "standard" 时会去除所有JS结尾的分号,当rules中添加 semi: ["error", "always"] 时则会补全所有JS结尾的分号。

【参考内容】:

[1] 前端代码格式处理-概述(Prettier + Stylelint + ESlint + Husky + lint-staged + commitlint )

[2] 【☆】项目中 Prettier + Stylelint + ESlint 配置

[3] ESLint 工作原理探讨

[4] 【☆】eslint+prettier+stylelint 集成全流程

[5] 解决 Prettier 和 ESLint 的冲突

[6] ESlint–解析器parser、parserOptions与插件

[7] eslint 使用总结 - 解析器选项 ecmaVersion - 默认设置为 3,5(默认), 你可以使用6、7、8、9、10、11、12 或 13 来指定你想要使用的 ECMAScript 版本。你也可以用使用年份命名的版本号指定为 2015(同6)、2016(同7)、2017(同8)、2018(同9)、2019(同10)、2020(同11)、2021(同 12)或 2022 (同 13) 以使用基于年份的命名。您还可以设置 “latest” 以使用最新支持的版本。

[8] Vue项目之配置 Vite + VSCode 使用EditorConfig, Eslint和Prettier实现代码规范 这里使用 extends 配置项,在它里边定义语法检查规则,这里我们使用之前安装的 eslint-plugin-vue 插件提供的规则,给 extends 配置项提供一个数组,在里边使用 "plugin:vue/vue3-recommended" 配置 Vue3 的语法检查。

[9] 【☆】前端代码规范化实践eslint+prettier+stylelint+editorconfig+commitlint

[10] 2022 Vite vue3 EsLint超简单配置 按步骤完成即可

[11] Eslint该如何配置?Eslint使用以及相关配置说明 Plugins和Extends的区别:简单的说Plugin是声明了一堆规则,此外还需要自己在rules中进行自定义其他规则。而extends(集成),同时具有plugin导入的能力,还引入了自带的规则风格。(Extends看以看作是当前配置对象的功能完备的子集)

[12] css代码规范工具stylelint

[13] stylelint 配置使用 | 阿离王-前端分享

[14] stylelint最佳实践

[15] 2022 Stylelint 配置详细步骤(css、less、sass、vue适用)

[16] vue2项目配置prettier + eslint + commitlint + stylelint

[17] 带你深入了解vscode-eslint插件 若是Vue2使用vetur, Vue3使用Volar。

[18] 前端工程化配置指南 为什么生成的配置文件名称是.eslintrc.cjs而不是.eslintrc.js?

[19] 【☆】原来 peerDependencies 是这么个东东 目的是提示宿主环境去安装满足 peerDependencies 所指定的额外依赖包。总结:peer 这个词翻译过来就是“同龄,同辈”的意思,因此可以理解为:你要想雇用我呀,那你就得把我的兄弟姐妹们也雇上,不然我干不了。在项目中就是:如果你期望在项目中使用这个依赖,那就得把这个依赖的相关依赖都叫上,不然无法运行。

[20] postcss官方文档 PostCSS是CSS语法转换的工具,很多工具如 Stylelint 都是建立在 PostCSS 生态系统之上的。

[21] .editorconfig 文件使用说明

[22] 为什么大多开源项目的.editorconfig总是设置end_of_line=lf而不是 crlf?

[23] 项目创建从editorconfig和prettier开始 基于少数服从多数,lf被更多系统使用,所以这个推荐使用lf作为end_of_line的值。还有一点是现在很多代码服务器或者业务服务器都是linux系统,本地和服务的代码换行符最好一样,以防一些文件字符操作的时候没有兼容