diff --git a/crates/binding/src/js_plugin.rs b/crates/binding/src/js_plugin.rs index 9df95fc8b..345157c9b 100644 --- a/crates/binding/src/js_plugin.rs +++ b/crates/binding/src/js_plugin.rs @@ -16,7 +16,7 @@ impl Plugin for JsPlugin { "js_plugin" } - fn build_start(&self, _context: &Arc) -> Result> { + fn build_start(&self, _context: &Arc) -> Result<()> { if let Some(hook) = &self.hooks.build_start { let (tx, rx) = mpsc::channel::>(); hook.call( @@ -26,7 +26,7 @@ impl Plugin for JsPlugin { rx.recv() .unwrap_or_else(|e| panic!("recv error: {:?}", e.to_string()))?; } - Ok(None) + Ok(()) } fn load(&self, param: &PluginLoadParam, _context: &Arc) -> Result> { @@ -64,11 +64,7 @@ impl Plugin for JsPlugin { Ok(None) } - fn generate_end( - &self, - param: &PluginGenerateEndParams, - _context: &Arc, - ) -> Result> { + fn generate_end(&self, param: &PluginGenerateEndParams, _context: &Arc) -> Result<()> { if let Some(hook) = &self.hooks.generate_end { let (tx, rx) = mpsc::channel::>(); hook.call( @@ -81,7 +77,7 @@ impl Plugin for JsPlugin { rx.recv() .unwrap_or_else(|e| panic!("recv error: {:?}", e.to_string()))?; } - Ok(None) + Ok(()) } fn before_write_fs(&self, path: &std::path::Path, content: &[u8]) -> Result<()> { diff --git a/crates/mako/src/compiler.rs b/crates/mako/src/compiler.rs index f0859b909..f7ecb17b5 100644 --- a/crates/mako/src/compiler.rs +++ b/crates/mako/src/compiler.rs @@ -247,7 +247,10 @@ impl Compiler { } if config.output.mode == OutputMode::Bundless { - plugins.insert(0, Arc::new(plugins::bundless_compiler::BundlessCompiler {})); + plugins.insert( + 0, + Arc::new(plugins::bundless_compiler::BundlessCompilerPlugin {}), + ); } if std::env::var("DEBUG_GRAPH").is_ok_and(|v| v == "true") { diff --git a/crates/mako/src/generate/analyze.rs b/crates/mako/src/generate/analyze.rs index 4f0254196..c1b4957d7 100644 --- a/crates/mako/src/generate/analyze.rs +++ b/crates/mako/src/generate/analyze.rs @@ -1,15 +1,14 @@ use std::fs; -use std::sync::Arc; +use std::path::Path; use anyhow::Result; -use crate::compiler::Context; use crate::stats::StatsJsonMap; pub struct Analyze {} impl Analyze { - pub fn write_analyze(stats: &StatsJsonMap, context: Arc) -> Result<()> { + pub fn write_analyze(stats: &StatsJsonMap, path: &Path) -> Result<()> { let stats_json = serde_json::to_string_pretty(&stats).unwrap(); let html_str = format!( r#" @@ -31,7 +30,7 @@ impl Analyze { stats_json, include_str!("../../../../client/dist/index.js").replace("", "<\\/script>") ); - let report_path = context.config.output.path.join("analyze-report.html"); + let report_path = path.join("analyze-report.html"); fs::write(&report_path, html_str).unwrap(); println!( "Analyze report generated at: {}", diff --git a/crates/mako/src/generate/mod.rs b/crates/mako/src/generate/mod.rs index e401f5965..7230ba084 100644 --- a/crates/mako/src/generate/mod.rs +++ b/crates/mako/src/generate/mod.rs @@ -29,6 +29,7 @@ use crate::config::{DevtoolConfig, OutputMode, TreeShakingStrategy}; use crate::dev::update::UpdateResult; use crate::generate::generate_chunks::{ChunkFile, ChunkFileType}; use crate::module::{Dependency, ModuleId}; +use crate::plugins::bundless_compiler::BundlessCompiler; use crate::stats::{create_stats_info, print_stats, write_stats}; use crate::utils::base64_encode; use crate::visitors::async_module::mark_async; @@ -48,8 +49,9 @@ struct ChunksUrlMap { } impl Compiler { - fn generate_with_plugin_driver(&self) -> Result<()> { - self.context.plugin_driver.generate(&self.context)?; + fn generate_bundless(&self) -> Result<()> { + let bundless_compiler = BundlessCompiler::new(self.context.clone()); + bundless_compiler.generate()?; let stats = create_stats_info(0, self); @@ -114,9 +116,8 @@ impl Compiler { } let t_tree_shaking = t_tree_shaking.elapsed(); - // TODO: improve this hardcode if self.context.config.output.mode == OutputMode::Bundless { - return self.generate_with_plugin_driver(); + return self.generate_bundless(); } let t_group_chunks = Instant::now(); @@ -183,7 +184,7 @@ impl Compiler { let stats = create_stats_info(0, self); if self.context.config.stats.is_some() { - write_stats(&stats, self); + write_stats(&stats, &self.context.config.output.path); } // build_success hook @@ -197,7 +198,7 @@ impl Compiler { } if self.context.config.analyze.is_some() { - Analyze::write_analyze(&stats, self.context.clone())?; + Analyze::write_analyze(&stats, &self.context.config.output.path)?; } debug!("generate done in {}ms", t_generate.elapsed().as_millis()); @@ -351,7 +352,7 @@ impl Compiler { // ref: https://github.com/umijs/mako/issues/1107 if self.context.config.stats.is_some() { let stats = create_stats_info(0, self); - write_stats(&stats, self); + write_stats(&stats, &self.context.config.output.path); } let t_generate = t_generate.elapsed(); diff --git a/crates/mako/src/plugin.rs b/crates/mako/src/plugin.rs index 81351e702..29816fa40 100644 --- a/crates/mako/src/plugin.rs +++ b/crates/mako/src/plugin.rs @@ -2,7 +2,7 @@ use std::any::Any; use std::path::Path; use std::sync::Arc; -use anyhow::{anyhow, Result}; +use anyhow::Result; use swc_core::common::errors::Handler; use swc_core::common::Mark; use swc_core::ecma::ast::Module; @@ -95,10 +95,6 @@ pub trait Plugin: Any + Send + Sync { Ok(()) } - fn generate(&self, _context: &Arc) -> Result> { - Ok(None) - } - fn after_generate_chunk_files( &self, _chunk_files: &[ChunkFile], @@ -107,15 +103,15 @@ pub trait Plugin: Any + Send + Sync { Ok(()) } - fn build_success(&self, _stats: &StatsJsonMap, _context: &Arc) -> Result> { - Ok(None) + fn build_success(&self, _stats: &StatsJsonMap, _context: &Arc) -> Result<()> { + Ok(()) } - fn build_start(&self, _context: &Arc) -> Result> { - Ok(None) + fn build_start(&self, _context: &Arc) -> Result<()> { + Ok(()) } - fn generate_beg(&self, _context: &Arc) -> Result<()> { + fn generate_begin(&self, _context: &Arc) -> Result<()> { Ok(()) } @@ -123,8 +119,8 @@ pub trait Plugin: Any + Send + Sync { &self, _params: &PluginGenerateEndParams, _context: &Arc, - ) -> Result> { - Ok(None) + ) -> Result<()> { + Ok(()) } fn runtime_plugins(&self, _context: &Arc) -> Result> { @@ -255,21 +251,11 @@ impl PluginDriver { pub fn before_generate(&self, context: &Arc) -> Result<()> { for plugin in &self.plugins { - plugin.generate_beg(context)?; + plugin.generate_begin(context)?; } Ok(()) } - pub fn generate(&self, context: &Arc) -> Result> { - for plugin in &self.plugins { - let ret = plugin.generate(context)?; - if ret.is_some() { - return Ok(Some(())); - } - } - Err(anyhow!("None of the plugins generate content")) - } - pub(crate) fn after_generate_chunk_files( &self, chunk_files: &[ChunkFile], @@ -282,40 +268,36 @@ impl PluginDriver { Ok(()) } - pub fn build_start(&self, context: &Arc) -> Result> { + pub fn build_start(&self, context: &Arc) -> Result<()> { for plugin in &self.plugins { plugin.build_start(context)?; } - Ok(None) + Ok(()) } pub fn generate_end( &self, param: &PluginGenerateEndParams, context: &Arc, - ) -> Result> { + ) -> Result<()> { for plugin in &self.plugins { plugin.generate_end(param, context)?; } - Ok(None) + Ok(()) } - pub fn generate_beg(&self, context: &Arc) -> Result> { + pub fn generate_begin(&self, context: &Arc) -> Result<()> { for plugin in &self.plugins { - plugin.generate_beg(context)?; + plugin.generate_begin(context)?; } - Ok(None) + Ok(()) } - pub fn build_success( - &self, - stats: &StatsJsonMap, - context: &Arc, - ) -> Result> { + pub fn build_success(&self, stats: &StatsJsonMap, context: &Arc) -> Result<()> { for plugin in &self.plugins { plugin.build_success(stats, context)?; } - Ok(None) + Ok(()) } pub fn runtime_plugins_code(&self, context: &Arc) -> Result { diff --git a/crates/mako/src/plugins/bundless_compiler.rs b/crates/mako/src/plugins/bundless_compiler.rs index 5bb3deb07..7552b5bf0 100644 --- a/crates/mako/src/plugins/bundless_compiler.rs +++ b/crates/mako/src/plugins/bundless_compiler.rs @@ -27,64 +27,120 @@ use crate::plugin::{Plugin, PluginTransformJsParam}; use crate::visitors::dep_replacer::{DepReplacer, DependenciesToReplace}; use crate::visitors::dynamic_import::DynamicImport; -pub struct BundlessCompiler {} +pub struct BundlessCompiler { + context: Arc, +} impl BundlessCompiler { - pub fn transform_all(&self, context: &Arc) -> Result<()> { - let module_graph = context.module_graph.read().unwrap(); - let module_ids = module_graph.get_module_ids(); - drop(module_graph); - transform_modules(module_ids, context)?; + pub(crate) fn new(context: Arc) -> Self { + Self { context } + } + + fn transform_all(&self) -> Result<()> { + crate::mako_profile_function!(); + let module_ids = self.context.module_graph.read().unwrap().get_module_ids(); + let context = &self.context; + + module_ids + .par_iter() + .map(|module_id| { + let module_graph = context.module_graph.read().unwrap(); + let deps = module_graph.get_dependencies(module_id); + + let module_dist_path = to_dist_path(&module_id.id, context) + .parent() + .unwrap() + .to_path_buf(); + + let resolved_deps = deps + .clone() + .into_iter() + // .map(|(id, dep)| (dep.source.clone(), id.generate(context))) + .map(|(id, dep)| { + let dep_dist_path = to_dist_path(&id.id, context); + + let rel_path = + diff_paths(&dep_dist_path, &module_dist_path).ok_or_else(|| { + anyhow!( + "failed to get relative path from {:?} to {:?}", + dep_dist_path, + module_dist_path + ) + })?; + + let rel_path = normalize_extension(rel_path); + + let replacement: String = { + let mut to_path = rel_path.to_str().unwrap().to_string(); + if to_path.starts_with("./") || to_path.starts_with("../") { + to_path + } else { + to_path.insert_str(0, "./"); + to_path + } + }; + + Ok((dep.source.clone(), (replacement.clone(), replacement))) + }) + .collect::>>(); + + let resolved_deps: HashMap = + resolved_deps?.into_iter().collect(); + + drop(module_graph); + + // let deps: Vec<(&ModuleId, &crate::module::Dependency)> = + // module_graph.get_dependencies(module_id); + let mut module_graph = context.module_graph.write().unwrap(); + let module = module_graph.get_module_mut(module_id).unwrap(); + let info = module.info.as_mut().unwrap(); + let ast = &mut info.ast; + + let deps_to_replace = DependenciesToReplace { + resolved: resolved_deps, + missing: info.deps.missing_deps.clone(), + }; + + if let ModuleAst::Script(ast) = ast { + transform_js_generate( + &module.id, + context, + ast, + &deps_to_replace, + module.is_entry, + ); + } + + Ok(()) + }) + .collect::>>()?; Ok(()) } - pub fn write_to_dist, C: AsRef<[u8]>>( - &self, - filename: P, - content: C, - context: &Arc, - ) { - let to = context.config.output.path.join(&filename); + fn write_to_dist, C: AsRef<[u8]>>(&self, filename: P, content: C) { + let to = self.context.config.output.path.join(&filename); let to = normalize_extension(to); - context + self.context .plugin_driver .before_write_fs(&to, content.as_ref()) .unwrap(); - if !context.config.output.skip_write { + if !self.context.config.output.skip_write { fs::write(to, content).unwrap(); } } -} - -impl Plugin for BundlessCompiler { - fn name(&self) -> &str { - "bundless_compiler" - } - fn modify_config(&self, config: &mut Config, root: &Path, _args: &Args) -> Result<()> { - if config.output.preserve_modules { - let preserve_path = config.output.preserve_modules_root.clone(); + pub(crate) fn generate(&self) -> Result<()> { + self.transform_all()?; - if !preserve_path.is_absolute() { - config.output.preserve_modules_root = root.join(preserve_path); - } - } - - Ok(()) - } - - fn generate(&self, context: &Arc) -> Result> { - self.transform_all(context)?; - - let mg = context.module_graph.read().unwrap(); + let mg = self.context.module_graph.read().unwrap(); let ids = mg.get_module_ids(); // TODO try tokio fs later ids.iter().for_each(|id| { - let target = to_dist_path(&id.id, context); + let target = to_dist_path(&id.id, &self.context); create_dir_all(target.parent().unwrap()).unwrap(); }); @@ -99,94 +155,41 @@ impl Plugin for BundlessCompiler { // nothing // todo: generate resolved AJSON } else { - let code = js_ast.generate(context.clone()).unwrap().code; - let target = to_dist_path(&id.id, context); - self.write_to_dist(target, code, context); + let code = js_ast.generate(self.context.clone()).unwrap().code; + let target = to_dist_path(&id.id, &self.context); + self.write_to_dist(target, code); } } ModuleAst::Css(_style) => {} ModuleAst::None => { - let target = to_dist_path(&id.id, context); - self.write_to_dist(target, &info.raw, context); + let target = to_dist_path(&id.id, &self.context); + self.write_to_dist(target, &info.raw); } } }); - Ok(Some(())) + Ok(()) } } -fn transform_modules(module_ids: Vec, context: &Arc) -> Result<()> { - crate::mako_profile_function!(); - - module_ids - .par_iter() - .map(|module_id| { - let module_graph = context.module_graph.read().unwrap(); - let deps = module_graph.get_dependencies(module_id); - - let module_dist_path = to_dist_path(&module_id.id, context) - .parent() - .unwrap() - .to_path_buf(); - - let resolved_deps = deps - .clone() - .into_iter() - // .map(|(id, dep)| (dep.source.clone(), id.generate(context))) - .map(|(id, dep)| { - let dep_dist_path = to_dist_path(&id.id, context); - - let rel_path = - diff_paths(&dep_dist_path, &module_dist_path).ok_or_else(|| { - anyhow!( - "failed to get relative path from {:?} to {:?}", - dep_dist_path, - module_dist_path - ) - })?; - - let rel_path = normalize_extension(rel_path); - - let replacement: String = { - let mut to_path = rel_path.to_str().unwrap().to_string(); - if to_path.starts_with("./") || to_path.starts_with("../") { - to_path - } else { - to_path.insert_str(0, "./"); - to_path - } - }; - - Ok((dep.source.clone(), (replacement.clone(), replacement))) - }) - .collect::>>(); - - let resolved_deps: HashMap = - resolved_deps?.into_iter().collect(); - - drop(module_graph); - - // let deps: Vec<(&ModuleId, &crate::module::Dependency)> = - // module_graph.get_dependencies(module_id); - let mut module_graph = context.module_graph.write().unwrap(); - let module = module_graph.get_module_mut(module_id).unwrap(); - let info = module.info.as_mut().unwrap(); - let ast = &mut info.ast; - - let deps_to_replace = DependenciesToReplace { - resolved: resolved_deps, - missing: info.deps.missing_deps.clone(), - }; - - if let ModuleAst::Script(ast) = ast { - transform_js_generate(&module.id, context, ast, &deps_to_replace, module.is_entry); +pub struct BundlessCompilerPlugin {} + +impl Plugin for BundlessCompilerPlugin { + fn name(&self) -> &str { + "bundless_compiler" + } + + fn modify_config(&self, config: &mut Config, root: &Path, _args: &Args) -> Result<()> { + if config.output.preserve_modules { + let preserve_path = config.output.preserve_modules_root.clone(); + + if !preserve_path.is_absolute() { + config.output.preserve_modules_root = root.join(preserve_path); } + } - Ok(()) - }) - .collect::>>()?; - Ok(()) + Ok(()) + } } fn transform_js_generate( diff --git a/crates/mako/src/plugins/copy.rs b/crates/mako/src/plugins/copy.rs index 39def1084..83c365952 100644 --- a/crates/mako/src/plugins/copy.rs +++ b/crates/mako/src/plugins/copy.rs @@ -75,12 +75,12 @@ impl Plugin for CopyPlugin { "copy" } - fn build_success(&self, _stats: &StatsJsonMap, context: &Arc) -> Result> { + fn build_success(&self, _stats: &StatsJsonMap, context: &Arc) -> Result<()> { CopyPlugin::copy(context)?; if context.args.watch { CopyPlugin::watch(context); } - Ok(None) + Ok(()) } } diff --git a/crates/mako/src/plugins/graphviz.rs b/crates/mako/src/plugins/graphviz.rs index ce3bc1f15..65d78bb42 100644 --- a/crates/mako/src/plugins/graphviz.rs +++ b/crates/mako/src/plugins/graphviz.rs @@ -35,7 +35,7 @@ impl Plugin for Graphviz { "graphviz" } - fn generate_beg(&self, context: &Arc) -> Result<()> { + fn generate_begin(&self, context: &Arc) -> Result<()> { Graphviz::write_graph( context.root.join("_mako_module_graph_origin.dot"), &context.module_graph.read().unwrap().graph, @@ -55,7 +55,7 @@ impl Plugin for Graphviz { &self, _params: &PluginGenerateEndParams, context: &Arc, - ) -> Result> { + ) -> Result<()> { Graphviz::write_graph( context.root.join("_mako_chunk_graph_finale.dot"), &context.chunk_graph.read().unwrap().graph, @@ -66,6 +66,6 @@ impl Plugin for Graphviz { &context.module_graph.read().unwrap().graph, )?; - Ok(None) + Ok(()) } } diff --git a/crates/mako/src/plugins/manifest.rs b/crates/mako/src/plugins/manifest.rs index 3e8590c66..5c7ca838e 100644 --- a/crates/mako/src/plugins/manifest.rs +++ b/crates/mako/src/plugins/manifest.rs @@ -21,7 +21,7 @@ impl Plugin for ManifestPlugin { "manifest" } - fn build_success(&self, _stats: &StatsJsonMap, context: &Arc) -> Result> { + fn build_success(&self, _stats: &StatsJsonMap, context: &Arc) -> Result<()> { if let Some(manifest_config) = &context.config.manifest { let assets = &context.stats_info.get_assets(); let mut manifest: BTreeMap = BTreeMap::new(); @@ -41,7 +41,7 @@ impl Plugin for ManifestPlugin { fs::write(output_path, manifest_json).unwrap(); } - Ok(None) + Ok(()) } } diff --git a/crates/mako/src/plugins/minifish.rs b/crates/mako/src/plugins/minifish.rs index 04fc6b367..feef90ecd 100644 --- a/crates/mako/src/plugins/minifish.rs +++ b/crates/mako/src/plugins/minifish.rs @@ -172,7 +172,7 @@ impl Plugin for MinifishPlugin { Ok(()) } - fn build_success(&self, _stats: &StatsJsonMap, context: &Arc) -> Result> { + fn build_success(&self, _stats: &StatsJsonMap, context: &Arc) -> Result<()> { if let Some(meta_path) = &self.meta_path { let mg = context.module_graph.read().unwrap(); @@ -217,7 +217,7 @@ impl Plugin for MinifishPlugin { .map_err(|e| anyhow!("write meta file({}) error: {}", meta_path.display(), e))?; } - Ok(None) + Ok(()) } } #[derive(Serialize)] diff --git a/crates/mako/src/plugins/ssu.rs b/crates/mako/src/plugins/ssu.rs index a762e5f45..843e3d152 100644 --- a/crates/mako/src/plugins/ssu.rs +++ b/crates/mako/src/plugins/ssu.rs @@ -453,7 +453,7 @@ module.export = Promise.all( Ok(()) } - fn build_start(&self, context: &Arc) -> Result> { + fn build_start(&self, context: &Arc) -> Result<()> { if let Some(content) = self.load_cached_state(context) { let mut state = self.cached_state.lock().unwrap(); *state = content; @@ -461,7 +461,7 @@ module.export = Promise.all( self.current_state.lock().unwrap().config_hash = Self::config_hash(&context.config); - Ok(None) + Ok(()) } fn runtime_plugins(&self, _context: &Arc) -> Result> { diff --git a/crates/mako/src/stats.rs b/crates/mako/src/stats.rs index 5caa57b3c..adf134917 100644 --- a/crates/mako/src/stats.rs +++ b/crates/mako/src/stats.rs @@ -1,9 +1,7 @@ -use std::cell::RefCell; use std::cmp::Ordering; use std::collections::HashMap; use std::fs; -use std::path::PathBuf; -use std::rc::Rc; +use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use std::time::{SystemTime, UNIX_EPOCH}; @@ -303,7 +301,7 @@ pub fn create_stats_info(compile_time: u128, compiler: &Compiler) -> StatsJsonMa let chunks = chunk_graph.get_chunks(); // 在 chunks 中获取 modules - let modules_vec: Rc>> = Rc::new(RefCell::new(Vec::new())); + let mut chunk_modules: Vec = Vec::new(); // 获取 chunks stats_map.chunks = chunks @@ -334,7 +332,7 @@ pub fn create_stats_info(compile_time: u128, compiler: &Compiler) -> StatsJsonMa // TODO: 现在是从每个 chunk 中找到包含的 module, 所以 chunk_id 是单个, 但是一个 module 有可能存在于多个 chunk 中 chunks: vec![chunk.id.id.clone()], }; - modules_vec.borrow_mut().push(module.clone()); + chunk_modules.push(module.clone()); module }) .collect(); @@ -429,8 +427,6 @@ pub fn create_stats_info(compile_time: u128, compiler: &Compiler) -> StatsJsonMa _ => None, }) .collect::>(); - let chunk_modules: Vec = - modules_vec.borrow().iter().cloned().collect(); stats_map.chunk_modules = chunk_modules; stats_map.modules = stats_info.get_modules(); @@ -440,8 +436,8 @@ pub fn create_stats_info(compile_time: u128, compiler: &Compiler) -> StatsJsonMa stats_map } -pub fn write_stats(stats: &StatsJsonMap, compiler: &Compiler) { - let path = &compiler.context.config.output.path.join("stats.json"); +pub fn write_stats(stats: &StatsJsonMap, path: &Path) { + let path = path.join("stats.json"); let stats_json = serde_json::to_string_pretty(stats).unwrap(); fs::write(path, stats_json).unwrap(); }