Simpler Dev Environments with Procfiles
Tags: node, tooling
Published: 2022-06-01 19:50:55

---
title: Simpler Dev Environments with Procfiles
published: true
description: Use Procfiles to turn multiple startup commands into a single one.
tags: nodejs, tooling
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ige13faq43xsh6sji8ha.jpg
---

Throughout the time, I've tried a number of different ways to manage my development environment. From Make files, to [PM2][1] and [Tmux][2]. 

Tmux, is well.., tmux. [Tmuxinator][3] makes it manageable, but the "layout" definition is far from readable, and copying errors from history to your clipboard, is a true pain in the ass.

I still recommend taking a look at PM2 if you need more than "get things running". It comes with a lot of options, but that also means that your config script comes with some verbosity. 

This article explains how I cover my simple use cases. Those that don't require additional file watchers (see PM2), or split panes to separate logs while sticking to a single terminal (see Tmux). For those, I use Procfiles.

## No fear, Procfile is here!

Procfile? Yeah, the first time I heard it I was "*not another make file, right?!*". And luckily, it's nothing like that. Let's get started.

So a Procfile is a simple `key: command` format. And much like a Dockerfile, it's by convention named after the format. I recommend creating file named `Procfile` in the root of your project, and commit it to your repo. If not for yourself, than for every new contributor that one day joins your team.

For [MagicBell][8], our procfile looks as follows:

```
server: bin/rails s -p 3000 -e development
worker: bin/bundle exec sidekiq
webpack: bin/webpacker-dev-server
```

That's it. That's all the config you need to get multiple services up and running through a single command. 

Obviously, we still need to install a runner to handle this procfile. Meet [foreman][4], or one of it's forks. Foreman is a Ruby script, so for that you'll need to have Ruby installed. There are many forks though. Such as [shoreman][5], which is a dependency free shell script, or [node-foreman][6], which is a javascript fork. I go with node-foreman, for the simple reason that I'm a node guy and I like that I can `npm install` it to the dependencies of my node projects.

So, go ahead, and install `node-foreman`. For the sake of this howto, let's go global. Drop the `-g` if you have a concrete project at hand.

```
npm i -g node-foreman
```

Node-foreman installs a binary named `nf`. With this installed, it's as simple as running `nf start` in the same directory as your `Procfile`. Try it, and see all your services spin up and log to the same terminal. When you have an `.env` file in the same directory, `node-foreman` automatically loads all environment variables from it. If your env file is named differently, say `.env.development`, you can specify it with the `--env` flag. Use the `--procfile` flag if you need to specify a Procfile.

## A bit more… tabs

The above might be all you need. But sometimes, I like to have my startup process a bit personalised. For that, I use scripts that I store under my home directory. 

For MagicBell, my config exists of two files. One custom procfile, saved as `~/scripts/magicbell.proc`:

```
server: bin/rails s -p 3000 -e development
worker: bin/bundle exec sidekiq
webpack: bin/webpacker-dev-server
codegen: yarn codegen -w
```

And the "executable" script that I run, saved as `~/scripts/start-magicbell` (don't forget to `chmod +x`)

```
#!/usr/bin/env bash

cd ~/dev/magicbell/backend
ttab docker-compose up

bundle install
yarn install
yarn db:migrate
 
nf start -j ~/scripts/magicbell.proc -e .env.development
```

When read that script, you'll notice `ttab`. [ttab][7] is a small utility that allows us to start commands in a new terminal tab. That way, I can start postgres & redis in one terminal instance (tab) while running everything else in another. Ttab is optional, but I highly recommend using it for simplicity.

```
npm i -g ttab
```

As I've added `~/scripts` to my `PATH`, I can get the MagicBell environment up and running using a single `start-magicbell` command. Let me walk you trough wat it does:

- first, it navigates to the git repo on my drive, at `~/dev/magicbell/backend`
- runs `docker-compose up` in a new tab, detached from the current
- installs all ruby gems, while the db is spinning up
- installs all node modules
- runs our database migration script
- starts the four services defined in the procfile

With this single command, I've started 6 services and ran some install/migrate commands. It happened too often that I manually had to install new gems or modules after pulling changes. Those commands are fast enough to run as part of my startup, yet take enough time for the database to be online before the server starts.

That's it. Both [node-foreman][6] and [ttab][7] come with a bunch of options. So be sure to check out their readmes (especially from node-foreman!)

---

_:wave: I'm Stephan. Follow me on [Twitter](https://twitter.com/meijer_s) if stuff like this has your interest._



[1]: https://dev.to/smeijer/simplify-your-dev-environment-with-pm2-2288
[2]: https://gist.github.com/smeijer/0e3604a51e9393d2ac009cef6ce0fb48
[3]: https://github.com/tmuxinator/tmuxinator
[4]: https://github.com/ddollar/foreman
[5]: https://github.com/chrismytton/shoreman
[6]: https://github.com/strongloop/node-foreman
[7]: https://www.npmjs.com/package/ttab
[8]: https://magicbell.com