JS `Static Analysis` (静态分析) 工具链的构建与自定义规则

各位观众老爷们,早上好/中午好/晚上好! 今天咱们来聊聊JS静态分析这档子事儿,以及如何打造一套属于你自己的、充满个性的代码质量管家。

开场白:为啥要搞静态分析?

想象一下,你吭哧吭哧写了一堆JS代码,信心满满地准备上线,结果…炸了!控制台里红彤彤的一片,用户疯狂吐槽。 这种酸爽,相信不少老铁都体验过。 静态分析就像一个先知,在代码还没运行之前,就能帮你揪出潜在的Bug、代码风格问题、安全隐患等等。 它可以有效减少上线后的故障率,提升代码质量,解放你的Debug时间,让你有更多时间摸鱼…哦不,是学习新知识!

第一章:JS静态分析工具链概览

市面上JS静态分析工具琳琅满目,各有千秋。 咱们先简单过一遍常见的几个:

工具名称 主要功能 优势 劣势
ESLint 代码风格检查、潜在错误检测、可扩展性强 可定制性高,规则丰富,社区活跃,支持各种流行的JS框架 配置复杂,学习曲线稍陡峭
JSHint 代码风格检查、潜在错误检测 简单易用,配置相对简单 功能相对ESLint较弱,可定制性较低
JSLint 代码风格检查、潜在错误检测 规则严格,有助于养成良好的编码习惯 规则过于严格,可能导致大量误报,不适合所有项目
TypeScript 类型检查、代码风格检查、潜在错误检测 静态类型检查,更早发现类型错误,代码可读性、可维护性更强 需要引入TypeScript语法,学习成本较高,编译过程增加
SonarQube 代码质量管理平台,包含静态分析、代码覆盖率、安全漏洞等 功能强大,可以进行全面的代码质量管理,支持多种语言 部署和配置较为复杂,需要一定的资源
Prettier 代码格式化 自动格式化代码,保持代码风格一致,减少Code Review成本 只能进行代码格式化,无法进行代码质量检查

这些工具通常会组合使用,形成一个完整的静态分析工具链。 比如,你可以用ESLint进行代码风格检查和潜在错误检测,用Prettier进行代码格式化,用TypeScript进行类型检查。

第二章:ESLint:你的代码质量管家

ESLint是JS静态分析领域的扛把子,拥有强大的可定制性和丰富的规则。 咱们重点讲讲ESLint。

2.1 安装和配置

首先,你需要安装ESLint:

npm install eslint --save-dev

或者

yarn add eslint --dev

然后,初始化ESLint配置:

npx eslint --init

这个命令会引导你创建一个.eslintrc.js.eslintrc.yaml、或者.eslintrc.json文件,用于配置ESLint规则。 你可以选择使用预设的规则集(比如Airbnb、Google、Standard),也可以自定义规则。

一个典型的.eslintrc.js文件可能长这样:

module.exports = {
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "plugins": [
    "react",
    "@typescript-eslint"
  ],
  "rules": {
    "no-unused-vars": "warn",
    "no-console": "warn",
    "react/prop-types": "off",
    "@typescript-eslint/explicit-function-return-type": "off"
  }
};

这里解释一下几个重要的配置项:

  • env: 指定代码运行的环境,比如browsernode
  • extends: 继承预设的规则集,可以继承多个。
  • parser: 指定代码解析器,比如@typescript-eslint/parser用于解析TypeScript代码。
  • parserOptions: 配置解析器选项,比如ecmaVersion指定ECMAScript版本,sourceType指定模块类型。
  • plugins: 使用插件,比如react插件用于检查React代码。
  • rules: 自定义规则,可以覆盖预设的规则。 规则的值可以是:
    • "off"0: 禁用规则。
    • "warn"1: 启用规则,但只发出警告。
    • "error"2: 启用规则,并发出错误。

2.2 常用规则

ESLint内置了大量的规则,涵盖代码风格、潜在错误、最佳实践等方面。 这里列举一些常用的规则:

  • no-unused-vars: 禁止未使用的变量。
  • no-console: 禁止使用console.log
  • no-debugger: 禁止使用debugger语句。
  • eqeqeq: 强制使用===!==,而不是==!=
  • quotes: 强制使用一致的引号风格(单引号或双引号)。
  • semi: 强制使用分号。
  • indent: 强制使用一致的缩进。
  • camelcase: 强制使用驼峰命名法。
  • max-len: 限制每行代码的最大长度。
  • complexity: 限制函数的复杂度。

2.3 集成到构建流程

为了让ESLint在开发过程中发挥作用,你需要将它集成到你的构建流程中。 常见的做法是使用npm scripts或者webpack插件。

package.json中添加一个lint脚本:

{
  "scripts": {
    "lint": "eslint src/**/*.js"
  }
}

然后,运行npm run lint或者yarn lint就可以检查代码了。

如果你使用webpack,可以使用eslint-webpack-plugin插件:

const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  // ...
  plugins: [
    new ESLintPlugin({
      extensions: ['js', 'jsx', 'ts', 'tsx'],
    }),
  ],
};

这样,每次构建代码时,ESLint都会自动检查代码。

第三章:自定义ESLint规则:打造你的专属代码质量管家

ESLint的强大之处在于它的可扩展性。 你可以根据自己的需求,自定义ESLint规则,检查特定的代码模式。

3.1 规则结构

一个ESLint规则通常包含以下几个部分:

  • meta: 包含规则的元数据,比如规则的描述、类型、修复方法等。
  • create: 一个函数,接收context对象作为参数,返回一个对象,包含一系列选择器,用于指定要检查的代码节点。

3.2 示例:禁止使用alert

咱们来写一个简单的规则,禁止使用alert函数。

// custom-rules/no-alert.js
module.exports = {
  meta: {
    type: 'problem', // 规则类型:problem、suggestion、layout
    docs: {
      description: '禁止使用alert',
      category: 'Possible Errors',
      recommended: 'error', // 推荐级别:off、warn、error
    },
    fixable: null, // 是否可自动修复:null、code
    schema: [], // 规则选项的JSON Schema
  },
  create: function(context) {
    return {
      CallExpression(node) {
        if (node.callee.name === 'alert') {
          context.report({
            node,
            message: '禁止使用alert',
          });
        }
      },
    };
  },
};

这个规则很简单:

  • meta.type指定规则类型为problem,表示这是一个潜在的错误。
  • meta.docs.description描述了规则的功能。
  • meta.docs.recommended指定推荐级别为error,表示应该将这个规则视为错误。
  • create函数返回一个对象,包含一个CallExpression选择器。 CallExpression表示函数调用表达式。
  • 当ESLint遇到一个函数调用表达式时,会执行CallExpression选择器对应的函数。
  • 如果函数调用的是alert函数,就调用context.report方法,报告一个错误。

3.3 使用自定义规则

要使用自定义规则,你需要做以下几步:

  1. 将规则文件放在一个目录下,比如custom-rules
  2. .eslintrc.js文件中,配置pluginsrules
module.exports = {
  // ...
  "plugins": [
    "custom-rules"
  ],
  "rules": {
    "custom-rules/no-alert": "error"
  },
  "settings": {
    "import/resolver": {
      "node": {
        "paths": ["custom-rules"]
      }
    }
  }
};

这里,plugins数组添加了custom-rules,ESLint会自动加载custom-rules目录下的所有规则。 rules对象配置了custom-rules/no-alert规则,并将其级别设置为error

3.4 进阶:自动修复

ESLint还支持自动修复代码。 要实现自动修复,需要在meta对象中设置fixable属性为code,并在context.report方法中提供一个fix函数。

咱们来修改一下no-alert规则,使其可以自动将alert替换为console.log

// custom-rules/no-alert.js
module.exports = {
  meta: {
    type: 'problem',
    docs: {
      description: '禁止使用alert,并替换为console.log',
      category: 'Possible Errors',
      recommended: 'error',
    },
    fixable: 'code', // 设置为code,表示可以自动修复
    schema: [],
  },
  create: function(context) {
    return {
      CallExpression(node) {
        if (node.callee.name === 'alert') {
          context.report({
            node,
            message: '禁止使用alert,请使用console.log',
            fix: function(fixer) {
              return fixer.replaceText(node.callee, 'console.log'); // 使用fixer.replaceText替换代码
            },
          });
        }
      },
    };
  },
};

这里,meta.fixable设置为code,表示这个规则可以自动修复。 context.report方法增加了一个fix函数,接收一个fixer对象作为参数。 fixer对象提供了一系列方法,用于修改代码。 这里使用fixer.replaceText方法,将alert替换为console.log

运行eslint --fix src/**/*.js就可以自动修复代码了。

第四章:结合Prettier:代码风格的完美统一

Prettier是一个代码格式化工具,可以自动格式化代码,保持代码风格一致。 将ESLint和Prettier结合使用,可以实现代码质量和代码风格的完美统一。

4.1 安装和配置

首先,你需要安装Prettier:

npm install prettier --save-dev

或者

yarn add prettier --dev

然后,创建一个.prettierrc.js文件,用于配置Prettier选项:

module.exports = {
  semi: false, // 不使用分号
  singleQuote: true, // 使用单引号
  trailingComma: 'all', // 尽可能使用尾逗号
  printWidth: 120, // 每行最大长度
  tabWidth: 2, // 缩进使用2个空格
};

4.2 集成到ESLint

为了让ESLint和Prettier协同工作,你需要安装以下几个插件:

npm install eslint-plugin-prettier eslint-config-prettier --save-dev

或者

yarn add eslint-plugin-prettier eslint-config-prettier --dev

然后,修改.eslintrc.js文件:

module.exports = {
  // ...
  "extends": [
    // ...
    "plugin:prettier/recommended" // 添加prettier插件
  ],
  "rules": {
    // ...
  }
};

这里,extends数组添加了plugin:prettier/recommended,这个插件会自动禁用ESLint中与Prettier冲突的规则。

现在,运行eslint --fix src/**/*.js,ESLint会自动调用Prettier格式化代码。

第五章:其他静态分析工具

除了ESLint和Prettier,还有一些其他的静态分析工具,可以帮助你提高代码质量。

  • Stylelint: 用于检查CSS代码风格。
  • commitlint: 用于检查Git提交信息是否符合规范。
  • husky: 用于在Git hooks中运行静态分析工具。

总结

静态分析是提高代码质量的重要手段。 通过使用ESLint、Prettier等工具,你可以及早发现潜在的Bug、代码风格问题,并自动修复代码。 结合自定义ESLint规则,你可以打造一套属于你自己的、充满个性的代码质量管家,让你的代码更加健壮、可维护。

希望今天的讲座对你有所帮助! 咱们下次再见! (挥手)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注