Slimmer is a piece of Rack Middleware that is inserted near the top of the middleware stack. Note that Slimmer is used in frontend apps such as finder-frontend, rather than publishing apps.
It takes a response from the Rails app, and a template from Static, and combines these into a single response. This allows us to do things like add 'Sign in' / 'Sign out' links to the header (or, more accurately, remove whichever link is not applicable) prior to rendering the page. This can't be done natively in Static because it would mean we can't cache responses from Static, which is a hosted service (i.e. templates are downloaded over HTTP). Slimmer is local to the app, so just a means of sharing the code that interfaces with Static, and can cache the fetched templates, locales and components.
How Slimmer works
- The Rails app defines the 'slimmer' gem as a dependency in the Gemfile.
- Slimmer bundles all its
libfiles in the gem, so that they're available to the Rails app.
- The gem (and all its
require'd in to the Rails app via Bundler. As an aside, Rails'
boot.rbcalls Bundler's setup script, which modifies the
GEM_PATH, meaning we don't need to explicitly
requireour Slimmer classes before we include them in the Rails app.
- One of the pulled in classes is
Slimmer::Railtie, which adds initialization steps to the Rails boot process to automatically invoke
Slimmer::App, which in turn initialises
Slimmer::Skinwhere much of the functionality happens.
- Back to the Rails app now. The Rails app defines what Slimmer template it needs, in the
- Every request to the app goes through the
ApplicationController, and every response from the app therefore gets proxied through
Slimmer::App. The response is passed to its
callmethod, which delegates to
Slimmer::Skinto rewrite the response.
Slimmer::Skinlists all of the processors to be applied to the response. Each processor has its own class (e.g.
Slimmer::Processors::AccountsShower) responsible for defining the HTML to be removed, replaced or added.
Slimmer::Skinalso determines which template to mix the response with. The template name is determined via mappings in
Slimmer::Headers, which is ultimately set in the Rails app via its
slimmer_templatecall earlier, defaulting to "core_layout".
- The template name is converted to a URL that points to Static.
- Requests to Static get routed to the RootController, which route to the chosen template (e.g.
- The template is fetched and then cached using the Rails cache.
- The processors are mixed with the template, the headers recalculated and the response returned.
There are a few different templates in Static so that apps can render consistent error pages, core layout pages, pages without footer links and so on.
Apps can choose to look for templates somewhere other than Static by specifying the
<title> content from the Rails response and copies it into the template.
<meta> tags from the Rails response into the template's
<link> tags it only copies tags with a
href attribute respectively, and only if a tag with a matching attribute doesn't already exist in the template.
<meta> tags, it only copies tags with a
content attribute, and only if a tag with matching attributes (and a matching
http-eqiv attribute) doesn't already exist.
Takes any conditional comments from the Rails response, and appends them to the template's
Takes the entirety of the element
#wrapper (by default), and replaces the corresponding
#wrapper element in the template with it. Both the source and destination selector can be configured.
Takes any classes applied to the
<body> element in the Rails response, and adds them to the
<body> element in the template. This will add to any classes already existing in the template.
Takes an element in the Rails response with a selector of
.header-context (by default), and replaces the corresponding element in the template with it. Does nothing unless the selector exists in both.
.header-context element typically wraps the 'breadcrumb' trail on the site.
If there is an
X-Slimmer-Search-Path header in the Rails response, it finds the search form (
form#search) in the template, and replaces the action attribute with the value of the header.