Using a Makefile with Your Web App
Automating command line tasks in your app build.
What is a Makefile and Why Use It?
In short,
a Makefile is a set of instructions, that’s it!
In long,
a Makefile is a file containing target commands that are executed using the UNIX ‘make’ utility. These targets are file based targets that the Makefile will look for, however, in our case, we are using the targets as commands rather than physical entities in the file system. So, we create ‘phony’ targets for our commands using .PHONY.
For example, in the very first line of the Makefile, we define out targets,
.PHONY:
install_web
run_web
run_server
run_client
build_clientMore on the above later!
Using a Makefile gives a way to easily organise file compilation, and commonly used terminal commands you will come across when running your web application.
For example,
yarn start // (or npm run start)
yarn // (or npm install)But, let’s say you have a client and server sub directory (as most modern web applications will), then you’ll have to cd from your root directory, into the server, run yarn (or npm install) and then run yarn start (or npm run start). Then, you’ll have to cd out of the server folder and into the client folder, run yarn (or npm install) again, and then run yarn start (or npm run start) again. Tedious terminal work if your are constantly starting and stopping you dev environment.
So, we use a Makefile to automate all of this!
I know some people will say “why not just use concurrently to run the package.json scripts simultaneously?”, which is of course an option! But, if you intend on containerising your application and keeping the client and server code independent (serving the client over NGINX maybe?) and deploying on a Kubernetes cluster, you’ll want the client and server to have their own package.json files!
Setting Up
In your root directory, we create the Makefile,
~/app/$ touch MakefileAs you can see, a Makefile has no file extension.
Then, create a folder to store the bash scripts the Makefile will use,
~/app/$ mkdir scripts && cd scriptsFor the SocioProphet web platform, we created the initial bash files for our Makefile,
~/app/scripts/$ touch install_web.sh run_web.sh run_server.sh run_client.sh build_client.shYou should then have a folder in your root directory as such,
Now that all the files have been created, we define our Makefile.
| # define 'phony' target commands (i.e. the following are not files) | |
| .PHONY: install_web run_web run_server run_client build_client | |
| # install dependencies for client and server | |
| install_web: | |
| cd socioprophet-web/scripts/ && bash install_web.sh | |
| # run client and server | |
| run_web: | |
| cd socioprophet-web/scripts/ && bash run_web.sh | |
| # local run server | |
| run_server: | |
| cd socioprophet-web/scripts/ && bash run_server.sh | |
| # local run client | |
| run_client: | |
| cd socioprophet-web/scripts && bash run_client.sh | |
| # build client | |
| build_client: | |
| cd socioprophet-web/scripts && bash build_client.sh |
Line 1 defines the targets, lines 5–6, 9–10, 13–14, 17–18, and 21–22 define what each of those target commands will do.
So, line 5–6 for example, tells the system to cd into socioprophet-web/scripts (or wherever you’d like to store the scripts folder) and then run the bash script install_web.sh using the command bash.
To run a Makefile command, use the make utility, for example,
make install_webwill execute in the terminal,
cd socioprophet-web/scripts/ && bash install_web.shNow to Write the Bash Scripts
install_web.sh
We will write bash commands in this file that will install all the dependencies for both the client and server sub directories.
In the first line of a bash file, it is useful to define the shell path.
#!/usr/bin/env bashThis of course assumes a dependency on bash, so if you are using a different shell, the definition may be different. (Bash however, is the default for the majority of systems).
The next two commands to install dependencies are,
cd .. && cd client && yarn
cd .. && cd server && yarn(The cd .. && cd client will be dependent on your project structure)
The final install_web.sh file,
| #!/usr/bin/env bash | |
| # install dependencies for client and server | |
| cd .. && cd client && yarn | |
| cd .. && cd server && yarn |
Now, when we run make install the following happens,
cd socioprophet-web/scripts/
bash install_web.sh
cd .. cd client
yarn
cd..
cd server
yarnEight separate commands, reduced to one!
Please note, the bash commands are dependent upon how you define your scripts inside of your package.json file.
Makefile and Bash Scripts Configuration for SocioProphet
Makefile
Defines the commands.
| # define 'phony' target commands (i.e. the following are not files) | |
| .PHONY: install_web run_web run_server run_client build_client | |
| # install dependencies for client and server | |
| install_web: | |
| cd socioprophet-web/scripts/ && bash install_web.sh | |
| # run client and server | |
| run_web: | |
| cd socioprophet-web/scripts/ && bash run_web.sh | |
| # local run server | |
| run_server: | |
| cd socioprophet-web/scripts/ && bash run_server.sh | |
| # local run client | |
| run_client: | |
| cd socioprophet-web/scripts && bash run_client.sh | |
| # build client | |
| build_client: | |
| cd socioprophet-web/scripts && bash build_client.sh |
For brevity of this post, I won’t post the gists for each .sh file below, however, all gists can be found on my GitHub at willjonestech.
install_web.sh
Installs client and server dependencies.
run_web.sh
Runs the server code in the background and runs the client code such that server and client are running simultaneously in one command make run_web.
run_server.sh
Runs the server code by itself.
run_client.sh
Runs the client code by itself using the webpack-dev-server.
build_client.sh
Builds the client code using Webpack into an output build directory
Further Note
Bash programming allows for variables to be defined, just like in any other language, so if you wanted, you could define variables that represent an npm package that you wanted to install. Therefore, you could have a make command such as make install_package that would run a bash script that would cd into the relevant directory and run yarn add <package name>.
The purpose of this would be never leaving the root directory in your terminal. New files, folders, binaries, anything can be created using the Makefile automation!

