DEV Community

Cover image for Barrelize: Automate Your JavaScript Imports Like a Pro
Nizami
Nizami

Posted on • Edited on • Originally published at github.com

Barrelize: Automate Your JavaScript Imports Like a Pro

Are you tired of manually maintaining index files in your JavaScript or TypeScript projects? Meet Barrelize - a powerful, modern tool that automatically generates and maintains barrel (index) files, making your codebase cleaner and more maintainable.

GitHub logo nizami / barrelize

A CLI tool for automatically generating index (barrel) files in TypeScript and JavaScript projects. Simplifies exports and maintains clean code organization.

Barrelize

🚀 A modern, lightweight and efficient tool for automatically generating index (barrel) files in your JavaScript and TypeScript projects.

Barrelize simplifies module exports by creating clean, centralized index.js or index.ts files, reducing boilerplate and improving project organization.

NPM Version GitHub License

Barrelize in action

Features

  • Automatic Barrel Generation: Scans directories and creates index files with exports for all modules.
  • TypeScript Support: Seamlessly works with TypeScript projects, preserving type safety.
  • Customizable: Configure file patterns, ignore specific files, or customize export styles (named, default, or both).
  • Recursive: Optionally generate barrels for nested directories.
  • CLI & API: Use via command line for quick setups or integrate programmatically in your build scripts.
  • Smart Export Control: Fine-grained control over what gets exported and how
    • Export specific members, namespaces, or use regex patterns
    • Support for custom export names and transformations
    • Support for asterisk (*) exports
    • Flexible export path manipulation
  • Flexible Path Handling: Replace patterns in…

What Are Barrel Files and Why Should You Care? 🤔

Barrel files (commonly named index.ts or index.js) serve as central export points for a directory, allowing you to group and re-export multiple modules. Instead of importing from multiple files:

import {UserService} from './services/user-service';
import {AuthService} from './services/auth-service';
import {ConfigService} from './services/config-service';
Enter fullscreen mode Exit fullscreen mode

You can have a clean, single import:

import {UserService, AuthService, ConfigService} from './services';
Enter fullscreen mode Exit fullscreen mode

While barrel files are great for code organization, maintaining them manually can be tedious and error-prone. That's where Barrelize comes in! 🚀

Why Should You Try Barrelize? ⭐️

  1. Automatic Barrel Generation: Scans directories and creates index files with exports for all modules
  2. TypeScript Support: Seamlessly works with TypeScript projects, preserving type safety
  3. Customizable: Configure file patterns, ignore specific files, or customize export styles
  4. Smart Export Control: Fine-grained control over what gets exported and how:
    • Export specific members, namespaces, or use regex patterns
    • Support for custom export names and transformations
    • Support for asterisk (*) exports
    • Flexible export path manipulation
  5. Flexible Path Handling: Replace patterns in export paths using string or regular expressions
  6. Customizable Formatting: Control bracket spacing, quotes, semicolons, and newlines

Getting Started in 30 Seconds ⚡️

  1. Install Barrelize:
npm install --save-dev barrelize
Enter fullscreen mode Exit fullscreen mode
  1. Initialize configuration (optional):
npx barrelize init
Enter fullscreen mode Exit fullscreen mode
  1. Generate your barrel files:
npx barrelize
Enter fullscreen mode Exit fullscreen mode

That's it! Barrelize will scan your project and create organized barrel files automatically. 🎉

Advanced Configuration 🛠

Create a .barrelize file in your project root to customize the behavior:

{
  "$schema": "node_modules/barrelize/schema.json",
  // Global formatting settings
  "bracketSpacing": true,
  "singleQuote": true,
  "semi": true,
  "insertFinalNewline": true,

  // Configure multiple barrels
  "barrels": [
    {
      // Root directory to start from
      "root": "src",
      // Name of the index file
      "name": "index.ts",
      // Files to include in the barrel
      "include": ["**/*.ts"],
      // Files to exclude from the barrel
      "exclude": ["**/*.test.ts"],
      // Optional ordering of exports
      "order": ["types", "constants", "utils"],
      // String/regex patterns to find and replace in export paths
      "replace": {
        "/\\.ts$/": "" // Remove .ts extension from paths
      },
      // Export configuration for different file patterns
      "exports": {
        "**/*.ts": [
          "* as lib", // Export all as namespace
          "/(.+)Config$/ as $1LibConfig", // Rename exports matching pattern
          "util" // Export specific member
        ]
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Real-World Example 🌟

Before:

src/
  ├── types.ts
  ├── constants.ts
  ├── utils.ts
  └── components/
      ├── Button.tsx
      └── Input.tsx
Enter fullscreen mode Exit fullscreen mode

After running barrelize:

src/
  ├── types.ts
  ├── constants.ts
  ├── utils.ts
  ├── index.ts           # New!
  └── components/
      ├── Button.tsx
      └── Input.tsx
Enter fullscreen mode Exit fullscreen mode

Generated src/index.ts:

export * from './types';
export * from './constants';
export * from './utils';
export * from './components/Button.tsx';
export * from './components/Input.tsx';
Enter fullscreen mode Exit fullscreen mode

Benefits for Your Project 💪

  • Save Time: Eliminate manual creation and maintenance of barrel files
  • Cleaner Imports: Simplify import statements with a single entry point for each directory
  • Scalable: Ideal for large projects with complex folder structures
  • Type Safety: Full TypeScript support ensures your types are preserved
  • Consistency: Automated generation ensures uniform export patterns
  • Flexibility: Customize everything from file patterns to export styles

Join the Community! 🤝

Barrelize is lightweight, open-source, and ready to improve your development workflow. Star us on GitHub and contribute to make it even better!

Discussion 💭

  • How do you currently manage your exports in large TypeScript/JavaScript projects?
  • What features would you like to see in Barrelize?
  • Have you tried other barrel file generators? How does Barrelize compare?

Let's discuss in the comments below! 👇

GitHub logo nizami / barrelize

A CLI tool for automatically generating index (barrel) files in TypeScript and JavaScript projects. Simplifies exports and maintains clean code organization.

Barrelize

🚀 A modern, lightweight and efficient tool for automatically generating index (barrel) files in your JavaScript and TypeScript projects.

Barrelize simplifies module exports by creating clean, centralized index.js or index.ts files, reducing boilerplate and improving project organization.

NPM Version GitHub License

Barrelize in action

Features

  • Automatic Barrel Generation: Scans directories and creates index files with exports for all modules.
  • TypeScript Support: Seamlessly works with TypeScript projects, preserving type safety.
  • Customizable: Configure file patterns, ignore specific files, or customize export styles (named, default, or both).
  • Recursive: Optionally generate barrels for nested directories.
  • CLI & API: Use via command line for quick setups or integrate programmatically in your build scripts.
  • Smart Export Control: Fine-grained control over what gets exported and how
    • Export specific members, namespaces, or use regex patterns
    • Support for custom export names and transformations
    • Support for asterisk (*) exports
    • Flexible export path manipulation
  • Flexible Path Handling: Replace patterns in…

Top comments (6)

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Not sure about this. What if a file exports 5 things, but I only want to externalize 1 or 2?

Collapse
 
nizami profile image
Nizami

Thanks for your interest and for raising this point — it's a valid consideration! I’ve created a feature request based on your input: github.com/nizami/barrelize/issues/1.

Let me know what you think — feel free to leave a comment either here or directly on GitHub.

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

Looks like a good proposal. What worries me is: Is it worth it to write some big configuration (because it's getting big) vs. what I earn in return, which is not writing index.ts myself?

For example: github.com/WJSoftware/wjfe-single-...

That's one index file for a Svelte package of mine. It has 6 lines that export. I don't take long at all to write that. Looks verbose but all files are auto-completed.

Oh, and now that I see this, how does this work with default exports? Svelte projects export components as default exports. Sometimes we need to control the name of said default export when exported to the public.

I don't know, man. I mean, the tool looks solid. I just don't know if it is worth writing a big config for the tool vs actually writing the index file.

Thread Thread
 
nizami profile image
Nizami

Yes, you're right, for a small index file, it's hardly worth using additional tools.
However, your example from the repository was so versatile that I tried to go further and assist even in this case.

To use barrelize for such an index.ts file, the configuration would look like this:

{
  "$schema": "node_modules/barrelize/schema.json",
  "barrels": [
    {
      "root": "src/lib",
      "name": "index.ts",
      "include": ["**/*.ts", "**/*.svelte"],
      "exclude": [
        "**/*.test.ts",
        "**/*.test.svelte",
        "**/*.d.ts",
        "**/utils.ts"
      ],
      "replace": {
        "/\\.ts$/": ".js"
      },
      "exports": {
        "**/singleSpaContext.ts": ["/.+SingleSpaContext/"],
        "**/SspaParcel.svelte": ["*", "default as SspaParcel"]
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

And provided you change the index.ts file to the following content, so you don't lose code not related to the export:

// barrelize-start
// barrelize-end
import singleSpaSvelteFactory from './single-spa/single-spa.svelte.js';

/**
 * Creates single-spa lifecycle functions for a Svelte v5 component.
 * @param component Svelte component to mount as a single-spa micro-frontend or parcel.
 * @param domElementGetter Optional function that returns the DOM element where the component is mounted.
 * @param options Optional set of options, including Svelte mounting options.
 * @returns An object containing the single-spa lifecycle functions for the component.
*/
export const singleSpaSvelte = singleSpaSvelteFactory();

Enter fullscreen mode Exit fullscreen mode

After running npx barrelize, you will get the expected result in index.ts.

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

Yeah I've wasted way too much time fixing imports by hand - something like this would've saved me so many headaches lol

Collapse
 
webjose profile image
José Pablo Ramírez Vargas • Edited

Add a unit test for the index file:

describe('index', () => {
  test('Should export the exact expected content.', () => {
    const expectedExports = [
      'funcA',
      'funcB',
    ];
    const m = await import('./index.js');
    for (let k in m) {
      expect(expectedExports).to.include(k);
    }
    for (let e of expectedExports) {
      expect(Object.hasOwnProperty(m, e)).to.be.true;
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

Every time you add a new thing, come here and update the expectedExports array.