Why read open source?
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.
The task at hand
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.
Callbacks available in Middleman Core
initialized
: called before config is parsed, and before extensions are registeredconfigure
: called to run anyconfigure
blocks (once for current environment, again for the current mode)before_extensions
: called before theExtensionManager
is instantiatedbefore_instance_block
: called before any blocks are passed to the configuration contextbefore_sitemap
: called before theSiteMap::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 theshutdown!
method, which lets users know the application is shutting downbefore
: called before Rack requestsbefore_server
: called before thePreviewServer
is createdreload
: called before the new application is initialized on a reload event
How to find Middleman Callbacks
- Clone the Middleman repository to your local machine.
- Open the Middleman directory in a text editor, IDE, or any tool that allows you to easily search through a folder's files for specific strings.
- Start with the existing documentation if it exists. Middleman lists the names of a few callbacks. You can search the directory for the string
after_configuration
. - In this instance, you should be able to find that string used like so:
execute_callbacks(:after_configuration)
. - You may also find it listed with other similar symbols in
middleman-core/lib/middleman-core/application.rb
. - Read through the related blocks of code around these search results, you'll get some additional context for how they work, and you may find additional search terms that will be helpful.
- In the case of Middleman callbacks, you can continue to search for combinations of the
execute_callbacks
method with any callback listed inmiddleman-core/lib/middleman-core/application.rb
to find where and when specific callbacks are used.
Contribute!
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.