💾 Archived View for capsule.adrianhesketh.com › 2021 › 05 › 28 › templ-hot-reload-with-air captured on 2023-07-22 at 16:20:47. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-11-30)

-=-=-=-=-=-=-

capsule.adrianhesketh.com

home

Templ - hot reload with Air

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.

[0]

[1]

[2]

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.

Asciinema demo

Putting it together

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

MacOS tip

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.

Nix users

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;
  };

More

Next

Building a Hotwired web app with Go and Templ

Previous

Thoughts on team metrics

Home

home