Re-exports and Barrel Files
Sometimes one module imports code from another module and exports it again.
This is called a re-export.
Re-exports are often used to create cleaner import paths.
Basic Re-export
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}Another file can re-export those functions:
// index.js
export { add, subtract } from "./math.js";Now another module can import from index.js:
import { add } from "./index.js";Export Everything From Another Module
You can re-export all named exports.
export * from "./math.js";This exports all named exports from math.js.
It does not re-export a default export automatically.
Barrel Files
A barrel file gathers exports from several files into one file.
Example folder:
utils/
index.js
formatters.js
validators.js
math.js// utils/index.js
export * from "./formatters.js";
export * from "./validators.js";
export * from "./math.js";Then another file can import from the folder entry point:
import { formatDate, isValidEmail, add } from "./utils/index.js";With bundler configuration, some projects allow:
import { formatDate } from "./utils";But plain browser modules usually need the explicit file path.
Re-exporting With Aliases
You can rename exports while re-exporting.
export { formatDate as formatDisplayDate } from "./formatters.js";Then import:
import { formatDisplayDate } from "./utils/index.js";Aliases can make exports more descriptive at module boundaries.
Re-exporting Default Exports
Default exports need special syntax.
// Button.js
export default function Button() {}Re-export as a named export:
// index.js
export { default as Button } from "./Button.js";Then import:
import { Button } from "./index.js";This pattern is common in component folders.
Why Use Barrel Files?
Barrel files can make imports cleaner.
Without a barrel:
import { formatDate } from "./utils/formatters.js";
import { isValidEmail } from "./utils/validators.js";
import { add } from "./utils/math.js";With a barrel:
import { formatDate, isValidEmail, add } from "./utils/index.js";This can be convenient.
When Barrel Files Can Hurt
Barrel files can also make code harder to trace.
If index.js exports too much, it becomes unclear where code really comes from.
import { doSomething } from "./utils/index.js";You may need to open multiple files to find the original definition.
Barrel files can also create circular dependencies if used carelessly.
Use them when they make imports clearer, not just shorter.
Public API of a Folder
A good barrel file acts like a public API for a folder.
components/
Button.js
Modal.js
Input.js
index.js// components/index.js
export { default as Button } from "./Button.js";
export { default as Modal } from "./Modal.js";
export { default as Input } from "./Input.js";Other parts of the app can import from the folder's public entry point.
import { Button, Modal } from "./components/index.js";Best Practices
Use re-exports to create clear public module boundaries.
Keep barrel files focused.
Avoid exporting unrelated code from one barrel.
Be careful with circular dependencies.
Use explicit imports when they are clearer than barrel imports.
Re-export default exports as named exports when it improves consistency.
Common Mistakes
Mistake 1: Expecting export * to Include Defaults
export * from "./Button.js";This does not automatically re-export the default export.
Use:
export { default as Button } from "./Button.js";Mistake 2: Creating a Giant Barrel
// everything/index.js
export * from "../api.js";
export * from "../components/index.js";
export * from "../utils/index.js";
export * from "../config.js";This can hide where things come from.
Mistake 3: Using Barrels to Avoid Thinking About Structure
Barrel files should clarify the public API.
They should not hide a messy folder design.
Summary
Re-exports let one module export values from another module.
export { name } from "./file.js"re-exports selected names.export * from "./file.js"re-exports named exports.- Default exports need special re-export syntax.
- Barrel files gather exports into an entry file like
index.js. - Barrel files can make imports cleaner.
- Overused barrel files can hide dependencies and create confusion.