I like modern Nodejs. Destructuring is probably my favorite feature.
1 | const {map, prop} = require('ramda') |
Yet, this syntax breaks for anyone using Node 4 (some people) or Node 0.12
(why are they still using it?!) So I usually get requests to remove an ES6
feature because Node 4 users cannot use one of my modules. Or a request
to downgrade Node engine declared in the package.json
file.
One can quickly check if a module at least loads on Node 4
1 | nvm use 4 |
If the module does not load on Node 4, it is probably using one of the missing / behind a flag features. We should make our module Node 4-compatible, right?
Here is a problem. I could set up transpiler and build Node 4-compatible source code before publishing. Yet this does not fully solve the problem. Often the offending code is NOT my own, but instead comes from one of many many dependencies used during development and semantic release!
So there are really four problems:
- making sure my own code is Node 4 compatible. Self-discipline and transpiling help.
- running tests should use Node 6 because the testing tools keep improving. I am not going to downgrade my snap-shot!
- I still want to test if the package can be used from Node. Note that
this is not even a subset of all tests, but rather is a
demo
script. - finally, the publishing to NPM registry should use Node 6. While I use semantic-release and [semantic-action][semantic-action] which run on Node 4, their plugins might not.
Here is my typical project setup, simple-changelog is a good example.
package.json
andREADME.md
say that this module works on Node 41
2
3
4
5{
"engines": {
"node": ">=4"
}
}Travis CI runs against both Node 4 and 6. For example see .travis.yml file.
1
2
3node_js:
- '4'
- '6'
Some of the modules do not really like NPM@2 that comes with Node 4, so I install NPM@3 before installing dependencies
1
2
before_install:
- npm install -g npm@3
BUT the Travis CI only runs the "demo" step on all Node versions. It only runs the unit tests on Node 6. While this might miss a few edge cases, it allows to keep upgrading all
devDependencies
without holding back. To only run a command on Node 6 I use if-node-version1
2
3script:
- npm run demo
- $(npm bin)/if-node-version ">=6" npm testA demo could be complex or just
node .
to make sure there are no obvious syntax incompatibilities.Publishing to NPM should also happen from Node 6. Because Travis sometimes gets confused by multiple jobs with error
This test run is not the build leader
(see issue) we need to hack the command a little bit, since we are limiting it to Node 6 anyway (I assume that you only have single Node 6 version in the build matrix)1
2after_success:
- TRAVIS_JOB_NUMBER=WORKAROUND.1 $(npm bin)/if-node-version ">=6" npm run semantic-release
That's it. While dirty, this approach of Node 4 for a demo + Node 6 for everything else seems to satisfy most of my own and my users' needs.
Transpiling
What if you really wanted to transpile your own source code? The setup using
Babel is very simple. Create .babelrc
file and use env
preset
and specify target version of Node 4
1 | { |
Setup transpile command in the package.json
to grab the entire folder
and (optionally) copy some files without transpiling them.
1 | { |
The above long command run the transpile
step before publishing to NPM and
includes just src
folder in the distribution.
3rd Party Modules
What about all the 3rd party modules? How can we make them compatible with Node 4? Can we open an issue for each module and expect things to be fixed for us? Without paying money for this?
I always think that a customer can ask for IE6 support, but will have to pay for it. I am interested in modern tools, and if you want to support something I am not interested in doing, well, it should then pay my bills.
After talking to Jamie Mason about it, we have decided that the most transparent solution for this would be to implement on-demand NPM registry proxy service that would transpile source files to Node 4. That's a great idea, Jamie! It might be a little extra effort to implement, but could work.
This service would sit between you and the public registry. Every time you ask for a package with specific version, it would fetch it from the public registry, test against Node 4, and if it does not load, would transpile the files. Of course, the transpiled bundle will be stored for the future.
Anyone thinks it is a bad idea? I can see enterprise customers paying for this...