模块化开发与规范化标准-笔记

125 阅读7分钟

规范化是我们践行前端工程化中的重要一部分。主要说说为什么要有规范化标准、哪些地方需要规范化、如何实施规范化。

为什么有标准

软件开发需要多人协同,但是不同的人会有各自的开发喜好和习惯,如果同一项目不做规范约束,没有统一的标准则会增加项目维护成本,所以每个项目或团队都需要有明确统一的规范化标准。

哪里需要规范化

一般来说只要是人为编写的成果物都需要规范化,比如代码、文档、提交日志。代码的标准化是最重要的,因为它决定了代码质量和可维护性。

实施规范化的方法

最初比较简单,就是在编码前进行人为的进行标准约定,在code review环节根据约定去进行检查,但这样的方式效率太低,也不全面,不可靠,开发人员也不能记住所有的规范。

所以就出现了Lint工具,配合自动化工具还可以自动检查。Lint名称是起源于C语言的编译前的一款叫Lint的检查工具。

ESLint介绍

它是最为主流的JavaScript Lint工具,用来检测代码的质量和规范,通过它可以很容易去统一编码规范。同时它还可以去检测代码中很多潜在不合理的地方,比如使用未定义变量、声明变量前使用、两等符号,帮我们提高代码质量。通过规范的约束,ESLint也可以帮助开发者提高编码能力。

开始使用

梳理一下操作步骤:

  • 初始化项目
  • 安装ESLint模块为开发依赖
  • 通过CLI命令验证开发结果

安装、配置ESLint

yarn add eslint --dev // 安装

yarn eslint --init // 初始化eslint配置文件

yarn eslint 文件路径 // 校验文件,可以写为通配符形式

ESLint的env属性

详细属性表和说明如下表所示,并且在env属性中可以配置多项。

ESLint的extend属性

用于继承一些公共的配置,接收一个数组。使用它需要遵守对应的语法规则,内部元素可以直接定义包名,也可以按照plugin形式定义插件包下导出的公共配置。比如:

extends: [
  'plugin:react/recommended', // 公共配置
  'standard'
],

ESLint的configs属性

用于定义公共的规则配置,在外部可以通过plugin:插件名/配置名的方式进行继承。

{
  configs: {
    recommended: {
      plugins: [
        'react'
      ],
      parserOptions: {
        ecmaFeatures: {
          jsx: true
        }
      },
      rules: {
        'react/display-name': 2,
        'react/jsx-key': 2,
      }
    },
    all: {
      plugins: [
        'react'
      ],
      parserOptions: {
        ecmaFeatures: {
          jsx: true
        }
      },
      rules: activeRulesConfig
    },
    'jsx-runtime': {
      plugins: [
        'react'
      ],
      parserOptions: {
        ecmaFeatures: {
          jsx: true
        }
      },
      rules: {
        'react/react-in-jsx-scope': 0,
        'react/jsx-uses-react': 0
      }
    }
  }
}

ESLint的parserOptions属性

设置语法解析器的相关配置,主要是控制使用哪个版本的ES语法标准。并且env所配置的语法标准优先级是高于该属性的。

ESLint的rules属性

配置ESLint中各种语法校验的规则:是否开启;配置校验选项;以及以何种形式进行报错,可选属性为:off、warn、error

// 展示部分配置示例
{
  "rules": {
      "no-var": "warn",

      "accessor-pairs": ["error", { "setWithoutGet": true, "enforceForClassMembers": true }],
      "array-bracket-spacing": ["error", "never"],
      "array-callback-return": ["error", {
        "allowImplicit": false,
        "checkForEach": false
      }],
      "arrow-spacing": ["error", { "before": true, "after": true }]
  }
}

ESLint的globals属性

额外的声明在代码中可访问的全局成员:

{
  globals: {
    'jQuery': 'readonly'
  }
}

ESLint的plugins属性

接受一个数组,用于配置eslint相关插件,比如eslint-plugin-react。在extend中如果继承了对应的配置,就不必要在这重复配置了。

ESLint的paser属性

配置语法解析器,在ts项目中能使用到:

parser: '@typescript-eslint/parser'

配置注释

在一般的开发过程中,代码肯定存在某些情况不能使用所配置的规范,我们也不能因为这些情况去更改我们的整个规范配置,所以就要用到配置注释,它可以将某行或某个文件的规范失效掉,从而不会报出规范检查错误。

// eslint-disable-line
直接注释失效整行代码

// eslint-disable-line no-template-curly-in-string
可以指定失效更具体的规范配置

// eslint-disable-line no-template-curly-in-string, quotes
禁用多个规范配置

以上所说属性,更详细的配置可以去官方文档上去查看。

ESLint结合Gulp

首先需要在项目中安装eslinteslint-gulp两个依赖模块,然后通过yarn eslint --init初始化一份ESLint配置。在将所有依赖都下下来后,在gulpfile.js文件中对ESLint进行配置,我们仅在处理JS的任务中加入ESLint插件:

// gulpfile.js

const script = () => {
  return src('src/assets/scripts/*.js', { base: 'src' })
    .pipe(plugins.eslint()) // 配置插件
    .pipe(plugins.eslint.format()) // 负责打印错误信息
    .pipe(plugins.eslint.failAfterError()) // 检查到错误信息终止任务管道
    .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
    .pipe(dest('temp'))
    .pipe(bs.reload({ stream: true }))
}

我们需要在管道最开始的地方配置eslint插件,不然经过babel转化后,就不是原始的代码了。

这里发现最新版本eslint-config-standardeslint-gulp是不兼容的,解决方法是要去除es2021这个关键字,并且发现降低版本到14.1.1好像也没有用。

ESLint结合Webpack

Webpack结合ESlint检查,是通过loader机制,而不是plugin机制。接入的方式也和Gulp差不多,首先安装好eslinteslint-loader等依赖,然后初始化一个.eslintrc.js文件,继续安装对应的eslint依赖,然后在webpack.config.js文件中配置eslint。

module: {
  rules: [
    // 方式一
    {
      test: /.js$/,
      exclude: /node_modules/,
      use: ['babel-loader', 'eslint-loader'],
    },
    
    // 方式二
    {
      enforce: 'pre',
      test: /.js$/,
      exclude: /node_modules/,
      loader: 'eslint-loader'
    },
  ]
}

enforce配置为pre是为了在第一个使用该loader,详细解释可以查看官方文档

在webpack中,eslint结合happypack的场景,会发生reduce undefined报错,最终发现解决办法是需要在happypack的插件配置中加入loaders属性,在这定义要用到的loader

现代化项目集成ESLint

随着前端React、Vue框架的普及,它们的生态已经非常好了。这里以Vue来举例,在这里可以直接使用vue-cli来生成一个Vue项目,我们手动进行交互配置,这里有一条问题值得注意,说的是何时使用lint进行检查:

 Lint on save // 在webpack监视模式下,每当监听到文件修改,就触发一次lint
 Lint and fix on commit // 这里是配合git hook,在git提交前进行lint并且fix修复

TypeScript结合ESLint

使用eslint直接初始化

StyleLint介绍

对于css代码一般使用StyleLint进行规范检查,它提供了:

  • 默认的代码检查规则
  • CLI工具,可以快速调用
  • 通过插件,可支持Less、Sass、PostCss等衍生css语法的检查
  • 支持Gulp和Webpack集成

使用方法:

stylelint作为开发依赖安装到项目中,针对Less、Sass、PostCss安装不同的插件进行支持:

  • stylelint-config-sass-guidelines
  • stylelint-config-standard

配置.styleintrc.js文件来配置语法检查规则:

module.exports = {
    extends: ["stylelint-config-standard", "stylelint-config-sass-guidelines"]
}

可以关注下Less相关插件,StyleLint集成入webpack、Gulp,以及HTML等的Lint工具。

HTML Lint工具有这么些:Bootlint、AriaLinter、htmllint、HTMLHint 及htmlcs。

配合Webpack、Gulp:我们可以使用stylelint-webpack-plugin插件配合Webpack,使用gulp-stylelint配合Gulp,Npm文档链接:gulp-stylelintstylelint-webpack-plugin

stylelint的stylelint-config-standard插件,已支持对less的语法检查

Prettier

前端代码规范化工具。

使用方法:

  • 将prettier作为开发依赖在项目中进行安装
  • 通过yarn prettier ./style.css --write将格式化后代码写入文件中
  • 通过yarn prettier . --write格式化文件目录下所有文件

Git Hooks

团队开发中,开发成员可能忘记进行Lint,那么可以使用Git Hooks在代码提交前进行强制的Lint操作。以下是关于它的相关介绍:

  • Git Hook也称之为git钩子,每个钩子对应一个任务
  • 通过shell脚本可以编写钩子任务触发时要具体执行的操作

在每一个git仓库中,都会有一个.git文件夹,它里边就有git hook的示例,我们可以基于它去编写:

简单的说,GitHooks就是通过钩子来对应具体的Git操作,当这个操作执行时就自动的执行钩子内定义的任务。但是对于Shell脚本很多前端开发人员并不会写,所以有了Husky这个简化工具,实现对Git Hooks的需求。

husky的功能会有些短板,配合lint-staged工具可以补足它的不足。