11use async_trait:: async_trait;
2- use rustc_hash:: FxHashSet ;
2+ use rustc_hash:: { FxHashMap , FxHashSet } ;
33
44use super :: * ;
5- use crate :: { cache:: Cache , compilation:: pass:: PassExt , logger:: Logger } ;
5+ use crate :: {
6+ cache:: Cache ,
7+ compilation:: { CompilationChunkAssetHook , pass:: PassExt } ,
8+ logger:: Logger ,
9+ } ;
610
711pub struct CreateChunkAssetsPass ;
812
@@ -84,13 +88,16 @@ pub async fn create_chunk_assets(
8488 . chunk_by_ukey
8589 . contains ( chunk)
8690 } ) ;
87- let chunks: FxHashSet < ChunkUkey > = mutations
88- . iter ( )
89- . filter_map ( |mutation| match mutation {
90- Mutation :: ChunkSetHashes { chunk } => Some ( * chunk) ,
91- _ => None ,
92- } )
93- . collect ( ) ;
91+ let mut chunks = Vec :: new ( ) ;
92+ let mut seen_chunks = FxHashSet :: default ( ) ;
93+ for chunk in mutations. iter ( ) . filter_map ( |mutation| match mutation {
94+ Mutation :: ChunkSetHashes { chunk } => Some ( * chunk) ,
95+ _ => None ,
96+ } ) {
97+ if seen_chunks. insert ( chunk) {
98+ chunks. push ( chunk) ;
99+ }
100+ }
94101 tracing:: debug!( target: incremental:: TRACING_TARGET , passes = %IncrementalPasses :: CHUNK_ASSET , %mutations) ;
95102 let logger = compilation. get_logger ( "rspack.incremental.chunkAsset" ) ;
96103 logger. log ( format ! (
@@ -105,7 +112,7 @@ pub async fn create_chunk_assets(
105112 . chunk_by_ukey
106113 . keys ( )
107114 . copied ( )
108- . collect ( )
115+ . collect :: < Vec < _ > > ( )
109116 } ;
110117 let compilation_ref = & * compilation;
111118 let results = rspack_parallel:: scope :: < _ , Result < _ > > ( |token| {
@@ -114,7 +121,7 @@ pub async fn create_chunk_assets(
114121 let s = unsafe { token. used ( ( compilation_ref, & plugin_driver, chunk) ) } ;
115122
116123 s. spawn ( |( this, plugin_driver, chunk) | async {
117- let mut manifests = Vec :: new ( ) ;
124+ let mut manifests = Vec :: with_capacity ( 2 ) ;
118125 let mut diagnostics = Vec :: new ( ) ;
119126 plugin_driver
120127 . compilation_hooks
@@ -134,12 +141,14 @@ pub async fn create_chunk_assets(
134141 } )
135142 . await ;
136143
137- let mut chunk_render_results = ChunkRenderArtifact :: default ( ) ;
144+ let mut chunk_render_results =
145+ FxHashMap :: with_capacity_and_hasher ( results. len ( ) , Default :: default ( ) ) ;
138146 for result in results {
139147 let item = result. to_rspack_result ( ) ?;
140148 let ( key, value) = item?;
141149 chunk_render_results. insert ( key, value) ;
142150 }
151+ let chunk_render_results = ChunkRenderArtifact :: from ( chunk_render_results) ;
143152 let chunk_ukey_and_manifest = if compilation
144153 . incremental
145154 . passes_enabled ( IncrementalPasses :: CHUNK_ASSET )
@@ -152,6 +161,51 @@ pub async fn create_chunk_assets(
152161 chunk_render_results
153162 } ;
154163
164+ let has_chunk_asset_hook =
165+ has_chunk_asset_taps ( & plugin_driver. compilation_hooks . chunk_asset ) . await ;
166+
167+ if !has_chunk_asset_hook {
168+ for (
169+ chunk_ukey,
170+ ChunkRenderResult {
171+ manifests,
172+ diagnostics,
173+ } ,
174+ ) in chunk_ukey_and_manifest
175+ {
176+ if !diagnostics. is_empty ( ) {
177+ compilation. extend_diagnostics ( diagnostics) ;
178+ }
179+
180+ if manifests. is_empty ( ) {
181+ continue ;
182+ }
183+
184+ let current_chunk = compilation
185+ . build_chunk_graph_artifact
186+ . chunk_by_ukey
187+ . expect_get_mut ( & chunk_ukey) ;
188+
189+ current_chunk. set_rendered ( true ) ;
190+ for file_manifest in & manifests {
191+ if file_manifest. auxiliary {
192+ current_chunk. add_auxiliary_file ( file_manifest. filename . clone ( ) ) ;
193+ } else {
194+ current_chunk. add_file ( file_manifest. filename . clone ( ) ) ;
195+ }
196+ }
197+
198+ for file_manifest in manifests {
199+ compilation. emit_asset (
200+ file_manifest. filename ,
201+ CompilationAsset :: new ( Some ( file_manifest. source ) , file_manifest. info ) ,
202+ ) ;
203+ }
204+ }
205+
206+ return Ok ( ( ) ) ;
207+ }
208+
155209 for (
156210 chunk_ukey,
157211 ChunkRenderResult {
@@ -160,7 +214,13 @@ pub async fn create_chunk_assets(
160214 } ,
161215 ) in chunk_ukey_and_manifest
162216 {
163- compilation. extend_diagnostics ( diagnostics) ;
217+ if !diagnostics. is_empty ( ) {
218+ compilation. extend_diagnostics ( diagnostics) ;
219+ }
220+
221+ if manifests. is_empty ( ) {
222+ continue ;
223+ }
164224
165225 for file_manifest in manifests {
166226 let filename = file_manifest. filename ;
@@ -201,3 +261,20 @@ async fn chunk_asset(
201261 . await ?;
202262 Ok ( ( ) )
203263}
264+
265+ async fn has_chunk_asset_taps ( hook : & CompilationChunkAssetHook ) -> bool {
266+ if !hook. taps . is_empty ( ) {
267+ return true ;
268+ }
269+
270+ for interceptor in hook. interceptors . iter ( ) {
271+ let Ok ( taps) = interceptor. call ( hook) . await else {
272+ return true ;
273+ } ;
274+ if !taps. is_empty ( ) {
275+ return true ;
276+ }
277+ }
278+
279+ false
280+ }
0 commit comments