Skip to content

Commit 480f74a

Browse files
authored
feat: support SRI with experiments.css and CssExtractRspackPlugin (#12239)
* feat: support sri in experiments css and extract css * test: add test cases
1 parent 8913728 commit 480f74a

File tree

23 files changed

+385
-53
lines changed

23 files changed

+385
-53
lines changed

crates/node_binding/napi-binding.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,8 @@ export interface KnownAssetInfo {
15171517
cssUnusedIdents?: Array<string>
15181518
/** whether this asset is over the size limit */
15191519
isOverSizeLimit?: boolean
1520+
/** the asset type */
1521+
assetType?: string
15201522
}
15211523

15221524
export declare function loadBrowserslist(input: string | undefined | null, context: string): Array<string> | null

crates/rspack_binding_api/src/asset.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ pub struct KnownAssetInfo {
6565
pub css_unused_idents: Option<Vec<String>>,
6666
/// whether this asset is over the size limit
6767
pub is_over_size_limit: Option<bool>,
68+
/// the asset type
69+
pub asset_type: Option<String>,
6870
}
6971

7072
/// Webpack: AssetInfo = KnownAssetInfo & Record<string, any>
@@ -140,6 +142,7 @@ impl From<AssetInfo> for rspack_core::AssetInfo {
140142
related,
141143
css_unused_idents,
142144
is_over_size_limit,
145+
asset_type,
143146
} = known;
144147

145148
let chunk_hash = chunkhash
@@ -178,6 +181,7 @@ impl From<AssetInfo> for rspack_core::AssetInfo {
178181
version: String::default(),
179182
css_unused_idents: css_unused_idents.map(|i| i.into_iter().collect()),
180183
is_over_size_limit,
184+
asset_type: asset_type.map(Into::into).unwrap_or_default(),
181185
extras,
182186
}
183187
}
@@ -225,6 +229,7 @@ impl From<rspack_core::AssetInfo> for AssetInfo {
225229
related,
226230
css_unused_idents,
227231
is_over_size_limit,
232+
asset_type,
228233
extras,
229234
..
230235
} = value;
@@ -244,6 +249,7 @@ impl From<rspack_core::AssetInfo> for AssetInfo {
244249
javascript_module,
245250
css_unused_idents: css_unused_idents.map(|i| i.into_iter().collect()),
246251
is_over_size_limit,
252+
asset_type: Some(asset_type.to_string()),
247253
},
248254
extras,
249255
}

crates/rspack_core/src/compilation/mod.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ pub mod build_chunk_graph;
22
pub mod build_module_graph;
33
use std::{
44
collections::{VecDeque, hash_map},
5-
fmt::Debug,
5+
fmt::{self, Debug},
66
hash::{BuildHasherDefault, Hash},
77
sync::{
88
Arc,
@@ -37,6 +37,7 @@ use rspack_util::allocative;
3737
use rspack_util::{itoa, tracing_preset::TRACING_BENCH_TARGET};
3838
use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet, FxHasher};
3939
use tracing::instrument;
40+
use ustr::Ustr;
4041

4142
use crate::{
4243
AsyncModulesArtifact, BindingCell, BoxDependency, BoxModule, CacheCount, CacheOptions,
@@ -2955,6 +2956,8 @@ pub struct AssetInfo {
29552956
pub css_unused_idents: Option<HashSet<String>>,
29562957
/// whether this asset is over the size limit
29572958
pub is_over_size_limit: Option<bool>,
2959+
/// the plugin that created the asset
2960+
pub asset_type: ManifestAssetType,
29582961

29592962
/// Webpack: AssetInfo = KnownAssetInfo & Record<string, any>
29602963
/// This is a hack to store the additional fields in the rust struct.
@@ -2994,6 +2997,11 @@ impl AssetInfo {
29942997
self
29952998
}
29962999

3000+
pub fn with_asset_type(mut self, v: ManifestAssetType) -> Self {
3001+
self.asset_type = v;
3002+
self
3003+
}
3004+
29973005
pub fn set_full_hash(&mut self, v: String) {
29983006
self.full_hash.insert(v);
29993007
}
@@ -3154,3 +3162,41 @@ pub struct ChunkHashResult {
31543162
pub hash: RspackHashDigest,
31553163
pub content_hash: ChunkContentHash,
31563164
}
3165+
3166+
#[cacheable]
3167+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
3168+
pub enum ManifestAssetType {
3169+
#[default]
3170+
Unknown,
3171+
Asset,
3172+
Css,
3173+
JavaScript,
3174+
Wasm,
3175+
Custom(#[cacheable(with=AsPreset)] Ustr),
3176+
}
3177+
3178+
impl fmt::Display for ManifestAssetType {
3179+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3180+
match self {
3181+
ManifestAssetType::Unknown => write!(f, "unknown"),
3182+
ManifestAssetType::Asset => write!(f, "asset"),
3183+
ManifestAssetType::Css => write!(f, "css"),
3184+
ManifestAssetType::JavaScript => write!(f, "javascript"),
3185+
ManifestAssetType::Wasm => write!(f, "wasm"),
3186+
ManifestAssetType::Custom(custom) => write!(f, "{custom}"),
3187+
}
3188+
}
3189+
}
3190+
3191+
impl From<String> for ManifestAssetType {
3192+
fn from(value: String) -> Self {
3193+
match value.as_str() {
3194+
"unknown" => ManifestAssetType::Unknown,
3195+
"asset" => ManifestAssetType::Asset,
3196+
"css" => ManifestAssetType::Css,
3197+
"javascript" => ManifestAssetType::JavaScript,
3198+
"wasm" => ManifestAssetType::Wasm,
3199+
_ => ManifestAssetType::Custom(value.into()),
3200+
}
3201+
}
3202+
}

crates/rspack_plugin_asset/src/lib.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use rspack_core::{
88
AssetParserDataUrl, BuildMetaDefaultObject, BuildMetaExportsType, ChunkGraph, ChunkUkey,
99
CodeGenerationDataAssetInfo, CodeGenerationDataFilename, CodeGenerationDataUrl,
1010
CodeGenerationPublicPathAutoReplace, Compilation, CompilationRenderManifest, CompilerOptions,
11-
DependencyType, Filename, GenerateContext, GeneratorOptions, Module, ModuleGraph,
12-
NAMESPACE_OBJECT_EXPORT, NormalModule, ParseContext, ParserAndGenerator, PathData, Plugin,
13-
PublicPath, RenderManifestEntry, ResourceData, RuntimeGlobals, RuntimeSpec, SourceType,
11+
DependencyType, Filename, GenerateContext, GeneratorOptions, ManifestAssetType, Module,
12+
ModuleGraph, NAMESPACE_OBJECT_EXPORT, NormalModule, ParseContext, ParserAndGenerator, PathData,
13+
Plugin, PublicPath, RenderManifestEntry, ResourceData, RuntimeGlobals, RuntimeSpec, SourceType,
1414
rspack_sources::{BoxSource, RawStringSource, SourceExt},
1515
};
1616
use rspack_error::{
@@ -824,12 +824,14 @@ async fn render_manifest(
824824
.data
825825
.get::<CodeGenerationDataAssetInfo>()
826826
.expect("should have asset_info")
827-
.inner();
827+
.inner()
828+
.to_owned()
829+
.with_asset_type(ManifestAssetType::Asset);
828830
RenderManifestEntry {
829831
source: source.clone(),
830832
filename: asset_filename.to_owned(),
831833
has_filename: true,
832-
info: asset_info.to_owned(),
834+
info: asset_info,
833835
auxiliary: true,
834836
}
835837
});

crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ use rspack_collections::{DatabaseItem, ItemUkey};
1111
use rspack_core::{
1212
AssetInfo, Chunk, ChunkGraph, ChunkKind, ChunkLoading, ChunkLoadingType, ChunkUkey, Compilation,
1313
CompilationContentHash, CompilationId, CompilationParams, CompilationRenderManifest,
14-
CompilationRuntimeRequirementInTree, CompilerCompilation, DependencyType, Module, ModuleGraph,
15-
ModuleType, ParserAndGenerator, PathData, Plugin, PublicPath, RenderManifestEntry,
16-
RuntimeGlobals, SelfModuleFactory, SourceType, get_css_chunk_filename_template,
14+
CompilationRuntimeRequirementInTree, CompilerCompilation, DependencyType, ManifestAssetType,
15+
Module, ModuleGraph, ModuleType, ParserAndGenerator, PathData, Plugin, PublicPath,
16+
RenderManifestEntry, RuntimeGlobals, SelfModuleFactory, SourceType,
17+
get_css_chunk_filename_template,
1718
rspack_sources::{
1819
BoxSource, CachedSource, ConcatSource, RawStringSource, ReplaceSource, Source, SourceExt,
1920
},
@@ -414,7 +415,7 @@ async fn render_manifest(
414415
&compilation.options.output,
415416
&compilation.chunk_group_by_ukey,
416417
);
417-
let mut asset_info = AssetInfo::default();
418+
let mut asset_info = AssetInfo::default().with_asset_type(ManifestAssetType::Css);
418419
let unused_idents = Self::get_chunk_unused_local_idents(compilation, chunk, &css_modules);
419420
asset_info.set_css_unused_idents(unused_idents);
420421
let output_path = compilation

crates/rspack_plugin_extract_css/src/plugin.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ use rspack_collections::{DatabaseItem, IdentifierMap, IdentifierSet, UkeySet};
1111
use rspack_core::{
1212
AssetInfo, Chunk, ChunkGraph, ChunkGroupUkey, ChunkKind, ChunkUkey, Compilation,
1313
CompilationContentHash, CompilationParams, CompilationRenderManifest,
14-
CompilationRuntimeRequirementInTree, CompilerCompilation, DependencyType, Filename, Module,
15-
ModuleGraph, ModuleIdentifier, ModuleType, NormalModuleFactoryParser, ParserAndGenerator,
16-
ParserOptions, PathData, Plugin, RenderManifestEntry, RuntimeGlobals, SourceType, get_undo_path,
14+
CompilationRuntimeRequirementInTree, CompilerCompilation, DependencyType, Filename,
15+
ManifestAssetType, Module, ModuleGraph, ModuleIdentifier, ModuleType, NormalModuleFactoryParser,
16+
ParserAndGenerator, ParserOptions, PathData, Plugin, RenderManifestEntry, RuntimeGlobals,
17+
SourceType, get_undo_path,
1718
rspack_sources::{
1819
BoxSource, CachedSource, ConcatSource, RawStringSource, SourceExt, SourceMap, SourceMapSource,
1920
WithoutOriginalOptions,
@@ -643,7 +644,8 @@ async fn render_manifest(
643644
&self.options.chunk_filename
644645
};
645646

646-
let mut asset_info = AssetInfo::default();
647+
let mut asset_info =
648+
AssetInfo::default().with_asset_type(ManifestAssetType::Custom("extract-css".into()));
647649
let filename = compilation
648650
.get_path_with_info(
649651
filename_template,

crates/rspack_plugin_javascript/src/plugin/impl_plugin_for_js_plugin.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use rspack_core::{
44
AssetInfo, CachedConstDependencyTemplate, ChunkGraph, ChunkKind, ChunkUkey, Compilation,
55
CompilationAdditionalTreeRuntimeRequirements, CompilationChunkHash, CompilationContentHash,
66
CompilationId, CompilationParams, CompilationRenderManifest, CompilerCompilation,
7-
ConstDependencyTemplate, DependencyType, IgnoreErrorModuleFactory, ModuleGraph, ModuleType,
8-
ParserAndGenerator, PathData, Plugin, RenderManifestEntry, RuntimeGlobals,
9-
RuntimeRequirementsDependencyTemplate, SelfModuleFactory, SourceType,
7+
ConstDependencyTemplate, DependencyType, IgnoreErrorModuleFactory, ManifestAssetType,
8+
ModuleGraph, ModuleType, ParserAndGenerator, PathData, Plugin, RenderManifestEntry,
9+
RuntimeGlobals, RuntimeRequirementsDependencyTemplate, SelfModuleFactory, SourceType,
1010
get_js_chunk_filename_template,
1111
rspack_sources::{BoxSource, CachedSource, SourceExt},
1212
};
@@ -518,7 +518,7 @@ async fn render_manifest(
518518
&compilation.options.output,
519519
&compilation.chunk_group_by_ukey,
520520
);
521-
let mut asset_info = AssetInfo::default();
521+
let mut asset_info = AssetInfo::default().with_asset_type(ManifestAssetType::JavaScript);
522522
asset_info.set_javascript_module(compilation.options.output.module);
523523
let output_path = compilation
524524
.get_path_with_info(

crates/rspack_plugin_sri/src/asset.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{cmp::Ordering, sync::Arc};
33
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
44
use rspack_core::{
55
ChunkUkey, Compilation, CompilationAfterProcessAssets, CompilationAssets,
6-
CompilationProcessAssets, CrossOriginLoading,
6+
CompilationProcessAssets, CrossOriginLoading, ManifestAssetType,
77
chunk_graph_chunk::ChunkId,
88
rspack_sources::{ReplaceSource, Source},
99
};
@@ -79,10 +79,15 @@ See https://w3c.github.io/webappsec-subresource-integrity/#cross-origin-data-lea
7979
files
8080
})
8181
.map(|(chunk_id, file)| {
82-
if let Some(source) = compilation.assets().get(file).and_then(|a| a.get_source()) {
82+
if let Some((source, asset_type)) = compilation
83+
.assets()
84+
.get(file)
85+
.and_then(|a| a.get_source().map(|s| (s, a.get_info().asset_type)))
86+
{
8387
process_chunk_source(
8488
file,
8589
source.clone(),
90+
asset_type,
8691
chunk_id,
8792
hash_funcs,
8893
&hash_by_placeholders,
@@ -155,6 +160,7 @@ Use [contenthash] and ensure "optimization.realContentHash" option is enabled."#
155160
fn process_chunk_source(
156161
file: &str,
157162
source: Arc<dyn Source>,
163+
asset_type: ManifestAssetType,
158164
chunk_id: Option<&ChunkId>,
159165
hash_funcs: &Vec<SubresourceIntegrityHashFunction>,
160166
hash_by_placeholders: &HashMap<String, String>,
@@ -181,7 +187,7 @@ fn process_chunk_source(
181187

182188
// compute self integrity and placeholder
183189
let integrity = compute_integrity(hash_funcs, new_source.source().into_string_lossy().as_ref());
184-
let placeholder = chunk_id.map(|id| make_placeholder(hash_funcs, id.as_str()));
190+
let placeholder = chunk_id.map(|id| make_placeholder(asset_type, hash_funcs, id.as_str()));
185191

186192
ProcessChunkResult {
187193
file: file.to_string(),

crates/rspack_plugin_sri/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rspack_plugin_runtime::RuntimePlugin;
2727
#[cfg(allocative)]
2828
use rspack_util::allocative;
2929
use rspack_util::fx_hash::FxDashMap;
30-
use runtime::{create_script, handle_runtime, link_preload};
30+
use runtime::{create_link, create_script, handle_runtime, link_preload};
3131
use rustc_hash::FxHashMap as HashMap;
3232
use tokio::sync::RwLock;
3333

@@ -130,6 +130,7 @@ async fn handle_compilation(
130130
runtime_plugin_hooks
131131
.create_script
132132
.tap(create_script::new(self));
133+
runtime_plugin_hooks.create_link.tap(create_link::new(self));
133134
runtime_plugin_hooks
134135
.link_preload
135136
.tap(link_preload::new(self));

0 commit comments

Comments
 (0)