Lots of my tasks embrace Node.js scripts to carry out setup or teardown steps. And whereas I might run all of them with the node
binary (node create-thumbnails
), I favor to take away the file extension and make the scripts executables (
). This strategy saves characters, and makes me really feel like a hacker!
My steps to create an executable are:
- Take away the
file extension (.js mv create-thumbnails
)..js create-thumbnails - Make the file executable (
chmod 744 create-thumbnails
). - Add a shebang (
#!/usr/bin/env node
) to sign that the executing shell ought to use thenode
binary.
Et voilà, you simply created a Node.js executable!
This strategy has served me nicely for CommonJS-based scripts utilizing the require
operate. But it surely’s 2022, and I deliberate to undertake ECMAScript modules in Node.js executables. Sadly, it isn’t that straightforward.
However what’s the issue?
There are 3 ways to allow ECMAScript modules in Node.js:
- use the
file extension.mjs - have a surrounding
package deal
with a.json "kind": "module"
subject - name
node
with the--input-type=module
flag
My executables ought to work and not using a file extension, which guidelines out the primary possibility. I additionally do not need to declare all recordsdata as module recordsdata or add a package deal
, so the kind
subject is out, too.
The --input-type
flag seems to be promising at first, but it surely solely works for strings you pipe into the Node binary your self.
echo "import { mkdir } from 'node:fs/guarantees';" | node --input-type=module
Why’s there no flag to allow modules when operating a file?
I spent the final quarter-hour studying Node.js points and discussions concerning the matter, and I nonetheless cannot reply this query. If you wish to learn extra, this is a really lengthy GitHub dialogue on why such a flag is not out there but.
Knock your self out, the dialogue takes many turns, and people have sturdy opinions!
There are a number of methods to make ECMAScript module-based executables work. All of them include barely completely different spins however use the identical trick.
Axel recommends the next for UNIX environments.
':'
import * as os from 'node:os';
const {username} = os.userInfo();
console.log(`Hey ${username}!`);
This snippet is wild! In brief, it does the next:
- the
cat
command reads the present file (the executable itself) - the file content material is then piped into
node
with the--input-type
flag - all the unique parameters are handed over to
node
, too ($@
) - the
node
name’s exit code is caught and propagated to the executable
This instruction makes the file learn and pipe itself into the node
binary as a result of there is no flag to allow modules. Wow! 🤯
As mentioned, this publish is just for my reference. Listed here are extra sources if you wish to study extra about different approaches or make it work on Home windows.