Converts npm packages to native ES6 modules which can be imported directly from modern browsers without bundlers and transpilers.
For example, to install the react
package as a browser-compatible ES6 module run this command: npx esmy react
, or: npm init esmy react
, or: yarn create esmy react
. The file ./es_modules/react.js
will be created. Modern browsers can import it like this:
<script type="module">
import React from './es_modules/react.js';
console.log(React);
</script>
All modern browsers now support importing ES6 modules within <script type="module">
. They also support most of the other ES6+ features. So it makes feasible to get rid of the bloat of bundlers and transpilers at least during development.
Also, it's tempting to use the npm package registry as the largest source of third-party JavaScript code. But at the moment of writing, most of its packages are provided in the CommonJS format which is incompatible with ES6 modules. Although some of them are distributed as ES6 modules as well, package authors assume that they will be used in conjunction with bundles like webpack which are not strictly compatible with browsers' implementation of ES6 modules (e.g. extensions in import
s may be omitted: import './foo'
, or there may be 'unqualified' imports from node_modules
or Node.js packages: import 'foo'
, etc.)
esmy
solves this problem trying to build browser-compatible ES6 modules from npm packages on install time with the help of the Rollup bundler.
This project was inspired by jspm.io (not to be confused with the seemed to be obsolete jspm package manager) which provides CDN for browser-compatible ES6 modules compiled from npm packages.
To quickly install npm packages as browser-compatible ES6 modules, without installing esmy
itself, run (if you have npm >= 5.2.0
installed):
npx esmy react
For older npm
, or if your system has no npx
executable:
npm init esmy react
Or if you prefer yarn
and have it installed:
yarn create esmy react
If you have a project with package.json
and want to declare browser-compatible ES6 modules as dependencies than install esmy
as a development dependency either using yarn:
yarn add -D esmy
or using npm:
npm install -D esmy
It will install the esmy
command locally which can be run using one of these commands: yarn esmy
, npx esmy
, or ./node_modules/.bin/esmy
.
Then add the esmy
command to the "install"
script entry of package.json
:
{
"scripts": {
"install": "esmy"
}
}
It will build browser-compatible ES6 modules from npm packages declared in the "dependencies"
section in package.json
and put them in the ./es_modules
directory every time yarn install
or npm install
is performed.
If you pass any arguments to the esmy
command it will first try to run yarn
with these arguments if it's available, otherwise, it will run npm
with them. So you can pass any arguments (or options) yarn
or npm
understand.
Some npm packages (like react
) rely on the NODE_ENV
environment variable to provide different behavior under different environments like development
or production
. esmy
builds them with NODE_ENV=development
by default. You can override it (if you need to) passing an actual environment variable NODE_ENV
like this:
NODE_ENV=production esmy react
Some npm packages use the Node.js standard library which is not available in browsers and needs to be polyfilled. To make esmy
build them install npm packages rollup-plugin-node-builtins
and rollup-plugin-node-globals
as development dependencies and run esmy
locally which will use these plugins on a build. Note that not all standard Node.js modules can be polyfilled, see (readme)(https://github.com/calvinmetcalf/rollup-plugin-node-builtins/blob/master/readme.md) of rollup-plugin-node-builtins
for details.
- npm modules can export only default exports which
rollup-plugin-commonjs
(used under the hood ofesmy
) can convert to named ones most of the times. But sometimes it's not possible, see here. - ES6 modules implies operating in strict mode (like one you get with
'use strict';
). Some npm modules use non-strict (aka lousy mode) and may fail in strict mode. Therefore they can't be converted to ES6 modules without rewriting original npm modules, see here. - At the moment it's not possible to import submodules. E.g. it's a known issue for the
rxjs
package which exposes its API not only from an entry package module (require('rxjs')
) but also from its submodules (require('rxjs/operators')
). It may be addressed in nextesmy
versions. - If multiple packages depend on the same package than they all will include a copy of it in their compiled ES6 packages because of how bundling currently works. There are exclusions for some popular packages like
jquery
andreact
which are declared as external dependencies but you may expect some code duplication with other shared packages. A list of known external dependencies can be expanded by a pull request.