【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

内容分享11小时前发布
0 0 0

问题描述:

在前端工程化的道路上,Husky + lint-staged + ESLint 是保证代码质量的“黄金三角”。但是配置好后,执行 git commit 命令 却失败了,并且明明在 eslint.config.js文件 中关闭了 no-undef 规则,ESLint 却依然报错。

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

分析原因:

一切始于一个简单的 git commit 操作。终端输出了如下错误信息:

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

核心矛盾点:明明在 eslint.config.js文件 中写着 'no-undef': 'off',为什么 ESLint 视而不见?

排查问题如下:

 第一步:排除外部干扰,锁定内部问题

既然使用的不是旧版 .eslintrc.js,那么 package.json 中的 eslintConfig 冲突自然不存在。同时,手动执行 npx eslint –fix src/main.js 也能复现问题。

结论:问题出现在 eslint.config.js 文件内部。
 

第二步:审视配置

在自己的  eslint.config.js 文件 发现结构混乱。自定义的 rules 对象放在了最前面,而 js.configs.recommended 等预设配置却放在了后面。

这意味着:

ESLint 首先加载了我的 { rules: { 'no-undef': 'off' } }。然后,它加载了 js.configs.recommended,这个预设内部包含了 { rules: { 'no-undef': 'error' } }。后面的配置覆盖了前面的!自己辛辛苦苦设置的 'off' 就这样被无情地覆盖了。

结论:不是自己的配置没生效,而是它生效了,但 立刻被后面的预设配置给覆盖了。
 

关键知识点:ESLint 9.x 引入了一个重大变革——它默认采用新的“Flat Config”格式(eslint.config.js),而不再自动支持旧版的 .eslintrc.js 文件。且 Flat Config 的一个核心原则是“数组中的配置对象按顺序合并,后面的会覆盖前面的!”
 

解决办法:

重构 Flat Config,建立秩序

找到了根源,解决方法就是 重新组织配置数组的顺序,并清理冗余。

清理 Prettier 配置:只保留 eslintConfigPrettier,这是最标准的做法。调整配置顺序:将预设配置(js.configs.recommended 等)放在前面,自定义配置放在最后,确保自定义规则拥有最高优先级。合并自定义规则:将所有 rules 集中到一个配置对象中。

最终,一个健壮、清晰的 eslint.config.js 诞生了。

原 eslint.config.js 代码:



import globals from 'globals'
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
 
import eslintConfigPrettier from '@vue/eslint-config-prettier' //添加这一行代码
 
export default [
  {
    name: 'app/files-to-lint',
    files: ['**/*.{js,mjs,jsx,vue}'],
 
    // rules添加到这里,上面写的该规则应用于js,mjs,jsx,vue
    rules: {
      'prettier/prettier': [
        'warn',
        {
          singleQuote: true, // 单引号
          semi: false, // 无分号
          printWidth: 100, // 每行宽度至多100字符
          trailingComma: 'none', // 不加对象|数组最后逗号
          endOfLine: 'auto' //换行符号不限制(win mac 不一致)
        }
      ],
      // vue组件名称多单词组成(忽略index.vue)
      'vue/multi-word-component-names': ['warn', { ignores: ['index'] }],
      // 关闭 props 解构的校验
      'vue/no-setup-props-destructure': ['off'],
      // 💡 添加未定义变量错误提示,create-vue@3.6.3 关闭,这里加上是为了支持下一个章节演示。
      'no-undef': 'off'  //这里是为了 测试 lint-staged 将 error 改为 off
    }
  },
 
  {
    name: 'app/files-to-ignore',
    ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
    //rules添加到这里
    rules: {
      'prettier/prettier': [
        'warn',
        {
          singleQuote: true,
          semi: false,
          printWidth: 100,
          trailingComma: 'none',
          endOfLine: 'auto'
        }
      ],
      'vue/multi-word-component-names': ['warn', { ignores: ['index'] }],
      'vue/no-setup-props-destructure': ['off'],
      'no-undef': 'off'  // 这里是为了 测试 lint-staged 将 error 改为 off
    }
  },
 
  {
    languageOptions: {
      globals: {
        ...globals.browser
      }
    }
  },
 
  js.configs.recommended,
  ...pluginVue.configs['flat/essential'],
  skipFormatting,
  eslintConfigPrettier //添加这一行代码
]

问题一:重复的 Prettier 配置(严重问题)

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

同时引入了两个 Prettier 相关的配置:

skipFormatting (来自 @vue/eslint-config-prettier/skip-formatting)eslintConfigPrettier (来自 @vue/eslint-config-prettier)

这是错误的!

eslintConfigPrettier 的作用是 禁用所有与 Prettier 冲突的 ESLint 规则。

skipFormatting 的作用是 完全禁用 prettier/prettier 规则,只保留冲突禁用的功能。

同时使用两者会导致混乱。只能选择一个。

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

问题二:配置结构不合理(关键问题)

原 eslint.config.js 文件配置结构是混乱的,将自定义规则和预设配置(js.configs.recommended等)分开放置。在 Flat Config 中,数组的顺序非常重要,后面的配置会覆盖前面的。

一个更清晰、更不容易出错的写法是:

先定义全局配置(如 ignores)。然后按顺序应用各种预设配置(js.configs.recommended, pluginVue.configs 等)。最后,在数组的末尾添加自己的自定义规则,这样可以确保你的规则具有最高优先级,能覆盖预设中的规则。
 

原 eslint.config.js 文件:

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

 问题三:rules 重复定义

原 eslint.config.js 文件在两个不同的配置对象里都定义了完全相同的 rules。这是不必要的,并且容易导致维护困难。应该将所有自定义规则统一放在一个地方。

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

问题四:缺少 globals 依赖

原 eslint.config.js 文件使用了 import globals from 'globals',虽然 由项目中 package.json文件知,globals 包是已安装的(自己看自己项目),但需要确保它被正确地应用到了 languageOptions 中。

修正后的写法:



// eslint.config.js
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import globals from 'globals'
import eslintConfigPrettier from '@vue/eslint-config-prettier'
 
export default [
  // 1. 全局忽略文件(必须放在最前面)
  {
    name: 'app/files-to-ignore',
    ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**']
  },
 
  // 2. 应用 ESLint 官方推荐规则
  js.configs.recommended,
 
  // 3. 应用 Vue 插件的推荐规则
  ...pluginVue.configs['flat/essential'],
 
  // 4. 应用 Prettier 配置,禁用冲突规则(必须放在最后)
  eslintConfigPrettier,
 
  // 5. 你的项目自定义配置(放在最后,优先级最高)
  {
    name: 'app/custom-rules',
    files: ['**/*.{js,mjs,jsx,vue}'], // 指定文件范围
    languageOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
      globals: {
        ...globals.browser // 注入浏览器全局变量
      }
    },
    rules: {
      // 在这里集中定义所有自定义规则
      'prettier/prettier': [
        'warn',
        {
          singleQuote: true, //单引号
          semi: false, // 无分号
          printWidth: 100, // 每行宽度至多100字符
          trailingComma: 'none', // 不加对象|数组最后逗号
          endOfLine: 'auto' //换行符号不限制(win mac 不一致)
        }
      ],
      // vue组件名称多单词组成(忽略index.vue)
      'vue/multi-word-component-names': ['warn', { ignores: ['index'] }],
      // 关闭 props 解构的校验,prop解构会影响响应式
      'vue/no-setup-props-destructure': 'off',
      // 💡 添加未定义变量错误提示,create-vue@3.6.3 关闭,这里加上是为了支持下一个章节演示。
      'no-undef': 'off' //这里是为了 测试 lint-staged 将 error 改为 off,测试完记得改回error
    }
  }
]

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

主要修改点说明

只保留 eslintConfigPrettier:这是最标准的选择,它会确保 Prettier 的格式化规则与 ESLint 的规则不冲突,同时保留 prettier/prettier 规则来检查代码风格。优化了配置顺序:ignores 在前,然后是预设配置,最后是自定义规则。这是 Flat Config 的最佳实践。合并了 rules:所有自定义规则都集中在一个配置对象中,清晰明了。将 globals 放入 languageOptions:这是 Flat Config 的标准语法,用于定义全局变量。修正了可能的拼写错误:将 vue/^-setup-props-destructure 修正为 vue/no-setup-props-destructure。

重新在终端中提交:

【Vue3 问题解决】husky+lint-staged 在提交代码时lint-staged不生效,有错误提示

成功!!

参考资料:

ESLint Flat Config 文档 – 配置对象

ESLint Flat Config 文档 – 如何配置规则

© 版权声明

相关文章

暂无评论

none
暂无评论...