Make Your JavaScript Scripts Portable with Shebang

If you've been using Unix (or Linux, or any other variation thereof) for a while, then you've undoubtedly seen the semi-magic incantation

#!/bin/sh

at the top of shell scripts. Similarly, if you’re a JavaScript (or Node.js) developer, then you’ve likely come across a similar line when writing scripts.

It turns out that these lines, simple as they are, can have a significant impact on your development process—and understanding what they do and how they work can be very helpful.

But first, some history: The # character has long been called "hash" (as in "hashtag"), and the exclamation point is often known among developers as "bang" (so Scheme and Ruby programmers pronounce "foo!" as "foo-bang"). This combination is known as "hash-bang," or more commonly, "shebang." So, when you see a line starting with #!, that’s called a "shebang line."

What does such a shebang line do? It essentially lets you treat scripts, and other programs written in interpreted languages, as if they were executable binaries.

For example, let’s assume you’ve written a new script and saved it in a file called script.js. You can run this script by typing:

node script.js

and it’ll work just fine. But experienced developers prefer to execute scripts like this:

./script.js

(Note: The initial ./ ensures you’re running the program in the current directory rather than the first one that appears in your PATH, which is the environment variable listing directories where the Unix shell looks for programs.)

Shebang lines let us run programs in this way. We add the path of the interpreter (e.g., /usr/bin/node) to the top of our file:

#!/usr/bin/node

Now, if we run the program with ./script.js, Unix sees the first line and understands it should use /usr/bin/node to interpret the script, passing the contents of script.js to it.

But hardcoding the path can cause issues if Node is located in a different directory. You might develop on one computer where Node is in /usr/bin, but when you try to run the script on another computer, it fails because Node might be in /usr/local/bin or even in a custom location.

To make scripts more portable, use the following shebang line:

#!/usr/bin/env node

This line tells Unix to look in your PATH for the first occurrence of node. If you’re using a version manager like nvm (Node Version Manager) to switch between different versions of Node, it’ll use the version you’ve selected for the current project, thanks to env.

Just like in shell scripts, you can add flags to the shebang to alter how the script runs. For instance, if you want to enable debugging, you could add the --inspect flag to your shebang line like this:

#!/usr/bin/env node --inspect

Now, when you run the script, it will run with the Node.js inspector enabled for debugging.

And if you're developing on Windows, don’t worry. The shebang line won’t break your JavaScript code. On Windows, the shebang is simply ignored, as it’s treated as a comment (#) by both the operating system and JavaScript itself. So, even though the shebang line doesn’t serve any purpose on Windows, it won’t interfere with running the script.

This shebang convention is widely recommended. It only takes a few days to make this habit, and it makes your scripts far more portable. Plus, it’s fully compatible with version managers like nvm.

Get my free, weekly JavaScript tutorials

Want to improve your JavaScript fluency?

Every week, I send a new full-length JavaScript article to thousands of developers. Learn about asynchronous programming, closures, and best practices — as well as general tips for software engineers.

Join today, and level up your JavaScript every Sunday!

Thank you, Taha, for your amazing newsletter. I’m really benefiting from the valuable insights and tips you share.

- Remi Egwuda