a snapshot of the terminal showing the output of env dash dash help command
a snapshot of the terminal showing the output of env dash dash help command

JavaScript is an interpreted language and its source code needs to be fed to some interpreter to run. If you want to run a JavaScript file using Node.js, you normally run this command:

$ node yourfile.js
$ ./yourfile.js

Shebang

Shebang or hashbang (#!) is the first line of the file which tells the OS which interpreter to use. It typically looks like this:

#!/absolute/path/to/the/interpreter [optional params]
#!/usr/bin/node

Say hello to env

env is primarily intended to run a command in a modified environment. The emphasis here being “a command” because env is almost always at /usr/bin/env while “a command” can be anything that’s on the PATH.

The short answer

This is the most common shebang for Node scripts:

#!/usr/bin/env node

Pass parameters to Node.js

Passing the -S option to env causes it to parse whatever comes after which opens up a new door: passing parameters to the command.

#!/usr/bin/env -S node --experimental-module
#!/usr/bin/env -S node -r ./my/other/file.js
#!/usr/bin/env -S node --inspect

Set environment variables

Remember we said env can run a command in a modified environment? That’s actually where it gets its name and it’s very powerful. Let’s say we want our script to run in production mode. We could set the NODE_ENV environment variable:

#!/usr/bin/env -S NODE_ENV=production node
#!/usr/bin/env -S NODE_OPTIONS=--experimental-modules node

Start with an empty environment

If we wanted the script to run without access to any environment variable at the user’s terminal, we could run it with the -i flag which stands for “ignore environment”:

#!/usr/bin/env -S -i node
#!/usr/bin/env -S - node

Force-disable DEBUG

Maybe we don’t want to clear all environment variables but block-list a few of them. An example is DEBUG (if you’re using the popular debug package). Maybe we don’t want the users of the scripts to set the flag when running it as a script. Then we’d use the -u flag which stands for unset environment variable.

#!/usr/bin/env -S -u=DEBUG - node

Lock the Node.js runtime version

Sometimes you want to lock the node version that is used to run a script. Prior to NPM@3 we could use engineStrict, but that feature is removed and now we can only set the engines in package.json which may or may not exist next to the script and depends on setting the engine-strict config flag.

#!/usr/bin/env -S npx node@6

Run it with TypeScript

There’s no rule that says we have to run node. Assuming typescript and ts-node are available globally (npm -i g typescript ts-node), we could specify ts-node as the interpreter:

#!/usr/bin/env ts-node

References

Written by

Knowledge Worker, MSc Systems Engineering, Tech Lead, Web Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store