Caching & ETags
Fold the import map into your ETags, and keep the map fresh while you edit JavaScript in development.
A digest of the import map in your ETag#
If you use ETags generated by Rails helpers like stale? or fresh_when, the digest of the import map has to be part of the calculation. Otherwise the application keeps answering 304 Not Modified after your JavaScript changed. stale_when_importmap_changes adds the digest to the ETag for HTML requests:
class ApplicationController < ActionController::Base
stale_when_importmap_changes
endUnder the hood that is Rails.application.importmap.digest(resolver: helpers), a SHA1 of the rendered import map JSON, which you can use directly in an etag { … } block if you'd rather scope it yourself.
Sweeping the cache in development and test#
The import map is cached once rendered. In development, and in test when class reloading is on, a file watcher on app/javascript and vendor/javascript clears that cache before each request when a file changed, so a new controller shows up in the map without a restart. That is config.importmap.sweep_cache, on by default in those environments; the watcher is only installed when classes are reloadable, so a test environment with enable_reloading = false (the Rails default) skips it.
An engine, or an app with JavaScript elsewhere, adds its directories to the watch list. The watcher reads the list in the importmap.cache_sweeper initializer, so an engine's initializer has to run before it:
initializer "my-engine.importmap", before: "importmap.cache_sweeper" do |app|
app.config.importmap.cache_sweepers << Engine.root.join("app/assets/javascripts")
endconfig/importmap.rb itself is reloaded by a separate reloader whenever any file in config.importmap.paths changes; removing a pin still needs a restart for it to disappear from the rendered map and the preloads.
Legacy browsers such as Safari on iOS 15#
For a browser without native import map support, load es-module-shims before the import map tags:
<script async src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js" data-turbo-track="reload"></script>
<%= javascript_importmap_tags %>