@comandeer/rollup-lib-bundler
Super opinionated library bundler using Rollup, Babel and terser.
Installation
npm install @comandeer/rollup-lib-bundler --save-dev
Usage
Just make it a npm script:
"scripts": {
"build": "rlb"
}
Configuration
No configuration. Consider it a feature.
How does it work?
It gets package.json
from the current working directory, parses it and get neeeded info:
-
name
,author
,version
andlicense
to create beautiful banner comment, -
exports.import
for saving ESM bundle, -
exports.require
to get path for saving CJS bundle (optional).
Then the bundling happens. The default entry point for Rollup is src/index.js
. Please note that dist/
directory is purged before bundling! So if anything should be there alongside the bundle, it should be added there after the bundling.
Assumed file structure
This is very opinionated bundler and it assumes that the project's file structure looks like the one below:
package/
|- package.json
|- src/
| |- index.js
| |- some-other-chunk.js
|- dist/
| |- bundled-index.cjs
| |- bundled-index.cjs.map
| |- bundled-index.mjs
| |- bundled-index.mjs.map
| |- bundled-some-other-chunk.cjs
| |- bundled-some-other-chunk.cjs.map
| |- bundled-some-other-chunk.mjs
| |- bundled-some-other-chunk.mjs.map
-
package.json
is in the root of the package (the only bit we all agree on!), -
src/
directory contains package's source,-
index.js
is the main entrypoint of the package, -
some-other-chunk.js
is the optional additional entrypoint (see [#mutliple-bundles](Multiple bundles) section for more info),
-
-
dist/
directory contains bundled code.
Multiple bundles
By default, src/index.js
is treated as the only entry point. However, using subpath exports you can create several bundled chunks/files. Example:
"exports": {
".": {
"require": "./dist/package.cjs",
"import": "./dist/package.mjs"
},
"./chunk": {
"require": "./dist/chunk.cjs",
"import": "./dist/chunk.mjs"
}
}
In this case two source files will be bundled:
-
src/index.js
:- ESM output:
dist/package.mjs
, - CJS output:
dist/package.cjs
,
- ESM output:
-
src/chunk.js
:- ESM output:
dist/chunk.mjs
, - CJS output:
dist/chunk.cjs
.
- ESM output:
Although Node.js supports several different syntaxes for subpath exports, this bundler supports only the form presented on the example above (so each subpath needs two properties – require
for CJS bundle and import
for ESM bundle).
Each subpath is translated to appropriate file in src
directory. Basically, ./
at the beginning is translated to src/
and the name of the subpath is translated to <subpath>.js
(e.g. ./chunk
→ src/chunk.js
). The only exception is the .
subpath, which is translated to src/index.js
.
As of version 0.19.0 the bundler also automatically omits bundling bundles inside other bundles. If there were an import of the src/chunk.js
file inside the src/index.js
file in the above structure, then the dist/package.(c|m)js
file would contain an import from dist/chunk.(c|m)js
file instead of the content of the other bundle.
TypeScript support
Starting from v0.17.0 the bundler is able also to bundle TypeScript projects. There is no configuration needed, just replace the .js
extension with the .ts
one! Also ensure that there's a valid tsconfig.json
file in the root of your project. If you want to provide different configuration for the bundler, place a tsconfig.rlb.json
file instead.
The bundler also bundles .d.ts
files but only if you specified the exports.types
field in your package.json
.
Sample configuration for a TS project:
"exports": {
".": {
"require": "./dist/index.cjs",
"import": "./dist/index.mjs",
"types": "./dist/index.d.ts"
},
"./chunk": {
"require": "./dist/chunk.cjs",
"import": "./dist/chunk.mjs"
}
}
In this case two source files will be bundled:
-
src/index.ts
:- ESM output:
dist/index.mjs
, - CJS output:
dist/index.cjs
, - DTS output:
dist/index.d.ts
,
- ESM output:
-
src/chunk.ts
:- ESM output:
dist/chunk.mjs
, - CJS output:
dist/chunk.cjs
, - DTS output: none (there's no
types
field).
- ESM output:
Bundling binaries
From v0.19.0 rlb
can also bundle binaries defined in the bin
field of the package.json
. It supports both the simple format of that field and the complex one. Source files for binaries must be placed in the src/__bin__
directory with the same name as in the bin
field. All source file formats supported for exports
bundles are also supported for the bin
ones.
All bundles created from the bin
field are saved in the ESM format. The bundler will also preserve shebang in the produced bundle. Please also note that in case of referencing some other bundles inside executables, their ESM versions will be used.
bin
format
Example with the simple {
"name": "some-package",
"exports": {
".": {
"import": "./dist/index.mjs"
}
},
"bin": "./dist/bin.mjs"
}
In that case bundler excepts the following source file structure:
some-package/
|- package.json
|- src/
| |- index.js
| |- __bin__/
| | |- some-package.js
Please note that when using the simple bin
format (so just the path to the executable, without its name), the bundler will look for the source file with the name of the package (derived from the name
field in the package.json
files).
bin
format
Example with the complex {
"name": "some-package",
"exports": {
".": {
"import": "./dist/index.mjs"
}
},
"bin": {
"whatever": "./dist/bin.mjs",
"another-one": "./dist/bin2.js"
}
}
In that case bundler excepts the following source file structure:
some-package/
|- package.json
|- src/
| |- index.js
| |- __bin__/
| | |- whatever.js
| | |- another-one.js
License
See LICENSE file for details.