在一个 Vue 项目中,如何实现代码分析和静态检查,例如利用 `ESLint` 和 `SonarQube` 提升代码质量?

大家好,欢迎来到今天的“代码质量提升大法”讲座!今天我们要聊聊怎么在 Vue 项目里玩转代码分析和静态检查,让我们的代码既健壮又漂亮,就像给代码做个全身 SPA!

一、开场白:为什么要给代码做 SPA?

想象一下,你辛辛苦苦写了一堆代码,结果上线之后各种bug冒出来,用户体验差到爆,老板天天催你修复,是不是感觉整个世界都灰暗了?这就是代码质量不高惹的祸!

好的代码就像一个健康的身体,需要定期检查、及时修复问题。代码分析和静态检查就是给代码做的 SPA,帮助我们:

  • 提前发现问题: 在代码提交之前,就能发现潜在的bug、代码风格问题、安全漏洞等。
  • 统一代码风格: 保证团队成员的代码风格一致,提高代码可读性和可维护性。
  • 提高代码质量: 减少bug,提高性能,让代码更健壮。
  • 减少维护成本: 降低后期维护的难度,节省时间和精力。

二、主角登场:ESLint 和 SonarQube

今天的主角是 ESLint 和 SonarQube,它们就像代码界的“神医”,一个擅长“望闻问切”,一个擅长“全面体检”。

  • ESLint: 专注于代码风格和潜在问题的静态检查工具。它可以根据预设的规则,检查代码是否符合规范,例如缩进、空格、命名等。就像一个严格的代码风格警察,时刻监督你的代码。

  • SonarQube: 一个全面的代码质量管理平台。它可以分析代码中的bug、漏洞、代码异味、代码重复率等,并提供详细的报告和改进建议。就像一个专业的体检中心,帮你全面了解代码的健康状况。

三、实战演练:ESLint 的配置与使用

接下来,我们就来实战演练一下,看看如何在 Vue 项目中配置和使用 ESLint。

  1. 安装 ESLint:

    首先,我们需要在项目中安装 ESLint 相关的依赖包。打开你的终端,输入以下命令:

    npm install eslint eslint-plugin-vue --save-dev

    或者使用 yarn:

    yarn add eslint eslint-plugin-vue -D
    • eslint: ESLint 的核心包。
    • eslint-plugin-vue: ESLint 的 Vue 插件,用于检查 Vue 组件中的代码。
    • --save-dev-D: 将这些依赖包安装到开发依赖中。
  2. 初始化 ESLint 配置:

    安装完成后,我们需要初始化 ESLint 的配置文件。在终端中输入以下命令:

    npx eslint --init

    这个命令会引导你创建一个 .eslintrc.js.eslintrc.json 文件,用于配置 ESLint 的规则。按照提示选择适合你项目的配置:

    • How would you like to use ESLint? (选择一种使用方式)
      • To check syntax, find problems, and enforce code style (检查语法、发现问题、强制代码风格)
    • What type of modules does your project use? (选择模块类型)
      • JavaScript modules (import/export) (JavaScript 模块,使用 import/export)
    • Which framework does your project use? (选择框架)
      • Vue.js
    • Does your project use TypeScript? (是否使用 TypeScript)
      • Yes/No (根据你的项目选择)
    • Where does your code run? (代码运行环境)
      • Browser (浏览器)
      • Node (Node.js)
    • How would you like to define a style for your project? (选择一种风格定义方式)
      • Use a popular style guide (使用流行的风格指南)
    • Which style guide do you want to follow? (选择风格指南)
    • What format do you want your config file to be in? (选择配置文件格式)
      • JavaScript
    • Would you like to install them now with npm? (是否立即安装依赖)
      • Yes

    根据你的选择,ESLint 会自动安装相关的插件和依赖包。例如,如果你选择了 Airbnb 风格指南,它会自动安装 eslint-config-airbnb-baseeslint-plugin-import 等依赖。

  3. 配置 ESLint 规则:

    打开 .eslintrc.js 文件,你可以看到 ESLint 的配置信息。例如,一个简单的配置如下:

    module.exports = {
        root: true,
        env: {
            node: true,
        },
        extends: [
            'plugin:vue/vue3-essential',
            'eslint:recommended',
            '@vue/airbnb',
        ],
        parserOptions: {
            parser: 'babel-eslint',
        },
        rules: {
            'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
            'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
            'indent': ['error', 2], // 强制使用两个空格缩进
            'quotes': ['error', 'single'], // 强制使用单引号
            'semi': ['error', 'always'], // 强制使用分号
            'vue/multi-word-component-names': 'off', // 关闭vue文件名称校验
        },
    };
    • root: true: 表示这是 ESLint 的根配置文件,停止在父目录中查找配置文件。
    • env: 指定代码运行的环境,例如 node: true 表示代码运行在 Node.js 环境中。
    • extends: 继承 ESLint 的配置,例如 eslint:recommended 表示使用 ESLint 的推荐规则,@vue/airbnb 表示使用 Vue 的 Airbnb 风格指南。
    • parserOptions: 指定代码解析器,例如 parser: 'babel-eslint' 表示使用 Babel 解析器。
    • rules: 自定义 ESLint 规则。你可以根据自己的需求,修改或添加规则。例如:
      • 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off': 在生产环境中,将 console.log 语句视为警告,否则关闭。
      • 'indent': ['error', 2]: 强制使用两个空格缩进,如果违反规则,则报错。
      • 'quotes': ['error', 'single']: 强制使用单引号,如果违反规则,则报错。
      • 'semi': ['error', 'always']: 强制使用分号,如果违反规则,则报错。
      • 'vue/multi-word-component-names': 'off': 关闭 Vue 组件名称必须是多单词的校验,否则会报错。这个规则在实际开发中可以关闭,因为很多时候组件名称使用单个单词更简洁明了。

    常用的 ESLint 规则:

    规则名称 描述
    no-unused-vars 禁止使用未使用的变量。
    no-console 禁止使用 console.log 等语句。
    no-debugger 禁止使用 debugger 语句。
    indent 强制使用一致的缩进。
    quotes 强制使用一致的引号风格。
    semi 强制使用一致的分号风格。
    eqeqeq 强制使用 ===!== 代替 ==!=
    no-alert 禁止使用 alert 语句。
    no-eval 禁止使用 eval 函数。
    no-implied-eval 禁止使用 setTimeoutsetIntervalexecScript 等函数,因为它们可能会执行字符串形式的代码。
    no-new-func 禁止使用 new Function() 构造函数。
    no-caller 禁止使用 arguments.callerarguments.callee 属性。
    no-iterator 禁止使用 __iterator__ 属性。
    no-proto 禁止使用 __proto__ 属性。
    no-script-url 禁止使用 javascript: URL。
    no-useless-call 禁止使用不必要的 .call().apply()
    no-void 禁止使用 void 操作符。
    no-with 禁止使用 with 语句。
    array-callback-return 强制数组的回调函数必须返回值。
    block-scoped-var 强制在块级作用域中使用变量。
    complexity 限制代码的复杂度。
    consistent-return 强制函数必须始终返回值或始终不返回值。
    default-case switch 语句中强制使用 default 分支。
    for-direction 强制 for 循环的方向正确。
    getter-return 强制 getter 函数必须返回值。
    no-await-in-loop 禁止在循环中使用 await 语句。
    no-compare-neg-zero 禁止与 -0 进行比较。
    no-cond-assign 禁止在条件语句中使用赋值表达式。
    no-constant-condition 禁止使用常量作为条件。
    no-control-regex 禁止在正则表达式中使用控制字符。
    no-dupe-args 禁止在函数定义中使用重复的参数名。
    no-dupe-keys 禁止在对象字面量中使用重复的键名。
    no-duplicate-case 禁止在 switch 语句中使用重复的 case 分支。
    no-empty 禁止使用空的代码块。
    no-empty-character-class 禁止在正则表达式中使用空的字符类。
    no-ex-assign 禁止在 catch 语句中重新赋值异常变量。
    no-extra-boolean-cast 禁止不必要的布尔类型转换。
    no-extra-parens 禁止不必要的括号。
    no-extra-semi 禁止不必要的分号。
    no-fallthrough 禁止 switch 语句的 case 分支没有 break 语句。
    no-func-assign 禁止重新赋值函数声明。
    no-global-assign 禁止修改只读的全局变量。
    no-inner-declarations 禁止在嵌套的代码块中使用变量或函数声明。
    no-invalid-regexp 禁止在 RegExp() 构造函数中使用无效的正则表达式。
    no-irregular-whitespace 禁止使用不规则的空白字符。
    no-loop-func 禁止在循环中创建函数。
    no-multi-spaces 禁止使用多个空格。
    no-new 禁止使用 new 关键字但没有赋值给变量。
    no-new-wrappers 禁止使用 String()Number()Boolean() 构造函数。
    no-obj-calls 禁止将全局对象作为函数调用,例如 Math()JSON()
    no-octal 禁止使用八进制字面量。
    no-param-reassign 禁止重新赋值函数参数。
    no-redeclare 禁止重复声明变量。
    no-regex-spaces 禁止在正则表达式中使用多个空格。
    no-return-assign 禁止在 return 语句中使用赋值表达式。
    no-return-await 禁止不必要的 await 语句。
    no-self-assign 禁止将变量赋值给自己。
    no-self-compare 禁止将变量与自身进行比较。
    no-sequences 禁止使用逗号运算符。
    no-shadow 禁止变量声明覆盖外部作用域中的变量。
    no-shadow-restricted-names 禁止使用保留字作为变量名。
    no-sparse-arrays 禁止使用稀疏数组。
    no-template-curly-in-string 禁止在普通字符串中使用模板字面量占位符。
    no-throw-literal 禁止抛出字面量作为异常。
    no-undef 禁止使用未声明的变量。
    no-undef-init 禁止将变量初始化为 undefined
    no-undefined 禁止使用 undefined 变量。
    no-unmodified-loop-condition 禁止在循环中没有修改的循环条件。
    no-unneeded-ternary 禁止不必要的三元运算符。
    no-unreachable 禁止在 returnthrowcontinuebreak 语句之后出现不可达的代码。
    no-unsafe-finally 禁止在 finally 代码块中使用控制语句,例如 returnthrowbreakcontinue
    no-unused-expressions 禁止使用未使用的表达式。
    no-unused-labels 禁止使用未使用的标签。
    no-useless-computed-key 禁止使用不必要的计算属性键名。
    no-useless-concat 禁止不必要的字符串拼接。
    no-useless-constructor 禁止不必要的构造函数。
    no-useless-escape 禁止不必要的转义字符。
    no-useless-rename 禁止不必要的重命名。
    no-var 强制使用 letconst 代替 var
    no-whitespace-before-property 禁止在对象属性之前出现空白。
    nonblock-statement-body-position 强制单行语句的位置。
    object-curly-newline 强制大括号内的换行符。
    object-curly-spacing 强制大括号内的空格。
    object-property-newline 强制对象属性的换行符。
    one-var 强制每个作用域中只声明一个变量。
    operator-linebreak 强制操作符的换行符。
    padded-blocks 强制代码块的填充。
    padding-line-between-statements 强制语句之间的填充。
    prefer-const 建议使用 const 声明那些声明后不再被修改的变量。
    prefer-destructuring 建议使用解构赋值。
    prefer-numeric-literals 建议使用数字字面量。
    prefer-promise-reject-errors 建议使用 Error 对象作为 Promise 的拒绝原因。
    quote-props 强制对象字面量属性名称的引号风格。
    radix 强制使用 parseInt() 函数时指定基数。
    require-await 建议在异步函数中使用 await 语句。
    require-unicode-regexp 建议在正则表达式中使用 Unicode 模式。
    sort-imports 强制导入语句的排序。
    sort-keys 强制对象键的排序。
    sort-vars 强制变量声明的排序。
    space-before-blocks 强制在块之前使用空格。
    space-before-function-paren 强制在函数括号之前使用空格。
    space-in-parens 强制在括号内使用空格。
    space-infix-ops 强制在操作符周围使用空格。
    space-unary-ops 强制在一元操作符之前或之后使用空格。
    spaced-comment 强制注释的间距。
    strict 强制使用严格模式。
    symbol-description 强制 Symbol 必须有一个描述。
    template-curly-spacing 强制在模板字面量占位符中使用空格。
    unicode-bom 强制使用 Unicode BOM。
    vars-on-top 强制将变量声明放在作用域顶部。
    wrap-iife 强制将立即执行函数表达式 (IIFE) 包装在括号中。
    wrap-regex 强制将正则表达式包装在括号中。
    yoda 强制使用 Yoda 条件。

    Vue 相关的 ESLint 规则:

    规则名称 描述
    vue/no-dupe-keys 禁止在 Vue 组件中使用重复的键名。
    vue/no-duplicate-attributes 禁止在 Vue 组件中使用重复的属性。
    vue/no-parsing-error 禁止在 Vue 组件中使用解析错误。
    vue/no-reserved-keys 禁止在 Vue 组件中使用保留的键名。
    vue/no-shared-component-data 禁止在 Vue 组件中使用共享的组件数据。
    vue/no-side-effects-in-computed-properties 禁止在计算属性中使用副作用。
    vue/no-template-key 禁止在 template 标签中使用 key 属性。
    vue/no-textarea-mustache 禁止在 textarea 标签中使用插值表达式。
    vue/no-unused-components 禁止在 Vue 组件中使用未使用的组件。
    vue/no-unused-vars 禁止在 Vue 组件中使用未使用的变量。
    vue/script-setup-uses-vars 防止 <script setup> 中使用的变量被标记为未使用。
    vue/require-prop-types 强制 Vue 组件必须声明 props 的类型。
    vue/require-render-return 强制 Vue 组件的 render 函数必须返回值。
    vue/require-v-for-key 强制在使用 v-for 指令时必须指定 key 属性。
    vue/return-in-computed-property 强制计算属性必须返回值。
    vue/valid-template-root 强制 Vue 组件的 template 必须有一个根元素。
    vue/valid-v-bind 强制 v-bind 指令必须是有效的。
    vue/valid-v-cloak 强制 v-cloak 指令必须是有效的。
    vue/valid-v-else 强制 v-else 指令必须是有效的。
    vue/valid-v-else-if 强制 v-else-if 指令必须是有效的。
    vue/valid-v-for 强制 v-for 指令必须是有效的。
    vue/valid-v-html 强制 v-html 指令必须是有效的。
    vue/valid-v-if 强制 v-if 指令必须是有效的。
    vue/valid-v-model 强制 v-model 指令必须是有效的。
    vue/valid-v-on 强制 v-on 指令必须是有效的。
    vue/valid-v-once 强制 v-once 指令必须是有效的。
    vue/valid-v-pre 强制 v-pre 指令必须是有效的。
    vue/valid-v-show 强制 v-show 指令必须是有效的。
    vue/valid-v-slot 强制 v-slot 指令必须是有效的。
    vue/attribute-hyphenation 强制 HTML 属性的连字符风格。
    vue/html-closing-bracket-newline 强制 HTML 闭合括号的换行符。
    vue/html-end-tags 强制 HTML 结束标签。
    vue/html-indent 强制 HTML 缩进。
    vue/max-attributes-per-line 限制每行 HTML 属性的数量。
    vue/mustache-interpolation-spacing 强制插值表达式的空格。
    vue/no-multi-spaces 禁止使用多个空格。
    vue/prop-name-casing 强制 prop 名称的命名风格。
    vue/singleline-html-element-content-newline 强制单行 HTML 元素内容的换行符。
    vue/v-bind-style 强制 v-bind 指令的风格。
    vue/v-on-style 强制 v-on 指令的风格。
    vue/attributes-order 强制属性的顺序。
    vue/order-in-components 强制组件的顺序。
    vue/this-in-template 强制在模板中使用 this 关键字。
  4. 运行 ESLint:

    配置完成后,你就可以在终端中运行 ESLint 来检查你的代码了。在 package.json 文件中添加一个 script:

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

    然后运行以下命令:

    npm run lint

    或者使用 yarn:

    yarn lint

    ESLint 会检查 src 目录下所有 .js.vue 文件,并输出检查结果。

  5. 集成到 IDE:

    为了更方便地使用 ESLint,你可以将其集成到你的 IDE 中。例如,在 VS Code 中,你可以安装 ESLint 插件,它可以实时检查你的代码,并在编辑器中显示错误和警告。

四、SonarQube 的配置与使用

接下来,我们来看看如何在项目中配置和使用 SonarQube。

  1. 安装 SonarQube:

    首先,你需要下载并安装 SonarQube 服务器。你可以从 SonarQube 官网下载最新版本的 SonarQube:https://www.sonarqube.org/downloads/

    下载完成后,解压到你想要安装的目录,然后按照官网的说明启动 SonarQube 服务器。

  2. 安装 SonarScanner:

    SonarScanner 是一个命令行工具,用于将代码分析结果发送到 SonarQube 服务器。你需要下载并安装 SonarScanner:https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/

    下载完成后,解压到你想要安装的目录,并将 SonarScanner 的 bin 目录添加到你的环境变量中。

  3. 配置 SonarQube:

    启动 SonarQube 服务器后,你需要登录 SonarQube 管理界面(默认地址是 http://localhost:9000,默认用户名和密码是 admin/admin)。

    • 创建项目: 在 SonarQube 管理界面中,创建一个新的项目。
    • 生成 Token: 为项目生成一个 Token,用于 SonarScanner 的身份验证。
  4. 配置 SonarScanner:

    在你的 Vue 项目根目录下创建一个 sonar-project.properties 文件,用于配置 SonarScanner。例如:

    sonar.projectKey=my-vue-project
    sonar.projectName=My Vue Project
    sonar.projectVersion=1.0
    sonar.sources=src
    sonar.sourceEncoding=UTF-8
    sonar.javascript.linter.eslint.reportPaths=eslint-report.json
    sonar.exclusions=**/node_modules/**
    • sonar.projectKey: 项目的唯一标识符。
    • sonar.projectName: 项目的名称。
    • sonar.projectVersion: 项目的版本。
    • sonar.sources: 源代码的目录。
    • sonar.sourceEncoding: 源代码的编码。
    • sonar.javascript.linter.eslint.reportPaths: ESLint 报告的路径。
    • sonar.exclusions: 需要排除的目录或文件

发表回复

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