@howto/browser-modules
A sample repo demonstrating package.json config for a browser module published to NPM
Explainer
This is an example repo illustrating some concepts of creating browser specific NPM modules. While many (admittedly most) modules published to NPM are for Node environments, this repo is designed to illustrate how to create NPM modules only targeting web environments.
This demo does not cover isomorphic/universal modules (e.g. firebase, moment, etc), only code that you would load in a browser.
tl;dr
Ship both an ECMAScript Module (ESM) build and a CommonJS (CJS) build to your users. Do this by specifying the pkg.module
field for your ESM entrypoint, and the pkg.main
field for your CJS entrypoint.
If you are not shipping isomorphic code, avoid defining a pkg.browser
.
Key points
The main things to call to attention here are in the package.json
, specifically:
pkg.main
pkg.module
NOTE: You can see examples of the pkg.main
and the pkg.module
in this repos package.json
pkg.main
This is the standard CJS entrypoint to your module as defined by NPM. Bundlers like browserify, rollup and webpack all use this field as the entrypoint when no other entry points are defined.
Caveat: Though all the bundlers will respect this field, not all of the bundlers expect the same format or have the same behavior. It is best to also provide the pkg.module
explained below.
pkg.module
The Rollup wiki gives a really nice explainer of the rationale behind this field. As the module landscape moves from CJS => ESM* using ESM where possible will result in more performant apps across the board.
Webpack and Rollup both support this field OOTB which helps lower the barrier to writing a performant app.
pkg.browser
Many bundlers also support a pkg.browser
. However, this field is only really useful if you are shipping isomorphic libraries (i.e. libraries that run in both browser and Node.js environments). If you are only shipping a browser module, this field can be safely omitted.
Bundlers handle the absence of this field in different ways:
-
Rollup: Rollup doesn't care if you provide this field,
pkg.browser
is not something they support OOTB. Though you can support it via plugins, you have to specify that support yourself. -
Webpack: Webpack will use the
pkg.browser
if available. In the case that it cannot find a validpkg.browser
it will fallback to thepkg.module
followed bypkg.main
(i.e. precedence is:pkg.browser
>pkg.module
>pkg.main
) -
Browserify: Browserify will also use the
pkg.browser
if available. However, due to its current lack of ESM support, it will ignore thepkg.module
and fall back to thepkg.main
.
.mjs
(i.e. "Michael Jackson Script")
What about This is something that is being considered for Node environments but is currently not something that impacts browser modules. I will add another module talking about isomorphic modules, and will cover this there!
Installation
$ npm install --save @howto/browser-modules
Usage
ESM
import { sum } from "@howto/browser-modules";
sum(1, 2, 3, 4, 5);
CJS
const { sum } = require("@howto/browser-modules");
sum(1, 2, 3, 4, 5);
License
MIT © Josh Crowther