DEV Community

EGOIST
EGOIST

Posted on

Bundle a TypeScript library with Bili

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.

Related Links

Top comments (3)

Collapse
 
renoirb profile image
Renoir

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.

Collapse
 
frank1e0927 profile image
Frankie

Egoist真强

Collapse
 
steveohoh profile image
steveo

Amazing work