Skip to content

Commit

Permalink
Allows preload to be determined by provided entry_point (#253)
Browse files Browse the repository at this point in the history
* Allows preload to be determined by provided entry_point

* entry point defaults and fix

* Tests for various preload values

* Update README.md
  • Loading branch information
aseroff committed Sep 15, 2024
1 parent 11e59ae commit e54fd54
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 8 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,25 @@ pin "md5", preload: false # file lives in vendor/javascript/md5.js
...
```

You can also specify which entry points to preload a particular dependency in by providing `preload:` a string or array of strings.

Example:

```ruby
# config/importmap.rb
pin "@github/hotkey", to: "@github--hotkey.js", preload: 'application'
pin "md5", preload: ['application', 'alternate']

# app/views/layouts/application.html.erb
<%= javascript_importmap_tags 'alternate' %>
# will include the following link before the importmap is setup:
<link rel="modulepreload" href="/assets/javascript/md5.js">
...
```



## Composing import maps

By default, Rails loads import map definition from the application's `config/importmap.rb` to the `Importmap::Map` object available at `Rails.application.importmap`.
Expand Down
6 changes: 3 additions & 3 deletions app/helpers/importmap/importmap_tags_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Importmap::ImportmapTagsHelper
def javascript_importmap_tags(entry_point = "application", importmap: Rails.application.importmap)
safe_join [
javascript_inline_importmap_tag(importmap.to_json(resolver: self)),
javascript_importmap_module_preload_tags(importmap),
javascript_importmap_module_preload_tags(importmap, entry_point:),
javascript_import_module_tag(entry_point)
], "\n"
end
Expand All @@ -24,8 +24,8 @@ 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)
javascript_module_preload_tag(*importmap.preloaded_module_paths(resolver: self))
def javascript_importmap_module_preload_tags(importmap = Rails.application.importmap, entry_point: "application")
javascript_module_preload_tag(*importmap.preloaded_module_paths(resolver: self, entry_point:))
end

# Link tag(s) for preloading the JavaScript module residing in `*paths`. Will return one link tag per path element.
Expand Down
8 changes: 4 additions & 4 deletions lib/importmap/map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ def pin_all_from(dir, under: nil, to: nil, preload: true)
# resolver that has been configured for the `asset_host` you want these resolved paths to use. In case you need to
# resolve for different asset hosts, you can pass in a custom `cache_key` to vary the cache used by this method for
# the different cases.
def preloaded_module_paths(resolver:, cache_key: :preloaded_module_paths)
def preloaded_module_paths(resolver:, entry_point: "application", cache_key: :preloaded_module_paths)
cache_as(cache_key) do
resolve_asset_paths(expanded_preloading_packages_and_directories, resolver: resolver).values
resolve_asset_paths(expanded_preloading_packages_and_directories(entry_point:), resolver:).values
end
end

Expand Down Expand Up @@ -118,8 +118,8 @@ def resolve_asset_paths(paths, resolver:)
end.compact
end

def expanded_preloading_packages_and_directories
expanded_packages_and_directories.select { |name, mapping| mapping.preload }
def expanded_preloading_packages_and_directories(entry_point:)
expanded_packages_and_directories.select { |name, mapping| mapping.preload.in?([true, false]) ? mapping.preload : (Array(mapping.preload) & Array(entry_point)).any? }
end

def expanded_packages_and_directories
Expand Down
27 changes: 26 additions & 1 deletion test/importmap_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ def setup
pin "editor", to: "rich_text.js", preload: false
pin "not_there", to: "nowhere.js", preload: false
pin "md5", to: "https://cdn.skypack.dev/md5", preload: true
pin "leaflet", to: "https://cdn.skypack.dev/leaflet", preload: 'application'
pin "chartkick", to: "https://cdn.skypack.dev/chartkick", preload: ['application', 'alternate']
pin "tinyMCE", to: "https://cdn.skypack.dev/tinymce", preload: 'alternate'

pin_all_from "app/javascript/controllers", under: "controllers", preload: true
pin_all_from "app/javascript/spina/controllers", under: "controllers/spina", preload: true
Expand Down Expand Up @@ -78,10 +81,32 @@ def setup
end
end

test "preloaded modules are included in preload tags" do
test "preloaded modules are included in preload tags when no entry_point specified" do
preloading_module_paths = @importmap.preloaded_module_paths(resolver: ApplicationController.helpers).to_s
assert_match /md5/, preloading_module_paths
assert_match /goodbye_controller/, preloading_module_paths
assert_match /leaflet/, preloading_module_paths
assert_no_match /application/, preloading_module_paths
assert_no_match /tinymce/, preloading_module_paths
end

test "preloaded modules are included in preload tags based on single entry_point provided" do
preloading_module_paths = @importmap.preloaded_module_paths(resolver: ApplicationController.helpers, entry_point: "alternate").to_s
assert_no_match /leaflet/, preloading_module_paths
assert_match /tinymce/, preloading_module_paths
assert_match /chartkick/, preloading_module_paths
assert_match /md5/, preloading_module_paths
assert_match /goodbye_controller/, preloading_module_paths
assert_no_match /application/, preloading_module_paths
end

test "preloaded modules are included in preload tags based on multiple entry_points provided" do
preloading_module_paths = @importmap.preloaded_module_paths(resolver: ApplicationController.helpers, entry_point: ["application", "alternate"]).to_s
assert_match /leaflet/, preloading_module_paths
assert_match /tinymce/, preloading_module_paths
assert_match /chartkick/, preloading_module_paths
assert_match /md5/, preloading_module_paths
assert_match /goodbye_controller/, preloading_module_paths
assert_no_match /application/, preloading_module_paths
end

Expand Down

0 comments on commit e54fd54

Please sign in to comment.