import/order
Enforce a consistent order of imports, by group and optionally by name
Also called import-x/order
When people add imports wherever there's room, you can't see at a glance what a file depends on, and two branches that add an import in the same spot conflict. This rule sorts imports into groups by where they come from.
The default order is Node.js built-ins, packages, parent folders (../), the same folder (./), then the folder's own index (. or ./). Inside a group any order is fine, unless you set alphabetize.
- The rule checks
importand top-levelconst x = require(). Allrequire()calls go after allimportstatements. import "./app.css"and other imports without a name are skipped, because moving them can change what the code does.bunandbun:testcount as built-ins. With an ESLint config they count as packages, unlesssettings["import/core-modules"]lists them.
--fix moves the imports, unless there's other code between them.
Configure#
Off by default. To turn it on:
[lint.rules]
"import/order" = "error" # or "warn"Every option, set to its default. The ones that are commented out are unset by default.
[lint.rules]
"import/order" = ["error", {
groups = ["builtin", "external", "parent", "sibling", "index"],
# "ignore", "always", "always-and-inside-groups" or "never"
newlines-between = "ignore",
# alphabetize = <object>,
named = false,
pathGroups = [], # list of objects
pathGroupsExcludedImportTypes = ["builtin", "external", "object"],
distinctGroup = true,
sortTypesGroup = false,
# newlines-between-types = <string>,
consolidateIslands = "never", # "inside-groups" or "never"
warnOnUnassignedImports = false,
}]Examples#
import { formatDate } from "./format.js";
import express from "express";express import should occur before import of ./format.js
import fs from "node:fs";node:fs import should occur before import of ./format.jsimport fs from "node:fs";
import { serve } from "bun";
import express from "express";
import { config } from "../config.js";
import { formatDate } from "./format.js";
import { routes } from "./";Options#
| Option | Default | What it does |
|---|---|---|
groups | ["builtin", "external", "parent", "sibling", "index"] | The order of the groups. A nested array makes several groups count as one. Groups you leave out come last, together. |
newlines-between | "ignore" | "always": one or more empty lines between groups, none inside. "always-and-inside-groups": the same, but empty lines inside a group are fine. "never": no empty lines at all. |
alphabetize | { order: "ignore" } | Sort each group by path. order: "asc" or "desc". caseInsensitive: false by default. orderImportKind: for two imports of the same path, "asc" puts the import type first and "desc" puts it last. |
named | false | Also sort the names inside { }, by alphabetize.order. true, or an object with enabled for all and import, export, require, cjsExports for each kind. Its types key says where inline type names go: "mixed", "types-first" or "types-last". |
pathGroups | [] | Puts paths that match a glob into a group: { pattern, group, position }. position is "before" or "after" the rest of the group. patternOptions takes glob options such as nocase and matchBase. |
pathGroupsExcludedImportTypes | ["builtin", "external", "object"] | Kinds of imports that pathGroups leaves alone. |
distinctGroup | true | For newlines-between, treat a path group with a position as a separate group. |
sortTypesGroup | false | Order the imports in the "type" group by groups too. |
newlines-between-types | same as newlines-between | With sortTypesGroup, the empty lines around and between import type statements. |
consolidateIslands | "never" | "inside-groups", with "always-and-inside-groups": an empty line around each multi-line import, none between single-line imports of a group. |
warnOnUnassignedImports | false | Also check imports without a name. --fix doesn't move them. |
You can put four more groups in groups:
"internal": a path that isn't relative and resolves to a file in your project."unknown": a path that doesn't fit any other group."object":import log = console.login TypeScript."type":import type.
newlines-between#
With "always", this is reported:
{ "newlines-between": "always" }1 problemimport fs from "node:fs";There should be at least one empty line between import groups
import express from "express";And this isn't:
{ "newlines-between": "always" }No problemsimport fs from "node:fs";
import express from "express";alphabetize and named#
[lint.rules]
"import/order" = ["error", {
named = true,
alphabetize = { order = "asc", caseInsensitive = true },
}]{ "named": true, "alphabetize": { "order": "asc", "caseInsensitive": true } }2 problemsimport { writeFile, readFilereadFile import should occur before import of writeFile } from "node:fs/promises";
import express from "express";
import chalk from "chalk";chalk import should occur before import of express{ "named": true, "alphabetize": { "order": "asc", "caseInsensitive": true } }No problemsimport { readFile, writeFile } from "node:fs/promises";
import chalk from "chalk";
import express from "express";pathGroups#
Use it for path aliases such as @/, which otherwise count as "unknown":
[lint.rules]
"import/order" = ["error", {
groups = ["builtin", "external", "internal", "parent", "sibling", "index"],
pathGroups = [{ pattern = "@/**", group = "internal" }],
}]{ "groups": ["builtin", "external", "internal", "parent", "sibling", "index"], "pathGroups": [{ "pattern": "@/**", "group": "internal" }] }1 problemimport { config } from "../config.js";
import { Button } from "@/components/button";@/components/button import should occur before import of ../config.js{ "groups": ["builtin", "external", "internal", "parent", "sibling", "index"], "pathGroups": [{ "pattern": "@/**", "group": "internal" }] }No problemsimport { Button } from "@/components/button";
import { config } from "../config.js";An alias that looks like a package name, such as @app/button, counts as "external", and pathGroups skips it. Set pathGroupsExcludedImportTypes to ["builtin"] to include it.
The "type" group#
With "type" in groups, every import type goes in that spot, no matter where it imports from:
{ "groups": ["builtin", "external", "parent", "sibling", "index", "type"] }1 problemimport type { Server } from "node:http";
import { formatDate } from "./format.ts";./format.ts import should occur before type import of node:http{ "groups": ["builtin", "external", "parent", "sibling", "index", "type"] }No problemsimport { formatDate } from "./format.ts";
import type { Server } from "node:http";