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

@jdb8/unbarrel

v0.3.1

Published

Pre-resolve barrel file imports automatically for faster development

Readme

unbarrel

main version

Barrel files are often a source of slowness in large codebases. While it's probably better to get rid of them entirely for new code, in some situations it may be unavoidable, undesirable, or costly to banish them wholesale. It would be great if there was a way to support barrel files without the heavy performance drawbacks!

Install

npm install -D @jdb8/unbarrel

Usage

Node

import { unbarrel } from "@jdb8/unbarrel";
const result = await unbarrel(options); // TODO: document options

Webpack

const config: webpack.Configuration = {
    module: {
        rules: [
            {
                test: /\.(t|j)sx?$/, // whichever file extensions you expect to unbarrel
                use: require.resolve("@jdb8/unbarrel"),
                // This will exclude node_modules files from being unbarreled,
                // but will still be traversed internally
                exclude: /node_modules/,
            },
        ],
    },
};

How does it work?

If you are working on a monorepo containing many interlinked packages, and each of those packages exports its code from a central index.ts entrypoint file, you are likely experiencing build tooling inefficiencies as a result of these barrel files.

unbarrel takes a resolver function and an input file:

import { deepImport } from "some-barrel-package";

where some-barrel-package's index.js looks like:

export { foo } from "./Foo.js";
export { bar } from "./Bar.js";
export { deepImport } from "./thing-my-caller-actually-wants.js";

and will output an "unbarreled" output file:

import { deepImport } from "/abs/path/to/some-barrel-package/thing-my-caller-actually-wants.js";

Now, tools that would previously have traversed Foo.js and Bar.js will completely ignore their existence. You could imagine that Foo.js and Bar.js each have many transitive imports into other packages, so at a high enough number of modules in the graph this can be meaningful.

FAQ

Is this safe?

Not really. Barrel files can have side effects which means that it's not completely safe to run this against all files in an unknown codebase, but if you're in control of the source barrel files you can guarantee code is equivalent.

Why isn't this a babel/eslint/<other tool> plugin?

In order to traverse module imports, we need access to a resolver function, which fits more naturally at a layer of the build pipeline that can provide us one. Bringing our own resolver function also risks incompatibilities with the bundler's own at a higher level of the pipeline.

While it's possible to teach a babel plugin to traverse the filesystem, it goes against the spirit of processing one file at a time in isolation and starts to make things more complicated.

ESLint has some prior art for linting across import boundaries (eslint-plugin-import) and so would be viable if the goal is to autofix imports to deep imports (perhaps this package's node api could be used under the hood), but this tool aims to leave the code untouched.

Other tools can implement wrappers around the node API by passing in a compatible resolver function from whichever tool is providing one. Jest is one that would probably be useful.

Doesn't tree-shaking already fix this?

Bundler tree-shaking is designed to reduce the amount of code that ends up in the resulting bundle, but it still needs to construct a module graph for every file being imported, so tree-shaking cannot provide a build-time performance boost. The only way to avoid the cost of loading/parsing/transpiling unnecessary files is to remove them from consideration entirely!

Why does the tool output absolute paths?

No strong reason, but in some cases providing absolute paths to tooling can allow it to skip additional lookup logic.

Development

This package is built with bun. Install bun on your machine, and then install and build dependencies with:

bun install
bun run build

To run a benchmark:

bun run benchmark

You'll see something like:

------------------------------ LOADER ENABLED: true ------------------------------
[567.80ms] compile true

# modules: 109

asset main.js 13 KiB [emitted] [minimized] (name: main)
orphan modules 68.7 KiB [orphan] 108 modules
./test-app-code.ts + 108 modules 68.8 KiB [built] [code generated]
webpack 5.95.0 compiled successfully in 568 ms
------------------------------ LOADER ENABLED: false ------------------------------
[686.04ms] compile false

# modules: 641

asset main.js 13 KiB [emitted] [minimized] (name: main)
orphan modules 613 KiB [orphan] 640 modules
./test-app-code.ts + 108 modules 68.8 KiB [built] [code generated]
webpack 5.95.0 compiled successfully in 686 ms

which shows that the unbarrelling logic has taken place.

Acknowledgements

This repo began as a fork of, and wrapper around, the debarrel vite plugin written by @developit. Make sure to watch his excellent ViteConf talk alongside the corresponding tweet thread!

Additional resources around barrel files:

  • https://tkdodo.eu/blog/please-stop-using-barrel-files
  • https://marvinh.dev/blog/speeding-up-javascript-ecosystem-part-7/