An ESLint rule for sorting and grouping imports.
npm install eslint-plugin-ordered-importseslint-plugin-ordered-imports package and add ordered-imports to
plugins section of your .eslintrc file. Optionally, add
plugin:ordered-imports/recommended to the extends section of your
.eslintrc file to enable the recommended configuration. For example, here are
.eslintrc file where both of these actions have been taken.
js
{
plugins: ["ordered-imports"],
extends: ["plugin:ordered-imports/recommended"],
}
`
$3
There is only one rule exposed by this plugin, ordered-imports. This rule has
three configuration options which may be configured or left with their default
values: declaration-ordering, specifier-ordering, and group-ordering. Here
is the structure of the rule configuration defined in TypeScript.
`ts
type Type = "side-effect" | "default" | "namespace" | "destructured";
type Configuration = {
// Defines whether symbols (e.g., $ or _) are sorted before other strings.
// Default = true
"symbols-first"?: boolean;
// Defines how import declarations are ordered.
// Default = ["source", "lowercase-last"]
"declaration-ordering"?:
// Unordered.
| ["any"]
// Ordered by import name (e.g., the foo in import foo from "bar").
| ["name", "case-insensitive" | "lowercase-last"]
// Ordered by import source (e.g., the bar in import foo from "bar").
| ["source", "case-insensitive" | "lowercase-last"]
// Ordered by import type which is a category defined by this plugin.
//
// * "side-effect" (e.g., import "foo")
// * "default" (e.g., import foo from "bar")
// "namespace" (e.g., import as foo from "bar")
// * "destructured" (e.g., import { foo, bar } from "baz")
//
// After being ordered by import type, the imports within each subgroup with
// the same import type may then be ordered.
| ["type", {
// Defines how subgroups with the same import type are ordered.
// Default = ["side-effect", "default", "namespace", "destructured"]
ordering?: [Type, Type, Type, Type];
// Defines how import declarations within each subgroup are ordered.
// Default = ["source", "lowercase-last"]
secondaryOrdering?:
// Unordered.
| ["any"]
// Ordered by import name (e.g., the foo in import foo from "bar").
| ["name", "case-insensitive" | "lowercase-last"]
// Ordered by import source (e.g., the bar in import foo from "bar").
| ["source", "case-insensitive" | "lowercase-last"];
}];
// Defines how import specifiers are ordered.
// Default = "lowercase-last"
"specifier-ordering"?: "case-insensitive" | "lowercase-last" | "any";
// Defines how import groups are ordered.
// Default = []
"group-ordering"?: { name: string; match: string; order: number }[];
};
`
Here is the recommended configuration (provided by
plugin:ordered-imports/recommended mentioned in the Usage section) as it
would appear in .eslintrc with all options fully specified (no default
values):
`js
{
rules: {
"ordered-imports/ordered-imports": [
"error",
{
"symbols-first": true,
"declaration-ordering": ["type", {
ordering: ["side-effect", "default", "namespace", "destructured"],
secondaryOrdering: ["name", "lowercase-last"],
}],
"specifier-ordering": "lowercase-last",
"group-ordering": [
{ name: "project root", match: "^@", order: 20 },
{ name: "parent directories", match: "^\\.\\.", order: 30 },
{ name: "current directory", match: "^\\.", order: 40 },
{ name: "third-party", match: ".*", order: 10 },
],
},
],
},
}
`
Note the ordering of the groups in the group-ordering configuration. An import
declaration is considered a member of the first group whose regular expression
(the match property) matches the source of the import declaration (e.g., the
bar in import foo from "bar"). As a result, the "third-party"` import group