Eslint自定义规则使用

发布于:2025-06-21 ⋅ 阅读:(17) ⋅ 点赞:(0)


前言

设计一个非常真实、非常有价值的自定义规则场景,这个场景在开发中都可能遇到的:架构约束规则


场景设定:维护代码分层,禁止“跨级调用”

背景
在一个良好分层的项目中,我们通常会把代码分成不同的层次。假设你的 uni-app 项目遵循以下结构:

  • src/services/:存放所有与后端 API 交互的逻辑(比如 userService.ts, productService.ts)。这些是“数据服务层”。
  • src/pages/:存放所有的页面(.vue 文件)。这些是“视图层”。
  • src/utils/:存放通用的工具函数。

团队规定(我们的架构约束)
为了保持代码的清晰和可维护性,团队规定 “视图层 (pages)” 不允许直接调用 “数据服务层 (services)”

  • 错误的做法:在 src/pages/my/index.vue 中直接 import { getUserInfo } from '@/services/userService';
  • 正确的做法:页面应该通过一个统一的、更高层的逻辑单元(比如 Vuex/Pinia 的 actions,或者一个专门的 controller 层)来获取数据,而不是直接触碰底层的 service。

目标
我们要创建一个自定义 ESLint 规则,叫做 no-service-import-in-pages。当有开发者试图在 src/pages/ 目录下的任何文件中导入 src/services/ 里的模块时,ESLint 应该立刻用红色下划线报错,并给出清晰的提示:“页面组件不允许直接导入 service,请通过状态管理层调用。”


实现步骤:从零到一,创建你的第一条自定义规则

这个过程分为两步:1. 编写规则2. 注册规则

第 1 步:创建规则文件
  1. 在你的项目根目录(和 package.json 同级)创建一个新文件夹,命名为 eslint-rules

  2. 在这个文件夹里,创建一个新文件,命名为 no-service-import-in-pages.js

  3. 将以下代码粘贴到 no-service-import-in-pages.js 中:

    /**
     * @fileoverview Rule to prevent importing from the services layer directly into page components.
     * @author Your Name
     */
    "use strict";
    
    //------------------------------------------------------------------------------
    // Rule Definition
    //------------------------------------------------------------------------------
    
    module.exports = {
      // meta: 包含了规则的元数据
      meta: {
        type: "problem", // 这表示规则将发现一个代码问题
        docs: {
          description: "Disallow direct imports from the services layer in page components",
          category: "Best Practices",
          recommended: true,
        },
        fixable: null, // 这个规则不可自动修复
        schema: [], // 这个规则没有额外的配置选项
        messages: {
            noServiceImport: "页面组件不允许直接导入 service,请通过状态管理层调用。",
        }
      },
    
      // create: 返回一个对象,这个对象包含了遍历 AST 时要访问的节点
      create(context) {
        // 获取当前正在被检查的文件的绝对路径
        const filename = context.getFilename();
    
        // 如果文件路径不包含 /pages/,那么这个规则直接跳过,不进行任何检查
        if (!filename.includes("/src/pages/")) {
          return {};
        }
    
        // 如果文件在 pages 目录下,我们返回一个访问者对象
        return {
          // 'ImportDeclaration' 是 AST 中代表 'import ... from ...' 语句的节点类型
          ImportDeclaration(node) {
            // node.source.value 获取的是 from 后面的字符串,比如 '@/services/userService'
            const importSource = node.source.value;
    
            // 检查这个导入路径是否包含了 'services'
            if (importSource && importSource.includes("services")) {
              // 如果包含了,就报告一个错误
              context.report({
                node: node, // 在这个 import 语句节点上报告错误
                messageId: "noServiceImport", // 使用 meta.messages 中定义好的错误信息
              });
            }
          },
        };
      },
    };
    
第 2 步:在 eslint.config.mjs 中注册并启用你的规则

现在我们需要告诉 ESLint:“嘿,我写了一个新规则,给你用!”

打开 eslint.config.mjs,我们需要修改 “3. A main configuration object” 这个部分,添加一个新的 plugins 字段,并启用我们的规则。

// ... 其他 import 语句 ...
// 导入我们自己的规则
import noServiceImportInPages from './eslint-rules/no-service-import-in-pages.js';

export default [
  // ... 其他配置 ...

  // 3. A main configuration object for our custom settings
  {
    languageOptions: {
      // ... globals ...
    },
    plugins: {
      // Make plugins available for all files
      '@typescript-eslint': tseslint.plugin,
      vue: vuePlugin,
      // 在这里注册我们的自定义规则插件
      'custom-rules': {
        rules: {
          'no-service-import-in-pages': noServiceImportInPages,
        },
      },
    },
    rules: {
      // ... 其他规则 ...
      // 在这里启用我们的自定义规则,并设置为 error 级别
      'custom-rules/no-service-import-in-pages': 'error',
    },
  },

  // ... 其他配置 ...
];

验证成果

做完以上修改后,请重启 VSCode!

现在,去任何一个位于 src/pages/ 目录下的 .vue 文件,在 <script> 标签里尝试写下:

import { someFunction } from '@/services/api';

你会立刻看到,这行代码被画上了红色波浪线,当你把鼠标悬停在上面时,会显示我们自定义的错误信息:“页面组件不允许直接导入 service,请通过状态管理层调用。”

而在 src/utils 或其他非 pages 目录的文件中进行同样的导入,则不会有任何报错。

就这样成功地创建并应用了一条非常有价值的、用于维护项目架构的自定义 ESLint 规则!


网站公告

今日签到

点亮在社区的每一天
去签到