Skip to content

Allow multiple importmaps in config/importmaps/ #241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
implement multiple importmaps
  • Loading branch information
manuelmeurer committed Aug 29, 2024
commit b97ef073d2d537ba55e70c02e7450845fdae3304
14 changes: 11 additions & 3 deletions app/helpers/importmap/importmap_tags_helper.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
module Importmap::ImportmapTagsHelper
# Setup all script tags needed to use an importmap-powered entrypoint (which defaults to application.js)
def javascript_importmap_tags(entry_point = "application", importmap: Rails.application.importmap)
def javascript_importmap_tags(entry_point = "application")
entry_point = entry_point.to_s

importmap_identifier =
entry_point != "application" && Rails.application.importmaps.key?(entry_point) ?
entry_point :
"application"
importmap = Rails.application.importmaps.fetch(entry_point)

safe_join [
javascript_inline_importmap_tag(importmap.to_json(resolver: self)),
javascript_importmap_module_preload_tags(importmap),
Expand All @@ -10,7 +18,7 @@ def javascript_importmap_tags(entry_point = "application", importmap: Rails.appl

# Generate an inline importmap tag using the passed `importmap_json` JSON string.
# By default, `Rails.application.importmap.to_json(resolver: self)` is used.
def javascript_inline_importmap_tag(importmap_json = Rails.application.importmap.to_json(resolver: self))
def javascript_inline_importmap_tag(importmap_json)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why you removed this default value declaration?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I removed it since Rails.application.importmap doesn't exist anymore.
I would even go one step further and pass in an importmap instead of importmap_json as the parameter, similar to what javascript_importmap_module_preload_tags accepts, which would be cleaner IMO.
What do you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Or maybe something like:

Suggested change
def javascript_inline_importmap_tag(importmap_json)
def javascript_inline_importmap_tag(importmap_json)
importmap_json ||= Rails.application.importmaps.find do |importmap|
importmap.name == "application"
end.to_json(resolver: self)

Assuming importmap has an attribute name or something like that for identification.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with passing the importmap as a param, since javascript_importmap_module_preload_tags accepts that as well. It looks very clean IMO, what do you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any particular preference. Let's see what others think.

tag.script importmap_json.html_safe,
type: "importmap", "data-turbo-track": "reload", nonce: request&.content_security_policy_nonce
end
Expand All @@ -24,7 +32,7 @@ def javascript_import_module_tag(*module_names)
# Link tags for preloading all modules marked as preload: true in the `importmap`
# (defaults to Rails.application.importmap), such that they'll be fetched
# in advance by browsers supporting this link type (https://caniuse.com/?search=modulepreload).
def javascript_importmap_module_preload_tags(importmap = Rails.application.importmap)
def javascript_importmap_module_preload_tags(importmap)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why you removed this default value declaration?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason as with javascript_inline_importmap_tag, there is no single Rails.application.importmap anymore. :)

javascript_module_preload_tag(*importmap.preloaded_module_paths(resolver: self))
end

Expand Down
30 changes: 24 additions & 6 deletions lib/importmap/engine.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "importmap/map"

# Use Rails.application.importmap to access the map
Rails::Application.send(:attr_accessor, :importmap)
# Use Rails.application.importmaps to access the maps
Rails::Application.send(:attr_accessor, :importmaps)

module Importmap
class Engine < ::Rails::Engine
Expand All @@ -14,9 +14,20 @@ class Engine < ::Rails::Engine
config.autoload_once_paths = %W( #{root}/app/helpers )

initializer "importmap" do |app|
app.importmap = Importmap::Map.new
importmap = Importmap::Map.new
app.importmaps = {
"application" => importmap
}
app.config.importmap.paths << app.root.join("config/importmap.rb")
app.config.importmap.paths.each { |path| app.importmap.draw(path) }
app.config.importmap.paths.each { |path| importmap.draw(path) }

Dir[app.root.join("config/importmaps/*.rb")].each do |path|
namespace = File.basename(path).delete_suffix(".rb")
importmap = Importmap::Map.new
app.config.importmap.paths.each { |path| importmap.draw(path) }
importmap.draw(path)
app.importmaps[namespace] = importmap
end
end

initializer "importmap.reloader" do |app|
Expand All @@ -33,10 +44,17 @@ class Engine < ::Rails::Engine
if app.config.importmap.sweep_cache && !app.config.cache_classes
app.config.importmap.cache_sweepers << app.root.join("app/javascript")
app.config.importmap.cache_sweepers << app.root.join("vendor/javascript")
app.importmap.cache_sweeper(watches: app.config.importmap.cache_sweepers)

app.importmaps.values.each do |importmap|
importmap.cache_sweeper(watches: app.config.importmap.cache_sweepers)
end

ActiveSupport.on_load(:action_controller_base) do
before_action { Rails.application.importmap.cache_sweeper.execute_if_updated }
before_action do
Rails.application.importmaps.values.each do |importmap|
importmap.cache_sweeper.execute_if_updated
end
end
end
end
end
Expand Down
4 changes: 3 additions & 1 deletion lib/importmap/reloader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ class Importmap::Reloader
delegate :execute_if_updated, :execute, :updated?, to: :updater

def reload!
import_map_paths.each { |path| Rails.application.importmap.draw(path) }
Rails.application.importmaps.values.each do |importmap|
import_map_paths.each { |path| importmap.draw(path) }
end
end

private
Expand Down