💾 Archived View for capsule.adrianhesketh.com › 2021 › 05 › 28 › templ-hot-reload-with-air captured on 2023-06-16 at 16:16:41. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2021-11-30)
-=-=-=-=-=-=-
My colleague Joe [0] introduced me to air [1] this week. He'd been using it while building a web app with the templ [2] templating language to rebuild templates, and restart his Go web server.
I'd never seen it before, but it was just what I was looking for.
Once you've installed it, you can run `air init` in your project's root directory to create a `.air.toml` file containing configuration.
If you have your `main` package and function in the root of your project, it will build and run your project straight away, but the default configuration isn't configured to watch for changes to `*.templ` files or run `templ generate`. It's also important to ignore `.*_templ.go` files or it will end up in an infinite loop of changes.
To make these changes, change the `cmd` field to add the `templ generate` command.
cmd = "templ generate && go build -o ./tmp/main ."
Then, update the `exclude_regex` field to ignore `.*_templ.go` files:
exclude_regex = [".*_templ.go"]
Finally, update the `include_ext` field to include the `templ` extension:
include_ext = ["go", "tpl", "tmpl", "templ", "html"]
Now you're free to run `air` at the command line. When you make changes the build will be executed and your web server can start up again.
In total, the configuration is as below:
root = "." tmp_dir = "tmp" [build] bin = "./tmp/main" cmd = "templ generate && go build -o ./tmp/main ." delay = 1000 exclude_dir = ["assets", "tmp", "vendor"] exclude_file = [] exclude_regex = [".*_templ.go"] exclude_unchanged = false follow_symlink = false full_bin = "" include_dir = [] include_ext = ["go", "tpl", "tmpl", "templ", "html"] kill_delay = "0s" log = "build-errors.log" send_interrupt = false stop_on_error = true [color] app = "" build = "yellow" main = "magenta" runner = "green" watcher = "cyan" [log] time = false [misc] clean_on_exit = false
If you're on a Mac, when you run a Go web server, it might pop up a warning:
Do you want the application "main" to accept incoming network connections?
That makes hot reload impossibly annoying, but it can be worked around.
If you've got `http.ListenAndServe(":8000")`, update it to `http.ListenAndServe("localhost:8000")` when you're running it on your local machine and MacOS won't put up the warning.
Just be aware that you'll need to set it back if you want the server to accept incoming requests from outside your local computer.
There's no package for `air` at the moment in the Nix packages repo, but it's relatively easy to add Go packages. Add this to `air.nix` and you can import it from your home manager or nix-darwin setup with `air = pkgs.callPackage ./air.nix {};`
{ lib, buildGoModule, fetchFromGitHub }: buildGoModule rec { pname = "air"; version = "1.27.3"; src = fetchFromGitHub { owner = "cosmtrek"; repo = "air"; rev = "v${version}"; # Calculated by downloading the code and running nix-hash --type sha256 . sha256 = "04xdgimbkg7kkngpfkxm7v0i3fbv3xfzvc96lafs05pn58zxrva0"; }; vendorSha256 = "1gnlx9rzp6vzjl7vivianhkr1c615iwvng2gfpsp6nz2b1821c07"; meta = with lib; { description = "Yet another live-reloading command line utility for Go applications in development"; homepage = https://github.com/cosmtrek/air; license = licenses.mit; maintainers = with maintainers; [ cosmtrek ]; platforms = platforms.linux ++ platforms.darwin; };
Building a Hotwired web app with Go and Templ