Learning to love bin/dev in Rails 7
Rails 7 introduced a new way to deal with assets via import maps and they also introduced a new way to run your app locally, the new bin/dev
file. It’s not installed by default(yet) unless you create a new app with the -css
option or it’s installed later on when you run the css:install
command.
See also(video): Adding bin/dev to your pre Rails 7 application for a way to add bin/dev
to any Rails app.
To get the new css/jss bundling configured with a new app you just need to specify what CSS framework you’d like to utilize if any, these options come from the cssbundling-rails gem.
$ rails new --help | grep css
-c, [—css=CSS]
# Choose CSS processor [options: tailwind, bootstrap, bulma, postcss, sass…
I’ll start a new app with rails new -c bootstrap
which installs everything needed and creates the bin/dev
file. If you’re looking to upgrade your app or install this in a new app just reference the full install options for the cssbundling-rails gem, it’s only two steps.
I really enjoy this approach because it’s another script to rule them all, we can now all align on one way to get things going locally. You run bin/setup
and then you run bin/dev
and your app should be running. If it isn’t running by that point, invest some time in making it so.
If you look at bin/dev
you’ll see that it’s really simple and it’s just using the foreman gem along with a Procfile.dev
. You’re most likely familiar with Procfile’s from Heroku or if you utilize them for your apps in various other hosting setups. Typically you’d just have a Procfile
but Profile.dev
is great to make it intentionally utilized for local development.
bin/dev
runs as a bash script, installs foreman if it isn’t already installed and then starts foreman with the Procfile.dev
as the Procfile.
#!/usr/bin/env bash
if ! command -v foreman &> /dev/null
then
echo “Installing foreman…”
gem install foreman
fi
foreman start -f Procfile.dev “$@“
From here with the default setup your Procfile.dev
only knows how to run a few processes(web, js, css). You can also easily modify this to say always boot the web process on a specific port, maybe you have a common authentication system for instance. We can also add a few additional processes like redis or postgresql, we’ll do that next.
web: bin/rails server -p 3000
js: yarn build —watch
css: yarn build:css —watch
With my local environment setup I boot up the backing services with docker compose, mainly the databases but really anything that’s more complicated than a brew install
or where I might need multiple versions on my machine.
One service that I’m pretty much always using is Redis and it’s pretty trivial to get going with docker compose so lets add that and then update our bin/dev
file.
I’m assuming you already have docker installed, if not follow your OS specific instructions to get that going before the next step.
Create a new docker-compose.yml file and add the redis service to it:
version: "3"
services:
redis:
image: redis:6.2.2-alpine
ports:
- "6379:6379"
Now that we have this in place we can update our bin/dev
file to boot this along with everything else.
redis: docker-compose up redis
web: bin/rails server -p 3000
js: yarn build --watch
css: yarn build:css --watch
Now when you run bin/dev
you’ll see that it gets everything running that you need to start working on your application. You can see how you can easily add additional backing services or things that you’d like to run via docker compose or some other tool. Maybe you always want to run guard with live reload so that your changes automatically refresh in your browser.
And what if you already have redis running and you just need the one instance running? It’s really easy to disable booting a specific process with Foreman. If you didn’t notice, in the bin/dev
script you’ll see “$@“
at the end of the foreman script which will pass the rest of the command arguments down to foreman.
To disable a specific process just set the process name to 0 when running bin/dev
: bin/dev redis=0,all=1
This translates to, disable redis but run everything(all) else.
The Foreman manual has a few other options that are worth checking out too.
Provide some feedback on the Rails forum if this is something you’d find useful to be in there by default in the future.