Hanami supports powerful features for web assets.
Each application can have its own separated assets settings in application configuration.
Toggle this value, to determine if the application must preprocess or copy assets from sources to public directory. It’s turned on by default in development and test environments, but turned off for production.
# apps/web/application.rb module Web class Application < Hanami::Application configure do # ... assets do # compile true, enabled by default end end configure :production do assets do compile false end end end end
In order to force browsers to cache the right copy of an asset, during the deploy, Hanami creates a copy of each file by appending its checksum to the file name.
We can control this feature via application configuration. It’s turned on by default only in production environment.
# apps/web/application.rb module Web class Application < Hanami::Application configure do # ... assets do # fingerprint false, disabled by default end end configure :production do assets do fingerprint true end end end end
If enabled, assets helpers will generate checksum relative URLs.
Serve Static Assets
It can dynamically serve them during development.
Hanami::Static middleware in project Rack stack. This component is conditionally activated, if the environment variable
SERVE_STATIC_ASSETS equals to
By default, new projects are generated with this feature enabled in development and test mode, via their corresponding
# .env.development # ... SERVE_STATIC_ASSETS="true"
Hanami assumes that projects in production mode are deployed using a web server like Nginx that is responsible to serve them without even hitting the Ruby code.
Static assets serving is enabled by default in development and test environments, but turned off for production.
There are cases where this assumption isn’t true. For instance, Heroku requires Ruby web apps to serve static assets.
To enable this feature in production, just make sure that this special environment variable is set to
What Does It Mean To Serve Static Assets With Hanami?
As mentioned above, when this feature is enabled, a special middleware is added in front of the project Rack stack:
Incoming requests can generate the following use cases
It copies the
public/assets/application.js and then serves it.
Assets are copied only if the destination path does NOT exist (eg.
If it DOES exist, the asset is only served, without copying it.
When an application has turned OFF asset compilation (Compile mode), Hanami won't copy the file.
This could happen in development mode. When we require an asset the first time it gets copied to the
public/ directory. Then when we edit the source file, the destination file becomes stale.
It copies the source into the destination file again (
public/assets/application.js) and then serves it.
Let’s say we use Sass to write our stylesheets.
It preprocess the
public/assets/application.css and then serves it.
This isn’t a static file available under
public/, so the control passes to the backend that hits the appropriate action.
This isn’t a static file or a dynamic resource, the project returns a
404 (Not Found).
Each application has a separated set of directories where its assets can be found. Assets are recursively searched under these paths.
New projects have a default directory where application assets can be put:
We can add as many directories we want under it (eg.
For a given application named
Web, the default asset directory is
If we want add other sources for a given application, we can specify them in the configuration.
# apps/web/application.rb module Web class Application < Hanami::Application configure do # ... assets do # apps/web/assets is added by default sources << [ 'vendor/assets' ] end end end end
This will add
apps/web/vendor/assets and all its subdirectories.
Hanami looks recursively through the asset sources. In order to NOT accidentally disclose sensitive files like secrets or source code, please make sure that these sources directories ONLY contain web assets.
Third Party Gems
Hanami allows developers to use Rubygems as a way to distribute web assets and make them available to Hanami applications.
Third party gems can be maintained by developers who want to bring frontend framework support to Hanami.
Let’s say we want to build an
% tree . # ... ├── lib │ └── hanami │ ├── emberjs │ │ ├── dist │ │ │ ├── ember.js │ │ │ └── ember.min.js │ │ └── version.rb │ └── emberjs.rb ├── hanami-emberjs.gemspec # ...
We put only the assets that we want to serve in an arbitrary directory.
Then we add it to
# lib/hanami/emberjs.rb require 'hanami/assets' module Hanami module Emberjs require 'hanami/emberjs/version' end end Hanami::Assets.sources << __dir__ + '/emberjs/source'
When an application requires
'hanami/emberjs', that directory will be added to the sources where Hanami can search for assets.
We can use the
ember.js in our application.