项目中import 顺序
- 分类顺序
可以根据模块或文件的功能、类型等进行分类,比如将所有的组件放在一起、工具函数放在一起等。这样的组织方式更有利于对项目结构和代码逻辑的理解,当需要查找某一类功能的代码时,可以快速定位到相应的 import 区域。
- Node.js 内置模块:像 path、fs 这类 Node.js 内置模块要放在最前面,因为它们是基础的运行时依赖。
- React 相关库:如果项目使用 React,那么 React 及其相关的库(例如 ReactDOM)要紧跟在内置模块之后。
- 第三方库:从 npm 或者 yarn 安装的第三方库(如 axios、lodash)排在 React 库之后。
- 外部 UI 库:像 Ant Design、Material UI 这类外部 UI 库单独列出,方便查找和管理。
- 内部组件:项目内自定义的组件要放在外部库之后,这样可以清晰地区分外部依赖和内部代码。
- 工具函数:通用的工具函数(例如日期格式化、邮件验证)要放在组件之后。
- 常量:常量要单独列出,方便修改和维护。
- ts 类型 /idl api:TypeScript 类型定义和 API 函数要放在常量之后。
- 图片:项目里使用的图片资源(如 logo)要放在类型定义之后。
- 样式:样式文件(如 CSS、SCSS)要放在最后,因为样式通常是全局的,不依赖于其他代码。
项目中import 顺序之React示例
- 以下按照分类顺序
// Node.js 内置模块 import path from 'path'; import fs from 'fs'; // React 相关库 import React from 'react'; import ReactDOM from 'react-dom/client'; // 第三方库(来自 npm/yarn) import axios from 'axios'; import lodash from 'lodash'; // 外部 UI 库 import { Button, Input } from 'antd'; // 内部组件 import Header from './components/Header'; import Footer from './components/Footer'; // 工具函数 import { formatDate, validateEmail } from './utils/helpers'; // 常量 import { API_BASE_URL, MAX_ATTEMPTS } from './constants'; // ts 类型 / idl api import type { User, Product } from './types'; import { getUserById } from './api'; // 图片 import logo from './assets/logo.png'; // 样式 import './styles/main.css';
ESLint自动化工具与配置
- 对 import 顺序而言,ESLint 提供了广泛的配置选项,可以通过 import/order 规则来精确控制不同类型,自动修复,提升效率。
- 使用 eslint-plugin-import 插件, 进行order 规则配置
- npm install eslint eslint-plugin-import --save-dev
- 使用 eslint-plugin-import 插件, 进行order 规则配置
初识Eslint的’import/order’规则
“import/order”:这是 eslint-plugin-import 插件里用于检查 import 语句顺序的规则。
- .eslintrc.js 文件: 'import/order’规则
plugins: ['import'], rules: { "import/order": [ // 表明违反该规则时,ESLint 会将其当作错误来处理。 "error", { "groups": [ "builtin",//Node.js 的内置模块 "external",//从 npm 或者 yarn 安装的第三方模块 "internal",//项目内部的模块,一般是通过项目内部的路径进行引用的 "parent",//从父目录导入的模块 "sibling",//从同级目录导入的模块 "index",//当前目录下的 index 文件 "object",//以对象形式导入的模块 "type",//用于 TypeScript 项目中仅导入类型的语句 "unknown"//无法明确归类到其他标准分组的 import 语句 ], // 不同分组的 import 语句之间必须有一个空行分隔 "newlines-between": "always", // 配置 import 语句在每个分组内的排序规则 "alphabetize": { // 按照字母表升序排列,从小到大 "order": "asc", // 在排序时忽略大小写 "caseInsensitive": true } } ] }
- 规则支持的选项:groups
- 确定哪些导入需要排序以及如何排序
- 有效值:(“builtin” | “external” | “internal” | “unknown” | “parent” | “sibling” | “index” | “object” | “type”)[]
- 默认值:[“builtin”, “external”, “parent”, “sibling”, “index”]
- 示例: [“builtin”, “external”, “internal”, “parent”, “sibling”, “index”, “object”, “type”]时的import顺序
// 1. node "builtin" modules 代表 Node.js 内置模块,像 fs、path、http 这类 import fs from 'fs'; import path from 'path'; // 2. "external" modules 指从 npm 或者 yarn 安装的第三方模块,例如 lodash import _ from 'lodash'; import chalk from 'chalk'; // 3. "internal" modules 表示项目内部使用别名(如 @xxx)引用的模块 // (if you have configured your path or webpack to handle your internal paths differently) import foo from 'src/foo'; // 4. modules from a "parent" directory "parent" 表示父目录下的模块 import foo from '../foo'; import qux from '../../foo/qux'; // 5. "sibling" modules from the same or a sibling's directory 同一目录下的模块 import bar from './bar'; import baz from './bar/baz'; // 6. "index" of the current directory 当前目录下的文件 import main from './'; // 7. "object"-imports (only available in TypeScript) 导入为对象形式的 import 语句 import log = console.log; import * as someObject from './someModule'; // 8. "type" imports (only available in Flow and TypeScript) 仅导入类型的 import 语句(在 TypeScript 中使用) import type { Foo } from 'foo';
- 规则支持的选项:pathGroups
- 自定义特定路径或模块的导入,例如,将 React 相关库设置为第一个加载.
- 使用场景:groups配置不够细粒度,尤其是在使用导入别名时
pathGroups: [ { pattern: "react", group: "external", position: "before", }, { pattern: "*.png", // 根据需要可以扩展其他图片文件类型 group: "unknown", patternOptions: { matchBase: true }, position: "after", }, { pattern: "*.types", group: "unknown", patternOptions: { matchBase: true }, position: "after", }, { pattern: "*.{css,scss,less}", group: "unknown", patternOptions: { matchBase: true }, position: "after", }, ],
- pattern: 简单的模式(Minimatch模式)字符串
- Minimatch模式是一个用于实现 glob 模式匹配的 JavaScript 库,它允许你使用简单的模式字符串来匹配文件路径。
- 工作原理是将 glob 表达式转换为 JavaScriptRegExp 对象
- Minimatch模式是一个用于实现 glob 模式匹配的 JavaScript 库,它允许你使用简单的模式字符串来匹配文件路径。
React项目.eslintrc.js 文件配置示例
module.exports = {
plugins: ['import'],
rules: {
'import/order': [
'error',
{
// 定义特定模式的分组和位置
pathGroups: [
{
// 匹配 react 相关的 import, 提取到external分组最前
pattern: 'react',
group: 'external',
position: 'before',
},
{
// 匹配 classnames 相关的 import
pattern: 'classnames',
group: 'external',
position: 'before',
},
{
// 把@features下的文件归为internal,注意这里必须是两个**,才可以表示多级目录
pattern: '@features/**',
group: 'internal',
},
// {
// //将 @ 导入的方式归为 internal
// pattern: '@/**',
// group: 'internal',
// },
{
// 匹配图片文件的 import
pattern: '*.{png,jpg,jpeg,gif,svg}',
group: 'unknown',
//仅在文件名部分进行匹配,不考虑文件路径
patternOptions: { matchBase: true },
position: 'after',
},
{
// 匹配样式文件的 import
pattern: '*.{css,scss,less}',
group: 'unknown',
patternOptions: { matchBase: true },
position: 'after',
},
],
// 定义 import 分组的整体顺序
groups: [
'builtin',
'external',
'internal',
['sibling', 'parent'],
'index',
'object',
'type',
'unknown',
],
// 控制哪些([builtin])分组的 import 语句不参与 pathGroups 的排序规则匹配
pathGroupsExcludedImportTypes: ['builtin'],
// 不同分组之间添加空行
'newlines-between': 'always',
// 每个分组内按字母升序排序,忽略大小写
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
},
],
},
};