Introduction
This tutorial will show you how use npm
to get a public URL for your project.
By the end of this tutorial, you'll be able to run npm run expose
which will both start your app and give it a public URL.
In most cases, you won't need to do any firewall or networking config to make this work, because the traffic to the public URLs will automatically be tunneled through most networks and firewalls.
Prerequisites
- NodeJS. It comes with
npm
bundled in - A Linux, Mac or Windows machine with access to the internet
- Half an hour or so of your time
You should be able to get a Public URL even if you are on a corporate network, VPN or behind a firewall (caveat: If its a very paranoid firewall, this may not work, for example if you work for a big three letter government agency or another extremely security sensitive employer and you are trying this at their office. Try at home to be sure in this case).
Set up your project
Open up your package.json
file. If there is no package.json
file (brand new project?), create one with npm init
and follow the prompts.
You should have an entry in package.json
for a "start"
script. It should look like this:
{
"name": "Your Project",
"dependencies": {
"react": "17.0"
....
},
"scripts": {
"start: "<command to start your app>, i.e. node src/index.js"
}
}
If not, you should create one. It should look like "start": "<command to start your app>"
. Replace <command to start your project>
with the command you use to start your app, such as node src/index.js
if you use express
and have it set up in src/index.js
, or react-scripts start
for react projects created using create-react-app
.
You can now run npm start
to start your app using npm
. Thats useful even without a Public URL because you don't need to remember the command to start your app.
Find out what port number your app is listening on
You need to find out the port number your app is listening on. There are a few ways you can do this.
You can run npm start
. Usually the port number will be shown in the output. You might see output like 127.0.0.1:3000
or localhost:3000
. The port number is the number after :
, in this example output it would be port 3000
.
In express
, look for app.listen
. It will have the port number passed as a parameter.
For React apps, the default port is 3000
if you used create-react-app
, unless you've changed it.
If the port number is not the common port numbers of 80
or 443
, it will be in the last part of the URL you normally use when accessing your app locally, after the last :
i.e. for http://myapp.local:8000
, the port number is 8000
.
If there is no port number in the URL and the URL does not start with https
, your app is running on port 80
, which is the default port that HTTP clients such as web browsers use so it doesn't need to be specified in URLs.
If the URL does start with https
and there is no port number in the URL, the port number is 443
, which is the default HTTPS/SSL port.
Install expose
There is one dependency we need to satisfy before we continue. As npm
is just a dependency manager that relies on other software to provide most functionality (such as npm
dependencies), it can't get you a public URL by itself without extra help.
For this tutorial, you'll need to install expose
, an app I created specifically for this purpose. You can then configure npm
to use it to generate public URLs.
The process to install expose
is a bit different, but just as easy as installing an NPM dependency.
Go to https://expose.sh/install for instructions to install expose
. Its an easy one line copy and paste install for Linux and Mac, just copy and paste the code shown into a terminal.
A downloadable executable is available for Windows, which you will then need to copy somewhere in your PATH, such as C:\Windows\System32
using an account with Administrator permissons.
Add expose
to NPM
Adding expose
to npm
is a bit different to adding other dependencies.
Normally when adding dependencies to npm
you would add them to the "dependencies"
or "devDependencies"
section in package.json
or run npm install
. This would work for dependencies like libraries, but expose
is a separate app, kind of like grunt
or webpack
which are often installed globally.
So in this case, we'll add an entry to the "scripts"
section in package.json
because we are going to use npm
to launch your app with the "start"
script you created earlier and then launch expose
, which will give your app a Public URL. This is similar to how other projects often run grunt
or webpack
before starting the app.
In package.json
, look for the "scripts"
section. If there isn't one, create it.
Add this entry to the scripts section: "expose": "npm start & expose <insert your port number here and remove the arrows>"
;
For example, lets say my app listens on port 3000
, like most React apps. My package.json
file should look something like this:
{
"name": "Your Project",
"description": "The project you want to get a public URL for"
"dependencies": {
"react": "17.0"
....
},
"scripts": {
"expose": "npm start & expose 3000"
}
}
This script will start your app, then run expose
to give your app a Public URL.
Expose your app
Now run npm run expose
.
You'll see something similar to this in the output:
http://siiqwa.expose.sh is forwarding to localhost:3000
https://siiqwa.expose.sh is forwarding to localhost:3000
These public HTTP and HTTPS URLs are randomly generated. Hit them in a browser or any other HTTP client and the traffic will go to your locally running project. All traffic is passed from the https://expose.sh service to the the expose
client app, which is why you didn't have to do any complex networking or firewall config.
Traffic to the public URLs can easily tunnel through most corporate firewalls and networks.
You can also run expose
by itself for non node applications. For example expose 3000
will also create Public URLs, except you will need to run npm start
first otherwise the connections won't reach your app.
Randomly generated URLs are good to get started. They are public, so you can share them around with colleagues and friends. They should be accessible from any unrestricted internet connection in the world. Some things they might be useful for:
You're building a mobile app backend and want to connect to it from the app on your mobile device. Rather than plug a cable into your phone, configure USB debugging or do other complex config, you can expose your backend API with a public URL, then configure your mobile app to use this. No cables needed.
Webhook integrations. With a public URL a webhook provider can send a request directly to your locally running project, enabling you quickly test changes and use tools like debuggers to speed up development.
Local HTTPs. Normally to get HTTPs locally you need to buy a certificate and configure your web server to use it. Since you now have a https URL, you don't need to do this unless you really want to. HTTPS is required for certain features like Web Notifications and Progressive Web Apps.
Collaborative development. Maybe you're building a back end API and your colleague is building the React App that will use it, or vice versa. You can both generate public URLs for your projects and use them to integrate your work with each other or even other squad members. Feedback will be faster than deploying code to a remote server because you and your collaborators wont need to wait for deployments.
Demos. You can use the URL to demo your project to a colleague or someone else, just send them the URL.
More use cases and cookbooks can be found in the expose
documentation: https://expose.sh/docs/
Getting a custom URL that does not change
Because expose
by default generates random subdomains, using a custom subdomain (like myapi.expose.sh
) would save you from needing to reconfigure a different endpoint every time you run expose
.
Expose.sh is free to use for randomly generated subdomains. If you want to use your own custom subdomains like myreactapp.expose.sh
, you can do this for as little as $5.99/month depending on how many domains you want to use. This also supports the expose
service, which is run by an independent developer and doesn't have a big company behind it.
Here's an example package.json
using a custom subdomain.
{
"name": "Your Project",
"description": "The project you want to get a public URL for"
"dependencies": {
"react": "17.0"
....
},
"scripts": {
"expose": "expose 3000 as myreactapp.expose.sh"
}
}
With this config, running npm run expose
will now expose your project under the URL myreactapp.expose.sh
(assuming no one else has taken that subdomain):
https://myreactapp.expose.sh is forwarding to localhost:3000
http://myreactapp.expose.sh is forwarding to localhost:3000
Of course, you can also run expose
by itself without npm
. In this example you can run expose 3000 as myreactapp.expose.sh
, but you'll need to run npm start
first otherwise the traffic hitting the Public URLs won't reach your app because it won't be running.
You can Sign up here to get custom subdomains.
Limits
The Public URLs expire after several hours. They should be used for development but not for any apps in production. Don't use them to do anything involving extreme amounts of traffic like load testing, but serving an app or API is fine.
Conclusion
npm
scripts are useful for testing and building your app, now you can also use them to get a public URL.
As an independent developer, I don't have a big marketing department or investor funding to help me spread the word about expose
. So if you found this article useful, please share it around on your favourite social platforms like Facebook, Twitter and LinkedIn.
Also consider purchasing a subscription to help cover the costs of running the expose
service.
Happy coding!
Top comments (0)