diff --git a/Cargo.lock b/Cargo.lock index 6119674e8..8bd2e8488 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1223,6 +1223,16 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + [[package]] name = "delegate" version = "0.12.0" @@ -2654,11 +2664,11 @@ dependencies = [ "maplit", "md5", "mdxjs", + "merge-source-map", "miette 5.10.0", "mimalloc-rust", "mime_guess", "nanoid", - "nohash-hasher", "notify", "notify-debouncer-full", "open", @@ -2803,6 +2813,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "merge-source-map" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f20543fa819b8d7b4f0fd51514aef9cfad3b1d746ad88c63d2f68b2b8cc034dd" +dependencies = [ + "sourcemap 7.0.1", +] + [[package]] name = "miette" version = "4.7.1" @@ -4465,6 +4484,22 @@ dependencies = [ "url", ] +[[package]] +name = "sourcemap" +version = "7.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10da010a590ed2fa9ca8467b00ce7e9c5a8017742c0c09c45450efc172208c4b" +dependencies = [ + "data-encoding", + "debugid", + "if_chain", + "rustc_version", + "serde", + "serde_json", + "unicode-id", + "url", +] + [[package]] name = "st-map" version = "0.2.0" @@ -4660,7 +4695,7 @@ dependencies = [ "rustc-hash", "serde", "serde_json", - "sourcemap", + "sourcemap 6.2.3", "swc_atoms 0.5.9", "swc_cached", "swc_common 0.32.1", @@ -4851,7 +4886,7 @@ dependencies = [ "rustc-hash", "serde", "siphasher", - "sourcemap", + "sourcemap 6.2.3", "string_cache", "swc_atoms 0.5.9", "swc_eq_ignore_macros", @@ -5201,7 +5236,7 @@ dependencies = [ "once_cell", "rustc-hash", "serde", - "sourcemap", + "sourcemap 6.2.3", "swc_atoms 0.4.43", "swc_common 0.30.5", "swc_ecma_ast 0.102.5", @@ -5220,7 +5255,7 @@ dependencies = [ "once_cell", "rustc-hash", "serde", - "sourcemap", + "sourcemap 6.2.3", "swc_atoms 0.5.9", "swc_common 0.31.22", "swc_ecma_ast 0.107.8", @@ -5239,7 +5274,7 @@ dependencies = [ "once_cell", "rustc-hash", "serde", - "sourcemap", + "sourcemap 6.2.3", "swc_atoms 0.5.9", "swc_common 0.32.1", "swc_ecma_ast 0.109.1", @@ -5756,7 +5791,7 @@ dependencies = [ "serde", "serde_json", "sha-1", - "sourcemap", + "sourcemap 6.2.3", "swc_common 0.32.1", "swc_ecma_ast 0.109.1", "swc_ecma_codegen 0.145.5", @@ -5913,7 +5948,7 @@ dependencies = [ "radix_fmt", "regex", "serde", - "sourcemap", + "sourcemap 6.2.3", "swc_atoms 0.5.9", "swc_common 0.32.1", "swc_ecma_ast 0.109.1", diff --git a/crates/mako/Cargo.toml b/crates/mako/Cargo.toml index 296a1b64c..2fe7c6242 100644 --- a/crates/mako/Cargo.toml +++ b/crates/mako/Cargo.toml @@ -90,8 +90,8 @@ indexmap = "2.0.0" indicatif = "0.17.8" md5 = "0.7.0" mdxjs = "0.1.14" +merge-source-map = "1.2.0" mime_guess = "2.0.4" -nohash-hasher = "0.2.0" notify = { version = "6.1.1", default-features = false, features = ["macos_kqueue"] } notify-debouncer-full = { version = "0.3.1", default-features = false } parking_lot = { version = "0.12", features = ["nightly"] } diff --git a/crates/mako/src/ast/sourcemap.rs b/crates/mako/src/ast/sourcemap.rs index 86695a61d..f9033a861 100644 --- a/crates/mako/src/ast/sourcemap.rs +++ b/crates/mako/src/ast/sourcemap.rs @@ -1,8 +1,9 @@ -use std::collections::HashMap; use std::path::PathBuf; +use merge_source_map::sourcemap::SourceMap as MergeSourceMap; +use merge_source_map::{merge, MergeOptions}; use pathdiff::diff_paths; -use swc_core::base::sourcemap as swc_sourcemap; +use swc_core::base::sourcemap; use swc_core::common::source_map::SourceMapGenConfig; use swc_core::common::sync::Lrc; use swc_core::common::{BytePos, FileName, LineCol, SourceMap}; @@ -33,7 +34,7 @@ pub fn build_source_map_to_buf(mappings: &[(BytePos, LineCol)], cm: &Lrc, -) -> swc_sourcemap::SourceMap { +) -> sourcemap::SourceMap { let config = SwcSourceMapGenConfig; cm.build_source_map_with_config(mappings, None, config) @@ -44,14 +45,14 @@ pub fn build_source_map( #[derive(Clone, Default, Debug)] pub struct RawSourceMap { pub file: Option, - pub tokens: Vec, + pub tokens: Vec, pub names: Vec, pub sources: Vec, pub sources_content: Vec>, } -impl From for RawSourceMap { - fn from(sm: swc_sourcemap::SourceMap) -> Self { +impl From for RawSourceMap { + fn from(sm: sourcemap::SourceMap) -> Self { Self { file: sm.get_file().map(|f| f.to_owned()), tokens: sm.tokens().map(|t| t.get_raw_token()).collect(), @@ -65,7 +66,7 @@ impl From for RawSourceMap { } } -impl From for swc_sourcemap::SourceMap { +impl From for sourcemap::SourceMap { fn from(rsm: RawSourceMap) -> Self { Self::new( rsm.file, @@ -77,124 +78,25 @@ impl From for swc_sourcemap::SourceMap { } } -pub fn merge_source_map( - target_source_map: swc_sourcemap::SourceMap, - chain_map: HashMap>, - root: &PathBuf, -) -> swc_sourcemap::SourceMap { - let mut builder = swc_sourcemap::SourceMapBuilder::new(None); - target_source_map.tokens().for_each(|token| { - if let Some(source) = token.get_source() { - let mut final_token = token; - let mut searched_in_chain = true; - - if let Some(source_map_chain) = chain_map.get(source) - && !source_map_chain.is_empty() - { - for map in source_map_chain.iter().rev() { - if let Some(map_token) = - map.lookup_token(token.get_src_line(), token.get_src_col()) - { - final_token = map_token; - } else { - searched_in_chain = false; - break; - } - } - - if !searched_in_chain { - return; - } - - // replace source - let replaced_source = final_token.get_source().map(|src| { - diff_paths(src, root) - .unwrap_or(src.into()) - .to_string_lossy() - .to_string() - }); - - // add mapping - let added_token = builder.add( - token.get_dst_line(), - token.get_dst_col(), - final_token.get_src_line(), - final_token.get_src_col(), - replaced_source.as_deref(), - final_token.get_name(), - ); - - // add source centent - if !builder.has_source_contents(added_token.src_id) { - let source_content = final_token.get_source_view().map(|view| view.source()); - - builder.set_source_contents(added_token.src_id, source_content); - } - } - } - }); - - builder.into_sourcemap() -} - -#[cfg(test)] -mod test { - use std::collections::HashMap; - use std::path::PathBuf; - use std::str::FromStr; - - use crate::ast::sourcemap::{merge_source_map, swc_sourcemap}; - - #[test] - fn test_merge() { - let sourcemap1 = r#"{ - "version": 3, - "file": "index.js", - "sourceRoot": "", - "sources": [ - "index.ts" - ], - "names": [], - "mappings": "AAAA,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,CAAC,GAAG,CAAC,iBAAU,IAAI,CAAE,CAAC,CAAC;AAChC,CAAC", - "sourcesContent": [ - "function sayHello(name: string) {\n console.log(`Hello, ${name}`);\n}\n" - ] - }"#; - let sourcemap2 = r#"{ - "version": 3, - "file": "minify.js", - "sourceRoot": "", - "sources": [ - "index.ts" - ], - "names": [ - "sayHello", - "name", - "console", - "log", - "concat" - ], - "mappings": "AAAA,SAASA,SAASC,CAAI,EAClBC,QAAQC,GAAG,CAAC,UAAUC,MAAM,CAACH,GACjC", - "sourcesContent": [ - "function sayHello(name) {\n console.log(\"Hello, \".concat(name));\n}\n" - ] - }"#; - - let merged_source_map = merge_source_map( - swc_sourcemap::SourceMap::from_reader(sourcemap2.as_bytes()).unwrap(), - HashMap::>::from([( - "index.ts".to_string(), - vec![swc_sourcemap::SourceMap::from_reader(sourcemap1.as_bytes()).unwrap()], - )]), - &PathBuf::from_str("./").unwrap(), - ); - - let mut buf = vec![]; - - merged_source_map.to_writer(&mut buf).unwrap(); - - let merged = String::from_utf8(buf).unwrap(); - - assert!(merged.eq(r#"{"version":3,"sources":["index.ts"],"sourcesContent":["function sayHello(name: string) {\n console.log(`Hello, ${name}`);\n}\n"],"names":[],"mappings":"AAAA,SAAS,SAAS,CAAY,EAC5B,QAAQ,GAAG,CAAC,UAAA,MAAA,CAAU,GACxB"}"#)); - } +pub fn merge_source_map(source_map_chain: Vec>, root: PathBuf) -> Vec { + let source_map_chain = source_map_chain + .iter() + .map(|s| MergeSourceMap::from_slice(s).unwrap()) + .collect::>(); + + let merged = merge( + source_map_chain, + MergeOptions { + source_replacer: Some(Box::new(move |src| { + diff_paths(src, &root) + .unwrap_or(src.into()) + .to_string_lossy() + .to_string() + })), + }, + ); + + let mut buf = vec![]; + merged.to_writer(&mut buf).unwrap(); + buf } diff --git a/crates/mako/src/generate/chunk_pot/ast_impl.rs b/crates/mako/src/generate/chunk_pot/ast_impl.rs index 44372edce..8a783bbb7 100644 --- a/crates/mako/src/generate/chunk_pot/ast_impl.rs +++ b/crates/mako/src/generate/chunk_pot/ast_impl.rs @@ -4,8 +4,6 @@ use std::sync::Arc; use anyhow::Result; use cached::proc_macro::cached; use cached::SizedCache; -use pathdiff::diff_paths; -use swc_core::base::sourcemap as swc_sourcemap; use swc_core::common::{Mark, DUMMY_SP, GLOBALS}; use swc_core::css::ast::Stylesheet; use swc_core::css::codegen::writer::basic::{BasicCssWriter, BasicCssWriterConfig}; @@ -17,7 +15,7 @@ use swc_core::ecma::ast::{ use swc_core::ecma::utils::{quote_ident, quote_str, ExprFactory}; use crate::ast::js_ast::JsAst; -use crate::ast::sourcemap::{build_source_map, merge_source_map}; +use crate::ast::sourcemap::{build_source_map_to_buf, merge_source_map}; use crate::compiler::Context; use crate::config::Mode; use crate::generate::chunk::{Chunk, ChunkType}; @@ -84,40 +82,22 @@ pub(crate) fn render_css_chunk( None => None, _ => { mako_profile_scope!("build_source_map"); + // source map chain + let mut source_map_chain: Vec> = vec![]; let module_graph = context.module_graph.read().unwrap(); - let chunk_source_map = build_source_map(&source_map, cm); - - let mut chain_map = HashMap::>::new(); - chunk.get_modules().iter().for_each(|module_id| { - if let Some(module) = module_graph.get_module(module_id) { - if let Some(info) = module.info.as_ref() - && matches!(info.ast, crate::module::ModuleAst::Css(_)) - { - let relative_source = diff_paths(&module_id.id, &context.root) - .unwrap_or((&module_id.id).into()) - .to_string_lossy() - .to_string(); - - chain_map.insert( - relative_source, - info.source_map_chain - .iter() - .map(|sc| swc_sourcemap::SourceMap::from_slice(sc).unwrap()) - .collect::>(), - ); - } + let module = module_graph.get_module(module_id).unwrap(); + if let Some(info) = module.info.as_ref() + && matches!(info.ast, crate::module::ModuleAst::Css(_)) + { + source_map_chain.append(&mut info.source_map_chain.clone()); } }); - let merged_source_map = merge_source_map(chunk_source_map, chain_map, &context.root); - - let mut buf = vec![]; - - merged_source_map.to_writer(&mut buf).unwrap(); + source_map_chain.push(build_source_map_to_buf(&source_map, cm)); - Some(buf) + Some(merge_source_map(source_map_chain, context.root.clone())) } }; diff --git a/crates/mako/src/generate/group_chunk.rs b/crates/mako/src/generate/group_chunk.rs index 742a402c0..d58dc999d 100644 --- a/crates/mako/src/generate/group_chunk.rs +++ b/crates/mako/src/generate/group_chunk.rs @@ -388,11 +388,16 @@ impl Compiler { let chunk_id = entry_module_id.generate(&self.context); let mut chunk = Chunk::new(chunk_id.into(), chunk_type.clone()); - let mut normal_deps = HashSet::<&ModuleId>::from_iter([entry_module_id]); + let mut visited_modules: Vec<&ModuleId> = vec![entry_module_id]; let module_graph = self.context.module_graph.read().unwrap(); visit_modules(vec![entry_module_id.clone()], None, |head| { + let parent_index = visited_modules + .iter() + .position(|m| m.id == head.id) + .unwrap_or(0); + let mut normal_deps = vec![]; let mut next_module_ids = vec![]; for (dep_module_id, dep) in module_graph.get_dependencies(head) { @@ -413,22 +418,21 @@ impl Compiler { { next_module_ids.push(dep_module_id.clone()); // collect normal deps for current head - normal_deps.insert(dep_module_id); + normal_deps.push(dep_module_id); } _ => {} } } + // insert normal deps before head, so that we can keep the dfs order + visited_modules.splice(parent_index..parent_index, normal_deps); + next_module_ids }); - let mut deps = module_graph.get_dependencies_by_link_back_dfs(entry_module_id); - // add modules to chunk as dfs order - while let Some(module_id) = deps.pop() { - if let Some(module_id) = normal_deps.take(module_id) { - chunk.add_module(module_id.clone()); - } + for module_id in visited_modules { + chunk.add_module(module_id.clone()); } (chunk, dynamic_entries, worker_entries) diff --git a/crates/mako/src/generate/optimize_chunk.rs b/crates/mako/src/generate/optimize_chunk.rs index b4c662083..e5ce023ca 100644 --- a/crates/mako/src/generate/optimize_chunk.rs +++ b/crates/mako/src/generate/optimize_chunk.rs @@ -125,7 +125,7 @@ impl Compiler { let async_chunk_root_modules = chunks .iter() .filter_map(|chunk| match chunk.chunk_type { - ChunkType::Async => chunk.modules.back(), + ChunkType::Async => chunk.modules.iter().last(), _ => None, }) .collect::>(); diff --git a/crates/mako/src/module_graph.rs b/crates/mako/src/module_graph.rs index 80febdee3..2d17ed2cb 100644 --- a/crates/mako/src/module_graph.rs +++ b/crates/mako/src/module_graph.rs @@ -2,20 +2,15 @@ use std::collections::{HashMap, HashSet}; use std::fmt; use fixedbitset::FixedBitSet; -use hashlink::LinkedHashSet; -use nohash_hasher::BuildNoHashHasher; use petgraph::graph::{DefaultIx, NodeIndex}; -use petgraph::prelude::Dfs; +use petgraph::prelude::{Dfs, EdgeRef}; use petgraph::stable_graph::{StableDiGraph, WalkNeighbors}; -use petgraph::visit::{EdgeRef, IntoEdgeReferences}; +use petgraph::visit::IntoEdgeReferences; use petgraph::Direction; use tracing::debug; use crate::module::{Dependencies, Dependency, Module, ModuleId, ResolveType}; -mod link_back_dfs_visit; -use link_back_dfs_visit::LinkBackDfs; - #[derive(Debug)] pub struct ModuleGraph { id_index_map: HashMap>, @@ -209,28 +204,6 @@ impl ModuleGraph { deps } - pub fn get_dependencies_by_link_back_dfs(&self, module_id: &ModuleId) -> Vec<&ModuleId> { - let start = self.id_index_map.get(module_id).unwrap(); - let mut dfs_post_order = LinkBackDfs::new(&self.graph, *start); - let mut deps = LinkedHashSet::>::with_hasher( - BuildNoHashHasher::default(), - ); - while let Some(nth) = dfs_post_order.next(&self.graph, |ex| { - let dependencies = self.graph.edge_weight(ex).unwrap(); - dependencies.iter().any(|d| { - matches!( - d.resolve_type, - ResolveType::DynamicImport | ResolveType::Worker - ) - }) - }) { - deps.insert(nth.index()); - } - deps.iter() - .map(|e| &self.graph[NodeIndex::new(*e)].id) - .collect() - } - pub fn get_dependents(&self, module_id: &ModuleId) -> Vec<(&ModuleId, &Dependency)> { let mut edges = self.get_edges(module_id, Direction::Incoming); let mut deps: Vec<(&ModuleId, &Dependency)> = vec![]; diff --git a/crates/mako/src/module_graph/link_back_dfs_visit.rs b/crates/mako/src/module_graph/link_back_dfs_visit.rs deleted file mode 100644 index 233b0d172..000000000 --- a/crates/mako/src/module_graph/link_back_dfs_visit.rs +++ /dev/null @@ -1,75 +0,0 @@ -use std::fmt::Debug; - -use fixedbitset::FixedBitSet; -use hashlink::{linked_hash_map, LinkedHashMap}; -use nohash_hasher::BuildNoHashHasher; -use petgraph::csr::IndexType; -use petgraph::graph::{EdgeIndex, NodeIndex}; -use petgraph::stable_graph::StableDiGraph; -use petgraph::visit::{VisitMap, Visitable}; -use petgraph::Direction; - -/// This visitor is for css ordering, see test cases of css-merge-in-js and css-merge-in-css -#[derive(Clone, Debug)] -pub struct LinkBackDfs { - pub stack: LinkedHashMap>, - pub discovered: FixedBitSet, - pub finished: FixedBitSet, -} - -impl LinkBackDfs { - pub fn new(graph: &StableDiGraph, start: NodeIndex) -> Self { - let mut dfs = Self::empty(graph); - dfs.move_to(start); - dfs - } - - pub fn empty(graph: &StableDiGraph) -> Self { - LinkBackDfs { - stack: LinkedHashMap::with_hasher(BuildNoHashHasher::default()), - discovered: graph.visit_map(), - finished: graph.visit_map(), - } - } - - pub fn move_to(&mut self, start: NodeIndex) { - self.stack.clear(); - self.stack.insert(start.index(), ()); - } - - pub fn next( - &mut self, - graph: &StableDiGraph, - execlude_edge: F, - ) -> Option - where - F: Fn(EdgeIndex) -> bool, - { - while let Some((&nx, _)) = self.stack.back() { - if self.discovered.visit(nx) { - let mut nxs = Vec::::new(); - - let mut walker = graph - .neighbors_directed(NodeIndex::new(nx), Direction::Outgoing) - .detach(); - while let Some((cex, cnx)) = walker.next(graph) { - if !execlude_edge(cex) { - nxs.push(cnx); - } - } - - while let Some(cnx) = nxs.pop() { - if let linked_hash_map::Entry::Occupied(entry) = self.stack.entry(nx.index()) { - entry.cursor_mut().insert_before(cnx.index(), ()); - } - } - } else { - self.stack.pop_back(); - if self.finished.visit(nx) { - return Some(NodeIndex::new(nx)); - } - } - } - None - } -} diff --git a/crates/mako/src/stats.rs b/crates/mako/src/stats.rs index 1061f2e7c..380c48c4b 100644 --- a/crates/mako/src/stats.rs +++ b/crates/mako/src/stats.rs @@ -126,9 +126,11 @@ impl Compiler { ChunkType::Sync => chunk_graph .dependents_chunk(&chunk.id) .iter() - .filter_map(|chunk_id| chunk_graph.chunk(chunk_id).unwrap().modules.back()) + .filter_map(|chunk_id| { + chunk_graph.chunk(chunk_id).unwrap().modules.iter().last() + }) .collect::>(), - _ => vec![chunk.modules.back().unwrap()], + _ => vec![chunk.modules.iter().last().unwrap()], }; let mut origins_set = IndexMap::new(); for origin_chunk_module in origin_chunk_modules { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e33406540..b2b91d465 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -512,9 +512,21 @@ importers: specifier: ^21.1.1 version: 21.1.1 optionalDependencies: + '@umijs/mako-darwin-arm64': + specifier: 0.8.5 + version: 0.8.5 + '@umijs/mako-darwin-x64': + specifier: 0.8.5 + version: 0.8.5 '@umijs/mako-linux-arm64-musl': specifier: 0.8.5 version: 0.8.5 + '@umijs/mako-linux-x64-gnu': + specifier: 0.8.5 + version: 0.8.5 + '@umijs/mako-linux-x64-musl': + specifier: 0.8.5 + version: 0.8.5 devDependencies: '@napi-rs/cli': specifier: ^2.18.0 @@ -6450,6 +6462,15 @@ packages: dev: true optional: true + /@umijs/mako-darwin-arm64@0.8.5: + resolution: {integrity: sha512-18QkvDD7FmDQ0AtbTLvrWMCPehq9qsjK5Rh0uVvvkihFBazOMhjM5eAX2Nd+n61I3gy6B34VvnbpdgFm3ryGYg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + /@umijs/mako-darwin-x64@0.7.4: resolution: {integrity: sha512-Umw5hNt63QQV6YxI4tKJxVy/cx5DAUmAStIiJ44YKjCD2RUbz7SQ0AzypoJwaQiK5LLI2ePQkb+H38k1Y0lfYQ==} engines: {node: '>= 10'} @@ -6459,6 +6480,15 @@ packages: dev: true optional: true + /@umijs/mako-darwin-x64@0.8.5: + resolution: {integrity: sha512-IJPO6j64WSs5Yv/AGviwDWwd4/3faytCxbVrBWzvh7Aaau61QGKq34UhHTGnb2zA1+Z+Xo2EmUkxAMLqIYnllw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + /@umijs/mako-linux-arm64-musl@0.8.5: resolution: {integrity: sha512-KX6aGkUIwHei+DlInsOd6YylwOKDUqCwLQ+xvf9yyp4eRQ9n2idIab3dJAsbBvNhSBm0eGUdt1qLV04DV8Oggg==} engines: {node: '>= 10'} @@ -6477,6 +6507,15 @@ packages: dev: true optional: true + /@umijs/mako-linux-x64-gnu@0.8.5: + resolution: {integrity: sha512-HydCu93FiWaM5OCiB918Fm8xEwMMhTNuyYhVWGP2bjqXxwSdTE0znuS4VT2kqZCjn5/2zxpF5CatRLoS+GZ5SQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@umijs/mako-linux-x64-musl@0.7.4: resolution: {integrity: sha512-49DhDNy8mHjCkduLvahOAVXY0X9c+R4pwgh5W3FjQgB61AT9jiJfPXyMnBIMvGu2hsk0tGzVWmRmRyfAuLmogQ==} engines: {node: '>= 10'} @@ -6486,6 +6525,15 @@ packages: dev: true optional: true + /@umijs/mako-linux-x64-musl@0.8.5: + resolution: {integrity: sha512-cobr1xQrOvTdQeE2f/4SSgG0s3Z+2RpEZXHtzSTGC6ic+RV+/6mGvYsDj7ho+5jnfh1kBYkuMKxeNaL477bWLQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + /@umijs/mako@0.7.4: resolution: {integrity: sha512-Wgfv13DHliBnNwefgR/ZtG31wTjmbxUuCtsiGnmUPcYxOv0qTQ+yhq1iaVNvQZm48/ohc6M2NIZeghSbbFp+/Q==} engines: {node: '>= 16'}