Published on: January 20, 2021
4 min read
Open source empowers you to learn beyond existing documentation. Getting started can be confusing. This is a demonstration finding unlisted Middleman callbacks.
When folks write about open source, I think there is a strong emphasis on contributing to open source projects, which makes sense. Many software professionals are excited to give back to the community.
But beyond adding to your favorite project, open source philosophies have a number of other benefits in our daily lives. In particular, I love open source because it allows me to learn more about my tools when the documentation is out of date, incomplete, or leaves me with additional questions from my own curiosity.
This happened to me recently when I was working on https://about.gitlab.com, a static site built with Middleman. I needed to find a more comprehensive list of available callbacks in the Middleman lifecycle.
I hope this blog post is helpful if you're looking for existing Middleman callbacks, or if you're getting started reading through the source code of your favorite open source tools.
If you're getting started reading open source, I find it helps to have a specific task. Any unfamiliar codebase can be challenging to navigate. Having a goal in mind narrows your focus. Here was my task for Middleman:
I recently created a merge request to add Webpack devServer to the local development environment. I had to modify some existing behavior of our Middleman preview server and wanted to use one of the lifecycle callbacks to modify the preview server's log output.
However, the Middleman documentation does not currently list all available callbacks, nor where they happen in the lifecycle. The extension docs say:
Middleman extensions are Ruby classes which can hook into various points of the Middleman system, add new features and manipulate content. This guide explains some of what's available, but you should read the Middleman source and the source of plugins like middleman-blog to discover all the hooks and extension points.
I took them up on their advice and read through the Middleman source code to find the available callbacks. Here's what I found, and how I found them.
initialized
: called before config is parsed, and before extensions are registeredconfigure
: called to run any configure
blocks (once for current environment, again for the current mode)before_extensions
: called before the ExtensionManager
is instantiatedbefore_instance_block
: called before any blocks are passed to the configuration contextbefore_sitemap
: called before the SiteMap::Store
is instantiated, which initializes the sitemapbefore_configuration
: called before configuration is parsed, mostly used for extensionsafter_configuration
: called after extensions have workedafter_configuration_eval
: called after the configuration is parsed, before the pre-extension callbackready
: called when everything is stablebefore_build
: called before the site build process runsafter_build
: called after the builder is completebefore_shutdown
: called in the shutdown!
method, which lets users know the application is shutting downbefore
: called before Rack requestsbefore_server
: called before the PreviewServer
is createdreload
: called before the new application is initialized on a reload eventafter_configuration
.execute_callbacks(:after_configuration)
.middleman-core/lib/middleman-core/application.rb
.execute_callbacks
method with any callback listed in middleman-core/lib/middleman-core/application.rb
to find where and when specific callbacks are used.With this in-depth knowledge of your tool, you can be more productive at your day-to-day work, and you can contribute back to open source more easily.
In my case, I was able to identify the best callback for my usecase, and I now plan to check in with the Middleman team and ask if they would accept a contribution to their documentation with this information so it's easier for other folks to find in the future.