@apec1/barrel-loader
v1.0.4
Published
High-performance barrel file loader for webpack/rspack using Rust NAPI bindings
Downloads
369
Maintainers
Readme
barrel-loader
High-performance barrel file optimization for webpack and rspack, powered by Rust + NAPI.
barrel-loader rewrites index.ts/js/tsx/jsx barrel files into clean, explicit, deduplicated exports. It is designed for large codebases where deeply nested export * chains can slow builds and create noisy bundles.
Table of Contents
- What this solves
- How it works
- Features
- Install
- Quick start
- Loader options
- Examples
- Behavior notes
- Debugging
- Build from source
- Architecture
- Troubleshooting
- Contributing
- License
What this solves
In many projects, barrel files gradually become chains of wildcard exports:
// src/index.ts
export * from './components'
export * from './hooks'
// src/components/index.ts
export * from './button'
export * from './input'This creates a few common issues:
- Duplicate re-exports from different paths
- Harder-to-predict export surfaces
- Slower parsing and transform work in large projects
- Mixed value/type export handling edge cases
barrel-loader resolves these by parsing and flattening export graphs, then reconstructing a normalized barrel output.
How it works
Pipeline at build time:
- Parse exports (native Rust parser)
- Resolve nested barrels recursively
- Expand namespace exports when configured
- Remove duplicates
- Sort output deterministically
- Reconstruct the final barrel source
Core execution path is native (Rust + NAPI), with selective JavaScript handling around integration logic.
Features
- Native Rust parsing and transforms via NAPI
- Webpack + rspack loader compatibility
- Recursive barrel resolution
- Namespace-to-named expansion support
- Type-aware export reconstruction
- Deterministic output ordering
- Verbose and debug logging modes
Install
pnpm add @apec1/barrel-loader
# or
npm install @apec1/barrel-loaderRuntime requirements:
- Node.js >= 18
- macOS or Linux (Windows is not officially supported)
Quick start
webpack
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\/index\.(ts|tsx|js|jsx)$/,
use: [
{
loader: '@apec1/barrel-loader',
options: {
verbose: false,
convertNamespaceToNamed: true
}
}
]
}
]
}
}rspack
// rspack.config.mjs
export default {
module: {
rules: [
{
test: /\/index\.(ts|tsx|js|jsx)$/,
use: [
{
loader: '@apec1/barrel-loader',
options: {
verbose: false,
convertNamespaceToNamed: true
}
}
]
}
]
}
}Loader options
type BarrelLoaderOptions = {
resolveBarrelFiles?: boolean
removeDuplicates?: boolean
sort?: boolean
convertNamespaceToNamed?: boolean
verbose?: boolean
}| Option | Type | Default | Description |
|---|---|---|---|
| resolveBarrelFiles | boolean | true | Resolve nested barrel chains recursively |
| removeDuplicates | boolean | true | Deduplicate repeated exports |
| sort | boolean | false | Sort exports deterministically |
| convertNamespaceToNamed | boolean | false | Convert export * to explicit named exports when resolvable |
| verbose | boolean | false | Emit loader stage logs |
Examples
1) Flatten nested barrels
Input
// src/index.ts
export * from './ui'
// src/ui/index.ts
export * from './button'
export * from './input'Typical output intent
export { Button } from './ui/button'
export { Input } from './ui/input'2) Convert namespace exports to named exports
With convertNamespaceToNamed: true:
// before
export * from './file'
// after (when analyzable)
export { fnA, fnB, fnC } from './file'3) Preserve type exports
// source
export * from './runtime'
export * from './types'
// output keeps value/type semantics distinct
export { run } from './runtime'
export type { User, Session } from './types'4) Enable trace-level diagnostics for local debugging
BARREL_LOADER_DEBUG=true pnpm buildThis enables detailed logs from parser/resolver stages and writes debug output files for transformed barrels.
More examples: docs/EXAMPLES.md
Behavior notes
- The loader targets barrel-like entry files (
index.ts/js/tsx/jsx) in your rule configuration. - Current transforms are export-focused; direct declaration rewriting is intentionally limited.
- Native addon load failures can surface as fallback warnings, but build behavior depends on where the failure occurs.
Debugging
Environment flags:
BARREL_LOADER_DEBUG=true→ deep debug logs +.debug.tsoutputs for transformed filesBARREL_LOADER_VERBOSE=true→ verbose parse/resolve logging
Example:
BARREL_LOADER_DEBUG=true BARREL_LOADER_VERBOSE=true pnpm buildBuild from source
Fast path
./setup.sh
./build.shCommon scripts
pnpm build # Rust + TypeScript
pnpm build:rust # Rust only
pnpm build:ts # TypeScript bundles only
pnpm build:debug # Debug Rust build + TypeScript
pnpm test # JS integration checks
pnpm test:rust # Rust tests
pnpm lint # biome + clippy
pnpm fmt # biome + rustfmtBuild artifacts
native/barrel_loader_rs.nodedist/index.cjsdist/index.mjsdist/index.d.ts
Architecture
Rust side
src/lib.rs– top-level native modulesrc/types.rs– shared NAPI object shapessrc/rs_utils/parser/*– export parsingsrc/rs_utils/deduplication.rs– dedupe logicsrc/rs_utils/sorting.rs– deterministic sortsrc/rs_utils/reconstruction/*– source regeneration
TypeScript side
src/barrel-loader.ts– loader orchestrationsrc/ts-utils/resolve-barrel.ts– recursive traversalsrc/ts-utils/resolve-utils.ts– export expansion helperssrc/ts-utils/native-addon.ts– native addon bridgesrc/index.ts– package entry and exports
Bundling
rslibemits CJS + ESM bundles todist/- Native
.nodeaddon is copied tonative/anddist/during build
Troubleshooting
A full troubleshooting guide is available here:
It includes fixes for:
- Rust files accidentally parsed by rslib/rspack
- Native addon field mismatch errors (
exportTypevsexport_type) rslib: command not foundafter cleaning dependencies- pnpm side-effects cache vs rspack build cache confusion
- Native addon load failures and clean rebuild strategy
Contributing
Contributions are welcome.
Recommended contribution workflow:
- Open an issue describing the problem/feature
- Add or update tests (
pnpm test,pnpm test:rust) - Keep docs in sync (
README,docs/*) - Run lint/format before opening PR
Release and publish details: PUBLISHING.md
License
MIT
