Zeitwerk: A new code loader for Ruby
I am thrilled to announce the project I have been working on during the last months: Zeitwerk.
Zeitwerk is a new code loader for Ruby. It is efficient, thread-safe, and matches Ruby semantics for constants.
Zeitwerk started out of the desire to build an autoloader for Rails 6¹ that has none of the known gotchas of the classic one², and that eliminates all known use cases for require_dependency, including STIs.
The classic loader in Rails is fundamentally limited because it is based on const_missing and that callback does not get the nesting or the algorithm being used when the constant was missing. The autoloader does the absolutely best it can do with the information that it has, and has served us well since 2004. But with time new additions to the Ruby language have made a superior approach possible.
Zeitwerk is based on Module#autoload, and this gem has been my Holy Grail for years.
While bootstrapping the project, I realized it could be designed in a way that allows every gem and application to have their own independent loader, with their own configuration, inflector, and optional logger.
And this addresses another personal pain point of mine: I don’t like require. require has a global side-effect and in any non-trivial project it is very easy to forget some. Since these omissions show up depending on the load order, you get an unpredictable kind of bugs that ensures some boxes of Gelocatil.
In addition to that, if you are used to write conventional project structures in which class and module names match their file path, haven’t you ever had the feeling that all those requires are kind of redundant?
If you are a gem author or have a project with a gem-like structure for which what I said above resonates, please give the just released “1.0.0.beta2” a try!
¹ Integration not there yet. The classic autoloader is not going anywhere by now though, the plan is to have the option to opt-in and use Zeitwerk.
² Except for the one about initializers. The problem with that one is not really related to the loader, but to the fact that initializers run only once.