Bili is a bundler built on the top of Rollup, it can be really convenient if you wanna bundle your library in multiple formats, nowadays it's pretty common to build a JavaScript library that works in CommonJS, UMD and ES Modules.
Bili also works with TypeScript seamlessly, this post will walk you through creating a simple TypeScript library.
Get Started
Let's get started by creating a new project to learn how to use TypeScript with Bili:
mkdir my-lib
cd my-lib
yarn init -y # Create a package.json
yarn add bili --dev
Next install TypeScript related dependencies:
yarn add typescript rollup-plugin-typescript2 --dev
We will use rollup-plugin-typescript2 instead of the official rollup-plugin-typescript because the latter does not perform type-checking during compilation.
Now Bili will automatically use rollup-plugin-typescript2 if you're building a .ts
file.
TypeScript Config
To let TypeScript perform proper type-checking, a tsconfig.json
is necessary, you can create one by running the TypeScript compiler with --init
flag:
yarn tsc --init
Feel free to tweak the options in tsconfig.json
to suit your needs.
Bundle in Multiple Formats
We will create a src/index.ts
in my-lib
:
# Create src/index.ts
mkdir src
echo "export default 42" > src/index.ts
# Bundle it in CommonJS and ESM format
# Omit `--format <format>` to bundle in CommonJS only
yarn bili src/index.ts --format cjs --format esm
Then src/index.ts
will be bundled to dist/index.js
:
'use strict';
var index = 42;
module.exports = index;
And dist/index.mjs
:
var index = 42;
export default index;
It's recommended to add dist
(generated by Bili) and .rpt2_cache
(generated by rollup-plugin-typescript2) in .gitignore
file.
Generate Declaration Files
To generate corresponding .d.ts
files for files in src
folder, first you need to enable compilerOptions.declaration
in your tsconfig.json
:
{
"compilerOptions": {
"declaration": true
}
}
Then create bili.config.ts
to configure TypeScript to include src
folder only:
import { Config } from 'bili'
const config: Config = {
plugins: {
typescript2: {
// Override the config in `tsconfig.json`
tsconfigOverride: {
include: ['src']
}
}
},
// Let's take this opportunity to move the CLI flags here as well
input: 'src/index.ts',
output: {
format: ['cjs', 'esm']
}
}
export default config
Note that we didn't set include: ['src']
in tsconfig.json
directly, because in most cases your editor like VS Code will use that file by default and you don't want other files like ./my-lib/test/index.test.ts
to be excluded.
Finally let's run yarn bili
and the declaration file will be generated to dist/index.d.ts
:
declare const _default: 42;
export default _default;
Configure package.json
{
"name": "my-lib",
"main": "dist/index.js",
"module": "dist/index.mjs"
"types": "dist/index.d.ts",
"files": ["dist"],
"scripts": {
"build": "bili",
"prepublishOnly": "npm run build"
}
}
Now you can publish it on npm and the types can be found when others are using it.
Check out https://github.com/egoist/objql for a simple real-world TypeScript library.
Top comments (3)
This is amazing!
Code changed a lot since last time I imported it.
TypeScript definitions and typings annotations are also nice.
Thanks!
While experimenting with the version bump, I realized maybe I misunderstood how to make different bundles not just by format, but by target runtime (e.g. Jest test runner, browser, etc).
I'm experimenting github.com/renoirb/experiments-201... this in this reproduction repository, and opened a ticket.
I will contribute documentation once I've understood how to do it properly. I must be missing something.
Amazing work