|
| 1 | +pub mod artifact; |
| 2 | +use std::mem; |
| 3 | + |
| 4 | +use rayon::iter::{IntoParallelRefIterator as _, ParallelIterator}; |
| 5 | +use rspack_error::Result; |
| 6 | + |
| 7 | +use crate::{ |
| 8 | + Compilation, Logger as _, |
| 9 | + collect_module_graph_effects::artifact::{ |
| 10 | + CollectModuleGraphEffectsArtifact, DependenciesDiagnostics, |
| 11 | + }, |
| 12 | + incremental::{self, IncrementalPasses, Mutation}, |
| 13 | +}; |
| 14 | +pub async fn collect_build_module_graph_effects(compilation: &mut Compilation) -> Result<()> { |
| 15 | + let mut artifact = mem::take(&mut compilation.collect_build_module_graph_effects_artifact); |
| 16 | + collect_build_module_graph_effects_inner(compilation, &mut artifact).await?; |
| 17 | + compilation.diagnostics.extend( |
| 18 | + artifact |
| 19 | + .dependencies_diagnostics |
| 20 | + .clone() |
| 21 | + .into_values() |
| 22 | + .flatten(), |
| 23 | + ); |
| 24 | + if let Some(mutations) = artifact.incremental.mutations_take() { |
| 25 | + for mutation in mutations { |
| 26 | + if let Some(mutations) = compilation.incremental.mutations_write() { |
| 27 | + mutations.add(mutation); |
| 28 | + } |
| 29 | + } |
| 30 | + } |
| 31 | + |
| 32 | + compilation.collect_build_module_graph_effects_artifact = artifact; |
| 33 | + Ok(()) |
| 34 | +} |
| 35 | +// collect build module graph effects for incremental compilation |
| 36 | +#[tracing::instrument("Compilation:collect_build_module_graph_effects", skip_all)] |
| 37 | +pub async fn collect_build_module_graph_effects_inner( |
| 38 | + ctx: &mut Compilation, |
| 39 | + artifact: &mut CollectModuleGraphEffectsArtifact, |
| 40 | +) -> Result<()> { |
| 41 | + let logger = ctx.get_logger("rspack.Compilation"); |
| 42 | + if let Some(mutations) = artifact.incremental.mutations_write() { |
| 43 | + mutations.extend( |
| 44 | + ctx |
| 45 | + .build_module_graph_artifact |
| 46 | + .affected_dependencies |
| 47 | + .updated() |
| 48 | + .iter() |
| 49 | + .map(|&dependency| Mutation::DependencyUpdate { dependency }), |
| 50 | + ); |
| 51 | + |
| 52 | + mutations.extend( |
| 53 | + ctx |
| 54 | + .build_module_graph_artifact |
| 55 | + .affected_modules |
| 56 | + .removed() |
| 57 | + .iter() |
| 58 | + .map(|&module| Mutation::ModuleRemove { module }), |
| 59 | + ); |
| 60 | + mutations.extend( |
| 61 | + ctx |
| 62 | + .build_module_graph_artifact |
| 63 | + .affected_modules |
| 64 | + .updated() |
| 65 | + .iter() |
| 66 | + .map(|&module| Mutation::ModuleUpdate { module }), |
| 67 | + ); |
| 68 | + mutations.extend( |
| 69 | + ctx |
| 70 | + .build_module_graph_artifact |
| 71 | + .affected_modules |
| 72 | + .added() |
| 73 | + .iter() |
| 74 | + .map(|&module| Mutation::ModuleAdd { module }), |
| 75 | + ); |
| 76 | + tracing::debug!(target: incremental::TRACING_TARGET, passes = %IncrementalPasses::MAKE, %mutations); |
| 77 | + } |
| 78 | + |
| 79 | + let start = logger.time("finish modules"); |
| 80 | + // finish_modules means the module graph (modules, connections, dependencies) are |
| 81 | + // frozen and start to optimize (provided exports, infer async, etc.) based on the |
| 82 | + // module graph, so any kind of change that affect these should be done before the |
| 83 | + // finish_modules |
| 84 | + |
| 85 | + ctx |
| 86 | + .plugin_driver |
| 87 | + .clone() |
| 88 | + .compilation_hooks |
| 89 | + .finish_modules |
| 90 | + .call(ctx, artifact) |
| 91 | + .await?; |
| 92 | + |
| 93 | + logger.time_end(start); |
| 94 | + |
| 95 | + // https://github.com/webpack/webpack/blob/19ca74127f7668aaf60d59f4af8fcaee7924541a/lib/Compilation.js#L2988 |
| 96 | + ctx.module_graph_cache_artifact.freeze(); |
| 97 | + // Collect dependencies diagnostics at here to make sure: |
| 98 | + // 1. after finish_modules: has provide exports info |
| 99 | + // 2. before optimize dependencies: side effects free module hasn't been skipped |
| 100 | + collect_dependencies_diagnostics(ctx, artifact); |
| 101 | + ctx.module_graph_cache_artifact.unfreeze(); |
| 102 | + Ok(()) |
| 103 | +} |
| 104 | +#[tracing::instrument("Compilation:collect_dependencies_diagnostics", skip_all)] |
| 105 | +fn collect_dependencies_diagnostics( |
| 106 | + ctx: &Compilation, |
| 107 | + artifact: &mut CollectModuleGraphEffectsArtifact, |
| 108 | +) { |
| 109 | + let mutations = ctx |
| 110 | + .incremental |
| 111 | + .mutations_read(IncrementalPasses::DEPENDENCIES_DIAGNOSTICS); |
| 112 | + // TODO move diagnostic collect to make |
| 113 | + let modules = if let Some(mutations) = mutations |
| 114 | + && !artifact.dependencies_diagnostics.is_empty() |
| 115 | + { |
| 116 | + let revoked_modules = mutations.iter().filter_map(|mutation| match mutation { |
| 117 | + Mutation::ModuleRemove { module } => Some(*module), |
| 118 | + _ => None, |
| 119 | + }); |
| 120 | + for revoked_module in revoked_modules { |
| 121 | + artifact.dependencies_diagnostics.remove(&revoked_module); |
| 122 | + } |
| 123 | + let modules = mutations.get_affected_modules_with_module_graph(&ctx.get_module_graph()); |
| 124 | + let logger = ctx.get_logger("rspack.incremental.dependenciesDiagnostics"); |
| 125 | + logger.log(format!( |
| 126 | + "{} modules are affected, {} in total", |
| 127 | + modules.len(), |
| 128 | + ctx.get_module_graph().modules().len() |
| 129 | + )); |
| 130 | + modules |
| 131 | + } else { |
| 132 | + ctx.get_module_graph().modules().keys().copied().collect() |
| 133 | + }; |
| 134 | + let module_graph = ctx.get_module_graph(); |
| 135 | + let module_graph_cache = &ctx.module_graph_cache_artifact; |
| 136 | + let dependencies_diagnostics: DependenciesDiagnostics = modules |
| 137 | + .par_iter() |
| 138 | + .map(|module_identifier| { |
| 139 | + let mgm = module_graph |
| 140 | + .module_graph_module_by_identifier(module_identifier) |
| 141 | + .expect("should have mgm"); |
| 142 | + let diagnostics = mgm |
| 143 | + .all_dependencies |
| 144 | + .iter() |
| 145 | + .filter_map(|dependency_id| module_graph.dependency_by_id(dependency_id)) |
| 146 | + .filter_map(|dependency| { |
| 147 | + dependency |
| 148 | + .get_diagnostics(&module_graph, module_graph_cache) |
| 149 | + .map(|diagnostics| { |
| 150 | + diagnostics.into_iter().map(|mut diagnostic| { |
| 151 | + diagnostic.module_identifier = Some(*module_identifier); |
| 152 | + diagnostic.loc = dependency.loc(); |
| 153 | + diagnostic |
| 154 | + }) |
| 155 | + }) |
| 156 | + }) |
| 157 | + .flatten() |
| 158 | + .collect::<Vec<_>>(); |
| 159 | + (*module_identifier, diagnostics) |
| 160 | + }) |
| 161 | + .collect(); |
| 162 | + |
| 163 | + artifact |
| 164 | + .dependencies_diagnostics |
| 165 | + .extend(dependencies_diagnostics); |
| 166 | +} |
0 commit comments