Skip to content
52 changes: 27 additions & 25 deletions crates/node_binding/napi-binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3110,31 +3110,32 @@ export declare enum RegisterJsTapKind {
CompilationProcessAssets = 23,
CompilationAfterProcessAssets = 24,
CompilationSeal = 25,
CompilationAfterSeal = 26,
NormalModuleFactoryBeforeResolve = 27,
NormalModuleFactoryFactorize = 28,
NormalModuleFactoryResolve = 29,
NormalModuleFactoryAfterResolve = 30,
NormalModuleFactoryCreateModule = 31,
NormalModuleFactoryResolveForScheme = 32,
ContextModuleFactoryBeforeResolve = 33,
ContextModuleFactoryAfterResolve = 34,
JavascriptModulesChunkHash = 35,
HtmlPluginBeforeAssetTagGeneration = 36,
HtmlPluginAlterAssetTags = 37,
HtmlPluginAlterAssetTagGroups = 38,
HtmlPluginAfterTemplateExecution = 39,
HtmlPluginBeforeEmit = 40,
HtmlPluginAfterEmit = 41,
RuntimePluginCreateScript = 42,
RuntimePluginCreateLink = 43,
RuntimePluginLinkPreload = 44,
RuntimePluginLinkPrefetch = 45,
RsdoctorPluginModuleGraph = 46,
RsdoctorPluginChunkGraph = 47,
RsdoctorPluginModuleIds = 48,
RsdoctorPluginModuleSources = 49,
RsdoctorPluginAssets = 50
CompilationShouldRecord = 26,
CompilationAfterSeal = 27,
NormalModuleFactoryBeforeResolve = 28,
NormalModuleFactoryFactorize = 29,
NormalModuleFactoryResolve = 30,
NormalModuleFactoryAfterResolve = 31,
NormalModuleFactoryCreateModule = 32,
NormalModuleFactoryResolveForScheme = 33,
ContextModuleFactoryBeforeResolve = 34,
ContextModuleFactoryAfterResolve = 35,
JavascriptModulesChunkHash = 36,
HtmlPluginBeforeAssetTagGeneration = 37,
HtmlPluginAlterAssetTags = 38,
HtmlPluginAlterAssetTagGroups = 39,
HtmlPluginAfterTemplateExecution = 40,
HtmlPluginBeforeEmit = 41,
HtmlPluginAfterEmit = 42,
RuntimePluginCreateScript = 43,
RuntimePluginCreateLink = 44,
RuntimePluginLinkPreload = 45,
RuntimePluginLinkPrefetch = 46,
RsdoctorPluginModuleGraph = 47,
RsdoctorPluginChunkGraph = 48,
RsdoctorPluginModuleIds = 49,
RsdoctorPluginModuleSources = 50,
RsdoctorPluginAssets = 51
}

export interface RegisterJsTaps {
Expand Down Expand Up @@ -3164,6 +3165,7 @@ export interface RegisterJsTaps {
registerCompilationProcessAssetsTaps: (stages: Array<number>) => Array<{ function: ((arg: JsCompilation) => Promise<void>); stage: number; }>
registerCompilationAfterProcessAssetsTaps: (stages: Array<number>) => Array<{ function: ((arg: JsCompilation) => void); stage: number; }>
registerCompilationSealTaps: (stages: Array<number>) => Array<{ function: (() => void); stage: number; }>
registerCompilationShouldRecordTaps: (stages: Array<number>) => Array<{ function: (() => boolean | undefined); stage: number; }>
registerCompilationAfterSealTaps: (stages: Array<number>) => Array<{ function: (() => Promise<void>); stage: number; }>
registerNormalModuleFactoryBeforeResolveTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<[boolean | undefined, JsResolveData]>); stage: number; }>
registerNormalModuleFactoryFactorizeTaps: (stages: Array<number>) => Array<{ function: ((arg: JsResolveData) => Promise<JsResolveData>); stage: number; }>
Expand Down
36 changes: 30 additions & 6 deletions crates/rspack_binding_api/src/plugins/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ use rspack_core::{
CompilationOptimizeTreeHook, CompilationParams, CompilationProcessAssets,
CompilationProcessAssetsHook, CompilationRuntimeModule, CompilationRuntimeModuleHook,
CompilationRuntimeRequirementInTree, CompilationRuntimeRequirementInTreeHook, CompilationSeal,
CompilationSealHook, CompilationStillValidModule, CompilationStillValidModuleHook,
CompilationSucceedModule, CompilationSucceedModuleHook, CompilerAfterEmit, CompilerAfterEmitHook,
CompilerAssetEmitted, CompilerAssetEmittedHook, CompilerCompilation, CompilerCompilationHook,
CompilerEmit, CompilerEmitHook, CompilerFinishMake, CompilerFinishMakeHook, CompilerId,
CompilerMake, CompilerMakeHook, CompilerShouldEmit, CompilerShouldEmitHook,
CompilerThisCompilation, CompilerThisCompilationHook, ContextModuleFactoryAfterResolve,
CompilationSealHook, CompilationShouldRecord, CompilationShouldRecordHook,
CompilationStillValidModule, CompilationStillValidModuleHook, CompilationSucceedModule,
CompilationSucceedModuleHook, CompilerAfterEmit, CompilerAfterEmitHook, CompilerAssetEmitted,
CompilerAssetEmittedHook, CompilerCompilation, CompilerCompilationHook, CompilerEmit,
CompilerEmitHook, CompilerFinishMake, CompilerFinishMakeHook, CompilerId, CompilerMake,
CompilerMakeHook, CompilerShouldEmit, CompilerShouldEmitHook, CompilerThisCompilation,
CompilerThisCompilationHook, ContextModuleFactoryAfterResolve,
ContextModuleFactoryAfterResolveHook, ContextModuleFactoryBeforeResolve,
ContextModuleFactoryBeforeResolveHook, ExecuteModuleId, Module, ModuleFactoryCreateData,
ModuleId, ModuleIdentifier, ModuleIdsArtifact, NormalModuleCreateData,
Expand Down Expand Up @@ -385,6 +386,7 @@ pub enum RegisterJsTapKind {
CompilationProcessAssets,
CompilationAfterProcessAssets,
CompilationSeal,
CompilationShouldRecord,
CompilationAfterSeal,
NormalModuleFactoryBeforeResolve,
NormalModuleFactoryFactorize,
Expand Down Expand Up @@ -536,6 +538,10 @@ pub struct RegisterJsTaps {
pub register_compilation_after_process_assets_taps: RegisterFunction<JsCompilationWrapper, ()>,
#[napi(ts_type = "(stages: Array<number>) => Array<{ function: (() => void); stage: number; }>")]
pub register_compilation_seal_taps: RegisterFunction<(), ()>,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: (() => boolean | undefined); stage: number; }>"
)]
pub register_compilation_should_record_taps: RegisterFunction<(), Option<bool>>,
#[napi(
ts_type = "(stages: Array<number>) => Array<{ function: (() => Promise<void>); stage: number; }>"
)]
Expand Down Expand Up @@ -852,6 +858,13 @@ define_register!(
kind = RegisterJsTapKind::CompilationSeal,
skip = true,
);
define_register!(
RegisterCompilationShouldRecordTaps,
tap = CompilationShouldRecordTap<(), Option<bool>> @ CompilationShouldRecordHook,
cache = false,
kind = RegisterJsTapKind::CompilationShouldRecord,
skip = true,
);
define_register!(
RegisterCompilationAfterSealTaps,
tap = CompilationAfterSealTap<(), Promise<()>> @ CompilationAfterSealHook,
Expand Down Expand Up @@ -1570,6 +1583,17 @@ impl CompilationSeal for CompilationSealTap {
}
}

#[async_trait]
impl CompilationShouldRecord for CompilationShouldRecordTap {
async fn run(&self, _compilation: &Compilation) -> rspack_error::Result<Option<bool>> {
self.function.call_with_sync(()).await
}

fn stage(&self) -> i32 {
self.stage
}
}

#[async_trait]
impl CompilationAfterSeal for CompilationAfterSealTap {
async fn run(&self, _compilation: &Compilation) -> rspack_error::Result<()> {
Expand Down
10 changes: 10 additions & 0 deletions crates/rspack_binding_api/src/plugins/js_hooks_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub struct JsHooksAdapterPlugin {
register_compilation_process_assets_taps: RegisterCompilationProcessAssetsTaps,
register_compilation_after_process_assets_taps: RegisterCompilationAfterProcessAssetsTaps,
register_compilation_seal_taps: RegisterCompilationSealTaps,
register_compilation_should_record_taps: RegisterCompilationShouldRecordTaps,
register_compilation_after_seal_taps: RegisterCompilationAfterSealTaps,
register_normal_module_factory_before_resolve_taps: RegisterNormalModuleFactoryBeforeResolveTaps,
register_normal_module_factory_factorize_taps: RegisterNormalModuleFactoryFactorizeTaps,
Expand Down Expand Up @@ -200,6 +201,10 @@ impl Plugin for JsHooksAdapterPlugin {
.compilation_hooks
.seal
.intercept(self.register_compilation_seal_taps.clone());
ctx
.compilation_hooks
.should_record
.intercept(self.register_compilation_should_record_taps.clone());
ctx
.compilation_hooks
.after_seal
Expand Down Expand Up @@ -313,6 +318,7 @@ impl Plugin for JsHooksAdapterPlugin {
.register_compilation_after_process_assets_taps
.clear_cache();
self.register_compilation_seal_taps.clear_cache();
self.register_compilation_should_record_taps.clear_cache();
self.register_compilation_after_seal_taps.clear_cache();
self
.register_normal_module_factory_before_resolve_taps
Expand Down Expand Up @@ -589,6 +595,10 @@ impl JsHooksAdapterPlugin {
register_js_taps.register_compilation_seal_taps,
non_skippable_registers.clone(),
),
register_compilation_should_record_taps: RegisterCompilationShouldRecordTaps::new(
register_js_taps.register_compilation_should_record_taps,
non_skippable_registers.clone(),
),
register_compilation_after_seal_taps: RegisterCompilationAfterSealTaps::new(
register_js_taps.register_compilation_after_seal_taps,
non_skippable_registers.clone(),
Expand Down
6 changes: 4 additions & 2 deletions crates/rspack_core/src/compilation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ define_hook!(CompilationRenderManifest: Series(compilation: &Compilation, chunk_
define_hook!(CompilationChunkAsset: Series(compilation: &Compilation, chunk_ukey: &ChunkUkey, filename: &str));
define_hook!(CompilationProcessAssets: Series(compilation: &mut Compilation));
define_hook!(CompilationAfterProcessAssets: Series(compilation: &Compilation, diagnostics: &mut Vec<Diagnostic>));
define_hook!(CompilationShouldRecord: SeriesBail(compilation: &Compilation) -> bool);
define_hook!(CompilationAfterSeal: Series(compilation: &Compilation),tracing=true);

#[derive(Debug, Default)]
Expand Down Expand Up @@ -167,6 +168,7 @@ pub struct CompilationHooks {
pub chunk_asset: CompilationChunkAssetHook,
pub process_assets: CompilationProcessAssetsHook,
pub after_process_assets: CompilationAfterProcessAssetsHook,
pub should_record: CompilationShouldRecordHook,
pub after_seal: CompilationAfterSealHook,
}

Expand Down Expand Up @@ -202,7 +204,7 @@ pub struct Compilation {
// The status is different, should generate different hash for `.hot-update.js`
// So use compilation hash update `hot_index` to fix it.
pub hot_index: u32,
pub records: Option<CompilationRecords>,
pub records: Option<Arc<CompilationRecords>>,
pub options: Arc<CompilerOptions>,
pub platform: Arc<CompilerPlatform>,
pub entries: Entry,
Expand Down Expand Up @@ -326,7 +328,7 @@ impl Compilation {
buildtime_plugin_driver: SharedPluginDriver,
resolver_factory: Arc<ResolverFactory>,
loader_resolver_factory: Arc<ResolverFactory>,
records: Option<CompilationRecords>,
records: Option<Arc<CompilationRecords>>,
incremental: Incremental,
module_executor: Option<ModuleExecutor>,
modified_files: ArcPathSet,
Expand Down
2 changes: 2 additions & 0 deletions crates/rspack_core/src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub struct Compiler {
pub emitted_asset_versions: HashMap<String, String>,
pub platform: Arc<CompilerPlatform>,
compiler_context: Arc<CompilerContext>,
last_records: Option<Arc<CompilationRecords>>,
}

impl Compiler {
Expand Down Expand Up @@ -195,6 +196,7 @@ impl Compiler {
input_filesystem,
platform,
compiler_context,
last_records: None,
}
}

Expand Down
22 changes: 19 additions & 3 deletions crates/rspack_core/src/compiler/rebuild.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::Path;
use std::{path::Path, sync::Arc};

use rspack_collections::IdentifierMap;
use rspack_error::Result;
Expand Down Expand Up @@ -57,7 +57,23 @@ impl Compiler {
changed_files: FxHashSet<String>,
deleted_files: FxHashSet<String>,
) -> Result<()> {
let records = CompilationRecords::record(&self.compilation);
let should_record = !matches!(
self
.plugin_driver
.compilation_hooks
.should_record
.call(&self.compilation)
.await?,
Some(false)
);

let records = if should_record {
let records = Arc::new(CompilationRecords::record(&self.compilation));
self.last_records = Some(Arc::clone(&records));
Some(records)
} else {
self.last_records.clone()
};

// build without stats
{
Expand All @@ -79,7 +95,7 @@ impl Compiler {
self.buildtime_plugin_driver.clone(),
self.resolver_factory.clone(),
self.loader_resolver_factory.clone(),
Some(records),
records,
Incremental::new_hot(self.options.incremental),
Some(ModuleExecutor::default()),
modified_files,
Expand Down
16 changes: 8 additions & 8 deletions crates/rspack_plugin_hmr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,16 @@ async fn compilation(

#[plugin_hook(CompilationProcessAssets for HotModuleReplacementPlugin, stage = Compilation::PROCESS_ASSETS_STAGE_ADDITIONAL)]
async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
let Some(CompilationRecords {
let Some(records) = compilation.records.take() else {
return Ok(());
};
let CompilationRecords {
chunks: old_chunks,
runtimes: all_old_runtime,
modules: old_all_modules,
runtime_modules: old_runtime_modules,
hash: old_hash,
}) = compilation.records.take()
else {
return Ok(());
};
} = records.as_ref();

if let Some(old_hash) = &old_hash
&& let Some(hash) = &compilation.hash
Expand All @@ -85,7 +85,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {

let mut updated_runtime_modules: IdentifierSet = Default::default();
let mut updated_chunks: HashMap<ChunkUkey, HashSet<String>> = Default::default();
for (identifier, old_runtime_module_hash) in &old_runtime_modules {
for (identifier, old_runtime_module_hash) in old_runtime_modules {
if let Some(new_runtime_module_hash) = compilation.runtime_modules_hash.get(identifier) {
// updated
if new_runtime_module_hash != old_runtime_module_hash {
Expand All @@ -107,7 +107,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
.collect();
let mut completely_removed_modules: HashSet<ModuleId> = Default::default();

for (chunk_id, (old_runtime, old_module_ids)) in &old_chunks {
for (chunk_id, (old_runtime, old_module_ids)) in old_chunks {
let mut remaining_modules: HashSet<ModuleId> = Default::default();
for old_module_id in old_module_ids {
if !all_module_ids.contains_key(old_module_id) {
Expand All @@ -134,7 +134,7 @@ async fn process_assets(&self, compilation: &mut Compilation) -> Result<()> {
if let Some(current_chunk) = current_chunk {
new_runtime = current_chunk
.runtime()
.intersection(&all_old_runtime)
.intersection(all_old_runtime)
.copied()
.collect();

Expand Down
15 changes: 14 additions & 1 deletion crates/rspack_plugin_no_emit_on_errors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt::Debug;

use rspack_core::{Compilation, CompilerShouldEmit, Plugin};
use rspack_core::{Compilation, CompilationShouldRecord, CompilerShouldEmit, Plugin};
use rspack_error::Result;
use rspack_hook::{plugin, plugin_hook};

Expand All @@ -23,13 +23,26 @@ async fn should_emit(&self, compilation: &mut Compilation) -> Result<Option<bool
}
}

#[plugin_hook(CompilationShouldRecord for NoEmitOnErrorsPlugin)]
async fn should_record(&self, compilation: &Compilation) -> Result<Option<bool>> {
if compilation.get_errors().next().is_some() {
Ok(Some(false))
} else {
Ok(None)
}
}

impl Plugin for NoEmitOnErrorsPlugin {
fn name(&self) -> &'static str {
"NoEmitOnErrorsPlugin"
}

fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> {
ctx.compiler_hooks.should_emit.tap(should_emit::new(self));
ctx
.compilation_hooks
.should_record
.tap(should_record::new(self));
Ok(())
}
}
2 changes: 2 additions & 0 deletions packages/rspack/src/Compilation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export class Compilation {
runtimeModule: liteTapable.SyncHook<[RuntimeModule, Chunk]>;
seal: liteTapable.SyncHook<[]>;
afterSeal: liteTapable.AsyncSeriesHook<[], void>;
shouldRecord: liteTapable.SyncBailHook<[], boolean>;
needAdditionalPass: liteTapable.SyncBailHook<[], boolean>;
}>;
name?: string;
Expand Down Expand Up @@ -389,6 +390,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
runtimeModule: new liteTapable.SyncHook(['module', 'chunk']),
seal: new liteTapable.SyncHook([]),
afterSeal: new liteTapable.AsyncSeriesHook([]),
shouldRecord: new liteTapable.SyncBailHook([]),
needAdditionalPass: new liteTapable.SyncBailHook([]),
};

Expand Down
19 changes: 19 additions & 0 deletions packages/rspack/src/taps/compilation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import binding from '@rspack/binding';
import { SyncBailHook } from '@rspack/lite-tapable';
import { tryRunOrWebpackError } from '../lib/HookWebpackError';
import type { Module } from '../Module';
import {
Expand Down Expand Up @@ -501,6 +502,24 @@ export const createCompilationHooksRegisters: CreatePartialRegisters<
};
},
),
registerCompilationShouldRecordTaps: createTap(
binding.RegisterJsTapKind.CompilationShouldRecord,

function () {
// shouldRecord is called in rebuild_inner on the old compilation
// before the new compilation is created, so guard against undefined.
return (
getCompiler().__internal__get_compilation()?.hooks.shouldRecord ??
new SyncBailHook<[], boolean>([])
);
},

function (queried) {
return function () {
return queried.call();
};
},
),
registerCompilationAfterSealTaps: createTap(
binding.RegisterJsTapKind.CompilationAfterSeal,

Expand Down
Loading
Loading