diff --git a/vite_rails/lib/vite_rails/tag_helpers.rb b/vite_rails/lib/vite_rails/tag_helpers.rb
index 3c4b4ebe..b8bd5460 100644
--- a/vite_rails/lib/vite_rails/tag_helpers.rb
+++ b/vite_rails/lib/vite_rails/tag_helpers.rb
@@ -26,15 +26,27 @@ def vite_asset_path(name, **options)
def vite_javascript_tag(*names,
type: 'module',
asset_type: :javascript,
+ integrity: false,
skip_preload_tags: false,
skip_style_tags: false,
crossorigin: 'anonymous',
media: 'screen',
**options)
entries = vite_manifest.resolve_entries(*names, type: asset_type)
- tags = javascript_include_tag(*entries.fetch(:scripts), crossorigin: crossorigin, type: type, extname: false, **options)
- tags << vite_preload_tag(*entries.fetch(:imports), crossorigin: crossorigin, **options) unless skip_preload_tags
+ tags = ''.html_safe
+
+ entries.fetch(:main).each do |src, attrs|
+ tags << javascript_include_tag(src, crossorigin: crossorigin, type: type, extname: false, **attrs, **options)
+ end
+
+ unless skip_preload_tags
+ entries.fetch(:imports).each do |href, attrs|
+ tags << vite_preload_tag(href, crossorigin: crossorigin, **attrs, **options)
+ end
+ end
+
tags << stylesheet_link_tag(*entries.fetch(:stylesheets), media: media, crossorigin: crossorigin, **options) unless skip_style_tags
+
tags
end
@@ -44,9 +56,12 @@ def vite_typescript_tag(*names, **options)
end
# Public: Renders a tag for the specified Vite entrypoints.
- def vite_stylesheet_tag(*names, **options)
- style_paths = names.map { |name| vite_asset_path(name, type: :stylesheet) }
- stylesheet_link_tag(*style_paths, **options)
+ def vite_stylesheet_tag(*names, integrity: false, **options)
+ ''.html_safe.tap do |tags|
+ vite_manifest.resolve_entries(*names, type: :stylesheet).fetch(:main).each do |href, attrs|
+ tags << stylesheet_link_tag(href, **attrs, **options)
+ end
+ end
end
# Public: Renders an tag for the specified Vite asset.
@@ -68,11 +83,13 @@ def vite_manifest
end
# Internal: Renders a modulepreload link tag.
- def vite_preload_tag(*sources, crossorigin:, **options)
- sources.map { |source|
- href = path_to_asset(source)
- try(:request).try(:send_early_hints, 'Link' => %(<#{ href }>; rel=modulepreload; as=script; crossorigin=#{ crossorigin }))
- tag.link(rel: 'modulepreload', href: href, as: 'script', crossorigin: crossorigin, **options)
- }.join("\n").html_safe
+ def vite_preload_tag(source, crossorigin:, **options)
+ href = path_to_asset(source)
+ try(:request).try(:send_early_hints, 'Link' => %(<#{ href }>; rel=modulepreload; as=script; crossorigin=#{ crossorigin }).tap { |hint|
+ if integrity = options[:integrity]
+ hint << "; integrity: #{ integrity }"
+ end
+ })
+ tag.link(rel: 'modulepreload', href: href, as: 'script', type: 'module', crossorigin: crossorigin, **options)
end
end
diff --git a/vite_ruby/lib/vite_ruby/manifest.rb b/vite_ruby/lib/vite_ruby/manifest.rb
index 5c5877af..ceea255a 100644
--- a/vite_ruby/lib/vite_ruby/manifest.rb
+++ b/vite_ruby/lib/vite_ruby/manifest.rb
@@ -22,16 +22,15 @@ def path_for(name, **options)
lookup!(name, **options).fetch('file')
end
- # Public: Returns scripts, imported modules, and stylesheets for the specified
+ # Public: Returns entries, imported modules, and stylesheets for the specified
# entrypoint files.
def resolve_entries(*names, **options)
entries = names.map { |name| lookup!(name, **options) }
- script_paths = entries.map { |entry| entry.fetch('file') }
imports = dev_server_running? ? [] : entries.flat_map { |entry| entry['imports'] }.compact.uniq
{
- scripts: script_paths,
- imports: imports.map { |entry| entry.fetch('file') }.uniq,
+ main: entries.map(&TO_ENTRY),
+ imports: imports.map(&TO_ENTRY).uniq,
stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry['css'] }.compact.uniq,
}
end
@@ -63,6 +62,9 @@ def react_refresh_preamble
protected
+ # Internal: Returns a [src, attrs] entry.
+ TO_ENTRY = ->(entry) { [entry.fetch('file'), entry.slice('integrity').symbolize_keys] }
+
# Internal: Strict version of lookup.
#
# Returns a relative path for the asset, or raises an error if not found.