Skip to content
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

Allows preload to be determined by provided entry_point #253

Merged
merged 4 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
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
Loading