npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eslint-plugin-no-barrel-files

v2.2.0

Published

ESLint plugin for reducing barrel-file usage in two ways:

Downloads

1,621,297

Readme

eslint-plugin-no-barrel-files

ESLint plugin for reducing barrel-file usage in two ways:

  • no-barrel-files: disallow authoring barrel files
  • prefer-source-imports: prefer importing from source modules instead of through a barrel

The plugin is useful both for strict greenfield setups and for incremental migrations away from existing barrels.

Why?

Barrel files can:

  • slow down builds and tests
  • make circular dependencies easier to introduce
  • make tree shaking less effective
  • blur module boundaries and make import paths less explicit

References:

  • https://github.com/jestjs/jest/issues/11234
  • https://github.com/vercel/next.js/issues/12557
  • https://dev.to/tassiofront/barrel-files-and-why-you-should-stop-using-them-now-bc4
  • https://flaming.codes/posts/barrel-files-in-javascript

Install

npm install --save-dev eslint-plugin-no-barrel-files

prefer-source-imports needs typescript in the consuming project whenever tsconfig resolution is enabled (the default), including when linting JavaScript files. Set tsconfig: false to use only relative imports and the rule's manual paths option instead.

npm install --save-dev typescript

Quick Start

This plugin supports:

  • ESLint 9+ and 10+ via flat config
  • ESLint 8 via legacy config

Flat Config

import noBarrelFiles from 'eslint-plugin-no-barrel-files';

export default [...noBarrelFiles.configs['flat/recommended']];

Legacy Config

module.exports = {
  extends: ['plugin:no-barrel-files/recommended'],
};

Included Configs

The plugin exports two recommended configs:

  • configs.recommended for legacy config
  • configs["flat/recommended"] for flat config

Both enable no-barrel-files and prefer-source-imports.

Rules

no-barrel-files

Disallows common barrel-file patterns such as re-exporting imported bindings or using export *.

// fail
export * from "./foo";

import Foo from "./foo";
export default Foo;

import Foo from "./foo";
export { Foo };

export { Moo } from "./Moo";
export { default as Moo } from "./Moo";

// pass
const Foo = "baz";
function Bar() {}
class Baz {}

export default Foo;
export { Bar, Baz };

import { Moo } from "./Moo";
export const Baz = Moo;

Use this rule when you want to stop new barrel files from being created.

Options

allow

Allows intentional barrel files whose path matches one of the supplied glob patterns. Patterns match paths relative to the current working directory; absolute patterns are also supported.

{
  'no-barrel-files/no-barrel-files': ['error', {
    allow: ['src/index.ts', 'packages/*/src/index.ts'],
  }],
}

prefer-source-imports

Reports imports that go through a barrel when the rule can resolve the original source module.

// fail
import { Foo } from './barrel';
import type { TypeFoo } from './barrel';

// if barrel.ts contains:
// export { Foo } from "./foo";
// export type { TypeFoo } from "./types";

// pass
import { Foo } from './foo';
import type { TypeFoo } from './types';

This rule is useful when:

  • a codebase still has barrel files
  • you want to migrate consumers away from barrels gradually
  • you want autofixable guidance where possible

What it can resolve

prefer-source-imports currently supports:

  • relative imports
  • TypeScript baseUrl and paths from the nearest tsconfig.json
  • explicit alias mappings through the paths rule option
  • explicit re-exports such as export { Foo } from "./foo"
  • aliased re-exports such as export { Bar as Foo } from "./bar"
  • local re-exports such as import { Foo } from "./foo"; export { Foo }
  • default re-exports such as export { default as Foo } from "./foo"
  • export * from "./foo" when the exported name can be resolved back to the source file
  • type-only re-exports such as export type { Foo } ... and export { type Foo } ...

Current scope:

  • the rule focuses on named imports
  • default imports are rewritten when the barrel directly re-exports its default export
  • namespace imports are not the target of this rule

Safe autofix behavior

The rule only autofixes when the full import declaration can be rewritten safely.

If only part of an import can be resolved safely, the rule still reports the problem but may skip autofix.

prefer-source-imports Options

fixStyle

Controls how the replacement import path is generated.

  • "relative" Always rewrites to a relative import path.
  • "preserve-alias" Preserves an alias only when the reverse alias mapping is unique.
  • "auto" Preserves aliases for alias-based imports when the reverse alias mapping is unique; otherwise falls back to a relative path.

ignore

Skips imports whose source specifier matches one of the supplied glob patterns. Use this for intentional public barrel APIs while continuing to fix internal barrel imports.

import noBarrelFiles from 'eslint-plugin-no-barrel-files';

export default [
  {
    plugins: {
      'no-barrel-files': noBarrelFiles,
    },
    rules: {
      'no-barrel-files/prefer-source-imports': ['error', {
        ignore: ['@acme/ui', '@acme/*/public'],
      }],
    },
  },
];

tsconfig

Controls tsconfig-based path resolution.

  • omitted or true Use the nearest tsconfig.json.
  • false Disable tsconfig-based resolution entirely.
  • "./path/to/tsconfig.json" Resolve using a specific config file.

paths

Manual alias mappings that supplement or replace tsconfig path resolution.

Values can be:

  • a string
  • an array of strings

Example:

{
  paths: {
    "@app/*": "src/*",
    "@shared/*": ["packages/shared/src/*", "src/shared/*"],
  },
}

Configuration Examples

Enable Only no-barrel-files

This blocks new barrel files, but does not yet enforce direct source imports.

import noBarrelFiles from 'eslint-plugin-no-barrel-files';

export default [
  {
    plugins: {
      'no-barrel-files': noBarrelFiles,
    },
    rules: {
      'no-barrel-files/no-barrel-files': 'error',
    },
  },
];

Enable Both Rules

This is a good migration setup.

import noBarrelFiles from 'eslint-plugin-no-barrel-files';

export default [...noBarrelFiles.configs['flat/recommended']];

Use Manual Alias Resolution Only

import noBarrelFiles from 'eslint-plugin-no-barrel-files';

export default [
  {
    plugins: {
      'no-barrel-files': noBarrelFiles,
    },
    rules: {
      'no-barrel-files/prefer-source-imports': [
        'error',
        {
          tsconfig: false,
          fixStyle: 'preserve-alias',
          paths: {
            '@app/*': 'src/*',
          },
        },
      ],
    },
  },
];

Use A Specific tsconfig.json

import noBarrelFiles from 'eslint-plugin-no-barrel-files';

export default [
  {
    plugins: {
      'no-barrel-files': noBarrelFiles,
    },
    rules: {
      'no-barrel-files/prefer-source-imports': [
        'error',
        {
          tsconfig: './tsconfig.eslint.json',
          fixStyle: 'auto',
        },
      ],
    },
  },
];

Adoption Strategy

Typical rollout options:

  • Start with no-barrel-files only to block new barrels.
  • Add prefer-source-imports later to migrate consumers away from old barrels.
  • Run prefer-source-imports first if the codebase already has many barrels and you want to shrink their usage before deleting them.

Notes

  • prefer-source-imports depends on being able to resolve the barrel and the underlying source module.
  • prefer-source-imports uses the consuming project's typescript installation for tsconfig parsing and module resolution.
  • The current TypeScript peer-dependency range is ^5.6.3 || ^6.0.0. TypeScript 7 is not supported yet.
  • If prefer-source-imports runs on a TypeScript file without typescript installed and tsconfig resolution is enabled, the rule reports a configuration error instead of crashing the plugin.
  • The same configuration error is reported for JavaScript files when the rule needs tsconfig-based resolution but typescript is not installed.
  • Alias preservation only happens when reverse alias lookup is unique.
  • If multiple aliases point to the same file, the fixer may fall back to a relative path or skip autofix depending on fixStyle.

Contributing

If you find a bug or want an additional feature, open an issue or send a pull request.