Structuring Angular/React + Node.js Application for Heroku Hosting
So the primary intention for writing this article is to give a little head start for the beginners to structure out their application for a good hosting environment like Heroku. Heroku allows you to both Pipeline your application using a remote VCS tool like GitHub, which makes it so much easier, and to configure your application using Heroku CLI locally and push it remotely. Here we’ll discuss how to structure your content to connect your GitHub repository branch to deploy your application in Heroku.
Structuring your application is a very critical task which you have to reconcile at the very beginning. If you ever made the incorrect file structure then you might know what I am talking about.
The main concept
Well, it doesn’t matter what your client side framework is going to be. Eventually, you will build all of those files (This is prominent for a large framework like Angular) and get a
dist folder which contains an
So by referring to our main concept, it might be apparent to you that our root should not be the client side framework. Our root should be the server side. This is because whatever the client side framework you’re gonna use, it will get eventually built up and put into the server’s static content directory so that it is served up at the
Note: In large scale applications, the client is usually hosted in a web server such as NGINX and the server is hosted somewhere else (In a container, a physical server, etc.). In this case, the double-origin system still exists, but the proxying still needs to happen.
So it is wise if you keep your file structure as displayed in the image below.
Notice that this use MV* Pattern and the
client is where your Angular application lives.
Configure the client
Proxying to the backend.
Let us get this concept straight. To do that, we must consider both the production environment and the development environment. In the production environment, since Heroku will serve your application from their own origin (i.e. their own server space) when you make calls to your backend from the Angular application, you need to make calls to the same origin. For example, in a development environment where you spin up two ports one for Angular and one for Node, you make Angular service calls from port 4200 to the Node port 8080. But in production environments, like Heroku, you make requests to the same origin.
Let us go to that particular instance where you have two ports. Here’s a typical Angular HTTP call (via a service) which you make to the backend.
But soon after we change into the production environment, there is only one origin. There are no two ports but one. So we need to do the HTTP call like this.
To resolve this conflict between the source code in the services in two environments, we use a
proxy.conf.json file. Here is a sample config file.
What this will do is it will proxy all your HTTP requests which starts with /, to
http://localhost:8080 origin, thus we're able to keep the same service code throughout the two environments. But be sure to alter your start script in
package.json to serve up with a proxy. And make sure you serve your application using
npm start not
ng serve because we have configured a different start script.
Refer more to proxying to the backend from Angular official documentation.
This is an example for consuming from the back-end through an Angular service,
This is the endpoint of the back-end where the above service is hitting. Note that the picture below is a code snippet of a Java backend and I hope it is trivial to compare it with node.
Note that proxying the backend is a concept we configure in the development environment prior to doing any HTTP requests. If you configure it after implementing the services you would have to go through each service and replace
/. Therefore, implement all the services using proxies.
Building your client side
No matter how extensive the file structure of your client application (e.g. Angular, React or Vue) is going to be, it eventually is going to be built up to a
So, in Angular, you build the client side using
ng build — prod and in React you build using
npm run build . These build scripts are specified in
package.json . Building the application usually builds up a
dist folder where all the static content (
index.html and the JS files we’ve talked about) lives in. What should be done after building is to copy these files into the static files directory which you configure in the server side — which is our next topic - Configure the server.
Configure the server
So how exactly are we going to configure the server-side so that it serves up our client? That is where
public folder comes in.
In Express API, which is used as a Node Framework, you have the capability to specify the location of the static files. We us
static middleware to do this.
This eventually tells that the server needs to serve up the static content from
public folder, where the content of your build i.e. content of your
dist folder, lives in. Make sure that your server serves up
index.html which lives in the
dist folder is served up at
In development environments we used to serve up two applications, one being the Angular/React app and the server side app. But now, after configuring this, you can serve up your application using one origin that is, the port where your server is served up. Simply open
http://localhost:3000 (Your backend port) in your browser and you will get served up with the
index.html you’ve just built.
So that’s it. All you have got to do is to link your application in Heroku.
Create a new Heroku app in Heroku dashboard (In official site) and link your GitHub profile and the repository there.
Make sure you add the correct branch.
If you have some CI tools you can enable automatic deployments but I have not configured it so I didn’t enable it.
When it comes to the database you can configure a remote database using mLab and use that database in your server.js. If you have got a MySQL database or a GraphDB like Neo4j, you need to host the database somewhere and configure the credentials including host, username, password, database name, port (The database hosting service will provide you all these) etc. in your server-side database configurations. Doing this will point the server to the remote database where you host the database.
Note: In this article I went through how to structure your application so that you can deploy your application using the same remote repository which you use to do development work. However, you can take a different approach and use Heroku CLI to host your
server folder, which is the other approach that Heroku themselves suggests.
A little bit about Continuous Integration
However, I find it easier to use CI tools (Continuous Integration Tools) with Heroku being deployed with the remote repository, thus I can attach a pipeline to the production. Adding a pipeline to the production will reflect the commits we push to the remote repository in the production. CI tools are recommended by default since we are directly pushing to the production, (because of the pipeline) even a minor change could cause an adverse effect to the overall production. Thus, the CI tools provide an efficient platform to write scripts of tests which are to be run prior to the push towards the remote repository. In case of a failure of the tests (You can adjust how critical these tests can be for the production) you can adjust the CI tool to reject the push and prompt the errors or exceptions.