拯救 import 杂乱无章:一次团队代码风格统一的实战记录

381 阅读3分钟

1.一次「看似很小,其实很烦」的问题

事情是这样的,一天我在帮同事 rebase 分支,刚解决完一个冲突,又来一个冲突;
再一看冲突内容,我直接愣住了:

- import axios from 'axios';
- import { getUserInfo } from '@/api/user';
- import Header from '@/components/Header.vue';

+ import Header from '@/components/Header.vue';
+ import axios from 'axios';
+ import { getUserInfo } from '@/api/user';

逻辑没变,代码没变,只是 import 顺序不一样

我当场沉默了 3 秒,然后心里冒出一句话:

“这不是代码问题,这是人类问题。”

在我们团队里:

  • 有人喜欢 先写业务,再慢慢补 import
  • 有人喜欢 外部库放最上面
  • 有人把 @/components 放最前
  • 有人一股脑全丢进去,IDE 自动排序,爱咋咋地

结果就是—— 代码能跑,但 Git 天天冲突。

2.问题本质:import 顺序,真的是“个人习惯”吗?

刚开始大家的态度是:“不就是 import 顺序吗?有必要搞这么复杂?”

但当你换个角度看:

  • import 本身 没有逻辑依赖
  • 却直接影响:
    • Git diff
    • merge 冲突
    • code review 体验
    • 新人阅读成本

它本质上是一个团队规范问题,而不是个人喜好问题。

所以我的目标很明确: 让 import 顺序“不可争论”,而不是“约定俗成”。

3. 解决方案:eslint-plugin-import

我选择的第一个方案是: 用 ESLint 强制约束 import 顺序。

按照 require() / import 语句的顺序执行一个惯例将groups选项设置为以下分组时,顺序如下所示:

(1)常见分组说明👇 配置文档

分组名含义示例
builtinNode 内置模块fspath
external外部依赖vueaxios
internal项目内部别名@/utils
parent父级目录../utils
sibling同级文件./bar.vue
index当前目录 index./
objectimport log = console.log
typeTS 类型import type { User }

(2)安装插件

npm install eslint-plugin-import -D

(3)引入插件

// .eslintrc.js
module.exports = {
  plugins: ['import'],
  rules: {
   'import/order': [
      'error',
      {
        groups: [
          'builtin',    // Node 内置模块
          'external',   // 第三方库
          'internal',   // 项目内部(@/)
          'parent',     // 父级目录
          'sibling',    // 同级文件
          'index',      // 当前目录index文件
          'object', 
          'type'
        ],
        pathGroups: [
          {
            pattern: 'vue',
            group: 'external',
            position: 'before',
          },
          {
            pattern: '@/api/**',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/assets/**',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/components/**',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/composables/**',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/constant',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/router/**',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/stores/**',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/utils/**',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '@/views/**',
            group: 'internal',
            position: 'before',
          },
        ],
        pathGroupsExcludedImportTypes: ['type'],
        newlines-between: 'always', 
        alphabetize: { 
            order: 'asc', 
            caseInsensitive: true, 
        }
      }
    ],
  }
}

import/order 这个规则,核心作用就一句话:不同“来源”的 import,必须按固定分组和顺序书写

(4)这套规则会强制你写成这样

import { ref } from 'vue';
import debounce from 'lodash/debounce';
import { getUserInfo } from '@/api/user';
import Header from '@/components/Header.vue';
import useUser from '@/composables/useUser';
import { YES_NO } './constant';
import BaseInfoForm from './BaseInfoForm.vue';

好处立刻显现:

  • 所有人 import 顺序完全一致
  • Git 冲突明显减少
  • Code Review 不再盯着 import 找茬

4. 我又发现了 eslint-plugin-simple-import-sort

用了一段时间后,我又发现了另一个插件:eslint-plugin-simple-import-sort

我第一反应是:“这玩意和 import/order 有啥区别?”

一句话总结:

它不讲“分组语义”,只讲“排序规则”,而且可以自动修复

特点非常鲜明:

  • ✅ 自动排序
  • ✅ 规则更简单
  • ❌ 语义不如 import/order 强

(1) 安装 & 使用

npm install eslint-plugin-simple-import-sort -D
plugins: ['simple-import-sort'],
rules: {
  'simple-import-sort/imports': 'error',
  'simple-import-sort/exports': 'error',
}

(2)自定义分组示例(实战)

// .eslintrc.js 
module.exports = {
  rules:{
    'simple-import-sort/imports': [
      'error',
      {
        groups: [
          // 1. Node 内置
          ['^node:'],
          // 2. 第三方库
          ['^vue', '^@?\w'],
          // 3. 内部模块
          ['^@/components'],
          ['^@/composables'],
          ['^@/utils'],
          ['^@/api'],
          ['^@/store'],
          ['^@/router'],
          ['^@/views'],
          // 4. 相对路径
          ['^\.'],
        ],
      }
    ]
  }  
}

它会直接帮你 自动修复成统一顺序

5.后来发生了什么?

这套规则上线后,有同事在群里说了一句:

“我终于不用再因为 import 冲突 rebase 半小时了。”

那一刻我意识到:真正的价值,不是炫技,而是让所有人更轻松。