find-unused-exports
v9.0.0
Published
A CLI and equivalent JS API to find unused ECMAScript module exports in a project.
Maintainers
Readme
find-unused-exports
A Node.js CLI and equivalent JS API to find unused ECMAScript module exports in a project.
To achieve this the whole project is analyzed at once, something ESLint can’t do as it lints files in isolation.
- The
npx find-unused-exportsscript is handy for finding redundant code to remove in legacy projects. - Use the CLI command
find-unused-exportsin package test scripts, so that CI can prevent the addition of redundant code.
Installation
To install find-unused-exports with npm, run:
npm install find-unused-exports --save-devThen, either use the CLI command find-unused-exports or import and use the function findUnusedExports.
Excluding modules
Exclude third party modules and build artifacts from analysis via an exclude glob. This is specified for the CLI command find-unused-exports via the argument --exclude-glob (relative to the current working directory), and for the function findUnusedExports via the option excludeGlob (relative to the current working directory specified by the option cwd, defaulting to process.cwd()).
By default TypeScript declaration files and node_modules directories are recursively excluded:
{**/{,*,.*}.d.{mts,cts,ts},**/node_modules/**}When specifying a custom exclude glob, include what the default does. E.g. to also exclude a directory dist at the project root:
{**/{,*,.*}.d.{mts,cts,ts},**/node_modules/**,dist/**}Don’t exclude modules you author as a way to ignore validly unused exports:
- Accidental unused exports in the excluded modules won’t be detected.
- The imports won’t be analyzed, potentially causing exports elsewhere in the project to be falsely considered unused.
See below for how to properly ignore specific exports in specific modules.
Ignoring unused exports
Ignore exports that are unused in a project for valid reasons:
- If the project is a package intended to be used by other projects, the package exports may be unused.
- If the project has configuration modules for tools, the exports are unused. E.g. the ESLint config file
eslint.config.mjshas an unused default export. - If the project uses a framework that by convention consumes certain certain exports from project modules, they may be unused. E.g. in a Next.js project the directory
pagesmodules have unused default exports.
Ignore exports map
A map of module file globs and export names to ignore as unused. The export name default ignores the default export, and * ignores all exports (usually a bad idea). This is specified for the CLI command find-unused-exports via the argument --ignore (relative to the current working directory), and for the function findUnusedExports via the option ignore (relative to the current working directory specified by the option cwd, defaulting to process.cwd()).
Examples
For a Next.js and ESLint project, a contrived ignore-unused-exports.json:
{
"eslint.config.js": ["default"],
"next.config.js": ["default"],
"pages/**/*.js": [
"default",
"getServerSideProps",
"getStaticPaths",
"getStaticProps"
]
}Then, using npx:
npx find-unused-exports --ignore "$(cat ignore-unused-exports.json)"For a published package, to ignore all the unused exports in a package main index module, the ignore exports map may contain:
{
"index.mjs": ["*"]
}Please don’t publish a package main index module though, for optimal JavaScript module design.
It’s usually a bad idea to ignore every export with *; instead ignore specific export names to be able to detect other accidental unused exports.
Ignore comments
Ignore comments can be used anywhere in a module to ignore all or specific unused exports. They are line or block comments, with the format:
- Optional whitespace.
ignore unused exports(case insensitive).- Optional to only ignore specific exports:
- Optional spaces.
- The names of exports to ignore, separated by a
,and optional spaces.
- Optional whitespace.
Examples
How to ignore all unused exports (usually a bad idea):
// ignore unused exports
export const a = true;
export default true;How to ignore specific unused exports:
// ignore unused exports b, default
export const a = true;
export const b = true;
export default true;Multiple comments can be used:
// ignore unused exports a
export const a = true;
// ignore unused exports b
export const b = true;Comments are case-insensitive, except for the export names:
// iGnOrE UnUsEd eXpOrTs defaultLine or block comments can be used:
/* ignore unused exports */Requirements
Supported runtime environments:
- Node.js versions
^22.19.0 || >=24.5.0.
Projects must configure TypeScript to use types from the ECMAScript modules that have a // @ts-check comment:
compilerOptions.allowJsshould betrue.compilerOptions.maxNodeModuleJsDepthshould be reasonably large, e.g.10.compilerOptions.moduleshould be"node16"or"nodenext".
CLI
Command find-unused-exports
Finds unused ECMAScript module exports in a project. If some are found, it reports them to stderr and exits with a 1 error status.
It implements the function findUnusedExports.
Arguments
| Argument | Default | Description |
| :-- | :-- | :-- |
| --exclude-glob | "{**/{,*,.*}.d.{mts,cts,ts},**/node_modules/**}" | File glob pattern to exclude files from the --module-glob results, relative to the current working directory. |
| --ignore | "{}" | JSON ignore exports map of module file globs (relative to the current working directory) and export names to ignore as unused. The export name default ignores the default export, and * ignores all exports (usually a bad idea). |
| --import-map | "{}" | JSON import map, relative to the current working directory. |
| --module-glob | "**/{,*,.*}.{mts,cts,ts,tsx,mjs,cjs,js,jsx}" | Module file glob pattern, relative to the current working directory. |
| --resolve-file-extensions | | File extensions (without the leading ., multiple separated with , in preference order) to automatically resolve in extensionless import specifiers. Import specifier file extensions are mandatory in Node.js; if your project resolves extensionless imports at build time (e.g. Next.js, via webpack) mjs,js might be appropriate. |
| --resolve-index-files | | Should directory index files be automatically resolved in extensionless import specifiers. Node.js doesn’t do this by default; if your project resolves extensionless imports at build time (e.g. Next.js, via webpack) this argument might be appropriate. This argument only works if the argument --resolve-file-extensions is used. |
Examples
Using npx in a standard Node.js project:
npx find-unused-exportsUsing npx in a legacy webpack project that has ESM in .js files, extensionless import specifiers, and index.js files:
npx find-unused-exports --module-glob "**/*.js" --resolve-file-extensions js --resolve-index-filesUsing npx in a project with an import map in a file import-map.json:
npx find-unused-exports --import-map "$(cat import-map.json)"package.json scripts for a project that also uses eslint and prettier:
{
"scripts": {
"prettier": "prettier -c .",
"eslint": "eslint",
"find-unused-exports": "find-unused-exports",
"test": "node --run prettier && node --run eslint && node --run find-unused-exports",
"prepublishOnly": "node --run test"
}
}Exports
The npm package find-unused-exports features optimal JavaScript module design. It doesn’t have a main index module, so use deep imports from the ECMAScript modules that are exported via the package.json field exports:
