I was about to publish a module to NPM, when I thought about rewriting it in ES6, to both future-proof it, and learn ES6. I've used Babel to transpile to ES5, and run tests. But I'm not sure how to proceed:
- Do I transpile, and publish the resulting /out folder to NPM?
- Do I include the result folder in my Github repo?
- Or do I maintain 2 repos, one with the ES6 code + gulp script for Github, and one with the transpiled results + tests for NPM?
In short: what steps do I need to take to publish a module written in ES6 to NPM, while still allowing people to browse/fork the original code?
The main key in
package.json
decides the entry point to the package once it's published. So you can put your Babel's output wherever you want and just have to mention the right path inmain
key.Here's a well written article on how to publish an npm package
https://codeburst.io/publish-your-own-npm-package-ff918698d450
Here's a sample repo you can use for reference
https://github.com/flexdinesh/npm-module-boilerplate
If you want to see this in action in a very simple small open source Node module then take a look at nth-day (which I started - also other contributors). Look in the package.json file and at the prepublish step which will lead you to where and how to do this. If you clone that module you can run it locally and use it as a template for yous.
Node.js 13.2.0+ supports ESM without the experimental flag and there're a few options to publish hybrid (ESM and CommonJS) NPM packages (depending on the level of backward compatibility needed): https://2ality.com/2019/10/hybrid-npm-packages.html
I recommend going the full backward compatibility way to make the usage of your package easier. This could look as follows:
The hybrid package has the following files:
mypkg/package.json
Importing from CommonJS:
Importing from ESM:
We did an investigation into ESM support in 05.2019 and found that a lot of libraries were lacking support (hence the recommendation for backward compatibility):
.mjs
filesmocha@7.0.0-esm1
.mjs
files:Following José and Marius's approach, (with update of Babel's latest version in 2019): Keep the latest JavaScript files in a src directory, and build with npm's
prepublish
script and output to the lib directory..npmignore
.gitignore
Install Babel (version 7.5.5 in my case)
package.json
And I have
src/index.js
which uses the arrow function:Here is the repo on GitHub.
Now you can publish the package:
Before the package is published to npm, you will see that
lib/index.js
has been generated, which is transpiled to es5:[Update for Rollup bundler]
As asked by @kyw, how would you integrate Rollup bundler?
First, install
rollup
androllup-plugin-babel
Second, create
rollup.config.js
in the project root directoryLastly, update
prepublish
inpackage.json
Now you can run
npm publish
, and before the package is published to npm, you will see that lib/index.js has been generated, which is transpiled to es5:Note: by the way, you no longer need
@babel/cli
if you are using the Rollup bundler. You can safely uninstall it:A few extra notes for anyone, using own modules directly from github, not going through published modules:
The (widely used) "prepublish" hook is not doing anything for you.
Best thing one can do (if plans to rely on github repos, not published stuff):
src
from .npmignore (in other words: allow it). If you don't have an.npmignore
, remember: A copy of.gitignore
will be used instead in the installed location, asls node_modules/yourProject
will show you.babel-cli
is a depenency in your module, not just a devDepenceny since you are indeed building on the consuming machine aka at the App developers computer, who is using your moduledo the build thing, in the install hook i.e.:
"install": "babel src -d lib -s"
(no added value in trying anything "preinstall", i.e. babel-cli might be missing)
I like José's answer. I've noticed several modules follow that pattern already. Here's how you can easily implement it with Babel6. I install
babel-cli
locally so the build doesn't break if I ever change my global babel version..npmignore
.gitignore
Install Babel
package.json