Sunday, January 5, 2020

Experimental Node Mode

The latest Long-Term Support (LTS) version of Node.js has support for writing and consuming modules in ECMAScript style - without any tools or frameworks. That is good news! I have mostly been writing back-end code using the CommonJS standard, but have always preferred the ECMAScript way, commonly used in front-end development with tools like Babel.

Now, with Node.js 12, there is native support for ECMAScript modules. But it has to be manually enabled, by using the '--experimental-modules' flag.

The current version - Node.js 13 - doesn't need a flag to enable ECMAScript modules. Great! It is on by default. But the runtime will log a message on startup, a warning that the feature is not ready for production yet. Maybe we can expect it to be a default setting, without experimental warnings, in the next LTS later this year?

I have tried out ECMAScript modules in Node.js, using the experimental flag and the type: module in package.json.


WebStorm IDE with ES Module support
Import tooling support, not perfect, but good enough.

Cool, but not perfect yet
I ran into issues when writing & running unit tests. My favorite unit testing library is tape, but it doesn't support ECMAScript modules natively:
Must use import to load ES Module

What about the AVA test runner ? No native support yet. Mocha? I couldn't find any info about it, but tests won't run.

Tape is just JavaScript 👍
It is convenient, but tape unit tests doesn't require the built in runner. Both AVA and Mocha need a runner. Using tape, you can run the unit tests just like any other JavaScript file with the Node.js CLI.

Don't try this at ... work?
Besides that using a default unit testing runner usually is a good thing, there's also a huge drawback with the experimental & non-standard approach that I describe in this post. The node command will run a single file only. 👀 

But, hey, we're in Experimental Mode right! A workaround would be to execute a custom runner containing all our unit tests. Just don't forget to add every new file to it.

"scripts": {
    "test": "node --experimental-modules test/run.js | tap-spec"
}

(from the script section of package.json)

The test/run.js file:
import 'path-to-unit-test'
import 'path-to-another-unit-test'


Try this at home, folks. Don't try it at work (yet). 🏡

No comments: