Skip to content

Commit 0b3142c

Browse files
committed
feat(experimental): add support for Subresource Integrity via vite-plugin-manifest-sri
1 parent b62de36 commit 0b3142c

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

vite_rails/lib/vite_rails/tag_helpers.rb

+28-11
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,27 @@ def vite_asset_path(name, **options)
2626
def vite_javascript_tag(*names,
2727
type: 'module',
2828
asset_type: :javascript,
29+
integrity: false,
2930
skip_preload_tags: false,
3031
skip_style_tags: false,
3132
crossorigin: 'anonymous',
3233
media: 'screen',
3334
**options)
3435
entries = vite_manifest.resolve_entries(*names, type: asset_type)
35-
tags = javascript_include_tag(*entries.fetch(:scripts), crossorigin: crossorigin, type: type, extname: false, **options)
36-
tags << vite_preload_tag(*entries.fetch(:imports), crossorigin: crossorigin, **options) unless skip_preload_tags
36+
tags = ''.html_safe
37+
38+
entries.fetch(:main).each do |src, attrs|
39+
tags << javascript_include_tag(src, crossorigin: crossorigin, type: type, extname: false, **attrs, **options)
40+
end
41+
42+
unless skip_preload_tags
43+
entries.fetch(:imports).each do |href, attrs|
44+
tags << vite_preload_tag(href, crossorigin: crossorigin, **attrs, **options)
45+
end
46+
end
47+
3748
tags << stylesheet_link_tag(*entries.fetch(:stylesheets), media: media, crossorigin: crossorigin, **options) unless skip_style_tags
49+
3850
tags
3951
end
4052

@@ -44,9 +56,12 @@ def vite_typescript_tag(*names, **options)
4456
end
4557

4658
# Public: Renders a <link> tag for the specified Vite entrypoints.
47-
def vite_stylesheet_tag(*names, **options)
48-
style_paths = names.map { |name| vite_asset_path(name, type: :stylesheet) }
49-
stylesheet_link_tag(*style_paths, **options)
59+
def vite_stylesheet_tag(*names, integrity: false, **options)
60+
''.html_safe.tap do |tags|
61+
vite_manifest.resolve_entries(*names, type: :stylesheet).fetch(:main).each do |href, attrs|
62+
tags << stylesheet_link_tag(href, **attrs, **options)
63+
end
64+
end
5065
end
5166

5267
# Public: Renders an <img> tag for the specified Vite asset.
@@ -68,11 +83,13 @@ def vite_manifest
6883
end
6984

7085
# Internal: Renders a modulepreload link tag.
71-
def vite_preload_tag(*sources, crossorigin:, **options)
72-
sources.map { |source|
73-
href = path_to_asset(source)
74-
try(:request).try(:send_early_hints, 'Link' => %(<#{ href }>; rel=modulepreload; as=script; crossorigin=#{ crossorigin }))
75-
tag.link(rel: 'modulepreload', href: href, as: 'script', crossorigin: crossorigin, **options)
76-
}.join("\n").html_safe
86+
def vite_preload_tag(source, crossorigin:, **options)
87+
href = path_to_asset(source)
88+
try(:request).try(:send_early_hints, 'Link' => %(<#{ href }>; rel=modulepreload; as=script; crossorigin=#{ crossorigin }).tap { |hint|
89+
if integrity = options[:integrity]
90+
hint << "; integrity: #{ integrity }"
91+
end
92+
})
93+
tag.link(rel: 'modulepreload', href: href, as: 'script', type: 'module', crossorigin: crossorigin, **options)
7794
end
7895
end

vite_ruby/lib/vite_ruby/manifest.rb

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,15 @@ def path_for(name, **options)
2222
lookup!(name, **options).fetch('file')
2323
end
2424

25-
# Public: Returns scripts, imported modules, and stylesheets for the specified
25+
# Public: Returns entries, imported modules, and stylesheets for the specified
2626
# entrypoint files.
2727
def resolve_entries(*names, **options)
2828
entries = names.map { |name| lookup!(name, **options) }
29-
script_paths = entries.map { |entry| entry.fetch('file') }
3029

3130
imports = dev_server_running? ? [] : entries.flat_map { |entry| entry['imports'] }.compact.uniq
3231
{
33-
scripts: script_paths,
34-
imports: imports.map { |entry| entry.fetch('file') }.uniq,
32+
main: entries.map(&TO_ENTRY),
33+
imports: imports.map(&TO_ENTRY).uniq,
3534
stylesheets: dev_server_running? ? [] : (entries + imports).flat_map { |entry| entry['css'] }.compact.uniq,
3635
}
3736
end
@@ -63,6 +62,9 @@ def react_refresh_preamble
6362

6463
protected
6564

65+
# Internal: Returns a [src, attrs] entry.
66+
TO_ENTRY = ->(entry) { [entry.fetch('file'), entry.slice('integrity').symbolize_keys] }
67+
6668
# Internal: Strict version of lookup.
6769
#
6870
# Returns a relative path for the asset, or raises an error if not found.

0 commit comments

Comments
 (0)