How to package tool library gracefully


Words written in the front

In daily work, in order to improve development efficiency, we usually need to integrate some code abstractly, such as tool library and component library. These libraries are different from our business development projects. They are usually published in the form of NPM packages and called by others, so they need to be compiled and packaged in different ways.

What do you need to play?

Combined with the needs of the actual production environment, the general use scenarios are as follows:

  • Commonjs format: provided to   Webpack,   Browserify, or node environment, SSR, jest, etc
  • Format of es2015: directly provide modular solution for tree shaping
  • UMD format: various compatible
  • The < script > tag is injected and mounted to the browser window object or node global

Examples of communities

Redux   Package output for:
How to package tool library gracefully

  • Dist: UMD format, compatible   Windows or global, but also compatible with AMD, commonjs format
  • Es: es2015 style module
  • Lib: commonjs format
  • SRC: source code

Let’s take a look at the output configuration it packs

// package.json
  "main": "lib/redux.js",
  "unpkg": "dist/redux.js",
  "module": "es/redux.js",
  "types": "types/index.d.ts",
  "files": [

Existing community tools

  • Webpack
  • Rollup
  • Babel
  • That’s the name… It’s actually an alias for UMI library

With what tools?

Webpack, rollup and Babel are familiar to all of us, so we won’t repeat them one by one. The community generally recommends the packaging of tool libraries   Rollup and Redux are also used   Rollup package, but a little more configuration, look at the source code, probably with 200 + lines. Here we mainly talk about father, encapsulation based on Babel and rollup.

This is the characteristic of the official website:

  • ✔ ︎ document function based on docz
  • ✔ ︎ component packaging function based on rollup and Babel
  • ✔ ︎ support typescript
  • ✔ ︎ it supports the packaging of CJS, ESM and UMD formats
  • ✔ ︎ ESM supports the generation of MJS, which is directly used by browsers
  • ✔ ︎ support to package CJS and ESM with Babel or Rollup
  • ✔ ︎ support multi entry
  • ✔ ︎ support lerna
  • ✔ ︎ support CSS and less, support to open CSS modules
  • ✔ ︎ support test
  • ✔ ︎ pre commit checking with prettier and eslint is supported


Use it in the project to see if it is as fragrant as the document says

Source file to compile:

// src/index.js
const sum = (a, b) => a + b;
export default sum;

Configure the file.fatherrc.js

// .fatherrc.js
export default {
  entry: 'src/index.js',
  esm: { type: 'rollup', file: 'es/index' },
  cjs: { type: 'rollup', file: 'lib/index'},
  umd: { file: 'umd/index', name: 'father-test' }

How to package tool library gracefully
It’s more in line with our expectations. We output UMD, commonjs and es2015 codes respectively. Let’s take a look at the specific content.

Compiled code in es2015 format:

// dist/es/index.js
var sum = function sum(a, b) {
  return a + b;

export default sum;

Compile code in commonjs format:

// dist/lib/index.js
'use strict';

var sum = function sum(a, b) {
  return a + b;

module.exports = sum;

UMD format compiler code:

// dist/umd/index.js
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global = global || self, global['father-test'] = factory());
}(this, (function () { 'use strict';

    var sum = function sum(a, b) {
      return a + b;

    return sum;


On the whole, it is relatively fragrant. The configuration is very simple. It is suitable for the packaging of the toolkit. The output content is diversified and can meet different use scenarios.