Master Hugo Modules: Rapidly Develop Modules Locally

By Nicholas Gracilla  ·   June 9, 2020  ·  3 minute read

Topics: Hugo

With a simple configuration change, it's easy to develop modules locally, without a lot of git pulls and pushes

This is the third of a series of articles on Hugo’s Modules. The first, Managing Themes as Modules, introduces modules and how to use them. The second, Handle Content or Assets as Modules, discusses handling external content libraries as modules.

This article is part of our side project, Hugo For Developers.

At this point in the Master Hugo Modules series, you’re ready to start developing your own modules. But the typical development workflow involves git pushing and pulling on both the module and parent project side: an update requires a push on the module side, and also a pull on the parent project side to localize the module changes. Especially early in the development and testing of a module, this is inefficient and slows down rapid iteration.

But with a simple configuration change, it’s easy to develop a module locally. You’ll avoid git push and pulls, and even see changes hot-swapped in your Hugo development environment. Let’s take a closer look.

The standard Hugo module development workflow

Here’s the typical workflow when developing a module:

  1. Make a change in the module,
  2. Commit and push the change,
  3. In the parent project, pull the module update with hot mod get; the mod update will need to be committed as well,
  4. Test and QA on the parent project development server,
  5. Wash, rinse, and repeat as needed.

Local Hugo module development workflow

Fortunately, there’s an alternative: you can make and test changes in a module locally, by routing your parent project’s dependency reference to a local resource. Crack open your project’s go.mod, and add the following:

replace gitlab.com/<path-to-module>/<module-name> => <directory path as needed>/<module-name>

You can route the local directory wherever you like, e.g.: replace gitlab.com/<path-to-module>/<module> => ../../<module>

With this in place, you can make changes to your local module, save, and immediately see the results in your parent project. And this really is immediate: modules will be hot replaced and reflected in your development environment without a refresh.

With local development, your workflow becomes:

  1. Make changes to the module locally and save,
  2. Test and QA on the parent project development server,
  3. Iterate as needed,
  4. Commit the module update to its repo when the feature is complete.

Don’t forget to remove the local module override when the parent project goes live.

Develop your Hugo modules using feature branching

Thanks to this method, it becomes easy to develop and test a module using feature branches in git — something you can’t readily do without the local override. Here, the workflow is:

  1. In your module repo, create your feature branch,
  2. In your local module, check out the feature branch,
  3. Iterate using local development as above,
  4. When the module feature is complete, merge the branch to master,
  5. And continue to check out a new feature branch in your local module, or check out the updated master branch.

That’s it.

Developing Hugo modules locally saves a ton of time in git pushes, pulls, and server latencies. Try it out, and feel free to drop me a note about your experiences. I’m at twitter.com/nickgracilla.