Skip to content

Commit

Permalink
fix(skip_modules): find export source terminated when meets default i…
Browse files Browse the repository at this point in the history
…mport (#862)

* chore: 🔧 skip modules default enabled

* fix: 🐛 found export source skip default

* test: ✅ update testcases

* test: ✅ add lodash-es default import

* chore: ⬆️ update pnpm-lock

* test: ✅ immigrate wepback side-effects test cases

* feat: ✨ 支持最终导出符号在 cjs 模块中的 case

* test: ✅  ts -> js 方便使用 webpack 编译对比

* chore: 🔧 enable skipModules in with-antd

* chore: ➕ add missing @jest/expect

* chore: ✏️  binding d.ts upddate
  • Loading branch information
stormslowly authored Jan 18, 2024
1 parent cb8ce77 commit 705e992
Show file tree
Hide file tree
Showing 143 changed files with 1,668 additions and 56 deletions.
2 changes: 1 addition & 1 deletion crates/mako/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ const DEFAULT_CONFIG: &str = r#"
"optimizePackageImports": false,
"emotion": false,
"flexBugs": false,
"optimization": { "skipModules": false },
"optimization": { "skipModules": true },
"react": {
"pragma": "React.createElement",
"importSource": "react",
Expand Down
2 changes: 0 additions & 2 deletions crates/mako/src/plugins/farm_tree_shake/module.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
mod import_exports;

use std::collections::{HashMap, HashSet};

use mako_core::swc_common::SyntaxContext;
Expand Down
1 change: 1 addition & 0 deletions crates/mako/src/plugins/farm_tree_shake/shake.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod find_export_source;
pub mod skip_module;

use std::cell::RefCell;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ use crate::plugins::farm_tree_shake::shake::strip_context;
use crate::plugins::farm_tree_shake::statement_graph::{ExportSpecifierInfo, ImportSpecifierInfo};

impl TreeShakeModule {
pub fn find_export_source(&self, ident: &String) -> Option<ReExportSource> {
pub fn find_skipable_export_source(&self, ident: &String) -> Option<ReExportSource> {
let mut local_ident = None;
let mut re_export_type = None;

let mut ambiguous_named = vec![];

for stmt in self.stmt_graph.stmts() {
if let Some(export_info) = &stmt.export_info {
if let Some(export_specifier) = export_info.find_export_specifier(ident) {
Expand All @@ -21,10 +23,17 @@ impl TreeShakeModule {
});
}
}
ExportSpecifierInfo::Ambiguous(_) => {
// TODO
// Ambiguous usually means mixed with cjs, currently cjs
// always has side effects
ExportSpecifierInfo::Ambiguous(all_exports) => {
let reexport_source = ReExportSource {
re_export_type: ReExportType::Named(strip_context(ident)),
source: Some(source.clone()),
};

if all_exports.iter().any(|i| is_ident_sym_equal(i, ident)) {
return Some(reexport_source);
} else {
ambiguous_named.push(reexport_source);
}
}
ExportSpecifierInfo::Named { exported, local } => {
let stripped_local = strip_context(local);
Expand Down Expand Up @@ -54,7 +63,10 @@ impl TreeShakeModule {
ExportSpecifierInfo::Default(_) => {
// Never when export with source
// export default from "x" is not supported in mako
return None;

if ident == "default" {
return None;
}
}
// export * as x from "x"
ExportSpecifierInfo::Namespace(name) => {
Expand All @@ -65,8 +77,6 @@ impl TreeShakeModule {
source: Some(source.clone()),
});
}

return None;
}
}
} else {
Expand Down Expand Up @@ -112,6 +122,10 @@ impl TreeShakeModule {
}
}

if ambiguous_named.len() == 1 {
return ambiguous_named.pop();
}

if let Some(local) = &local_ident {
for stmt in self.stmt_graph.stmts() {
if let Some(import_info) = &stmt.import_info {
Expand Down Expand Up @@ -144,10 +158,7 @@ impl TreeShakeModule {
}
ImportSpecifierInfo::Default(name) => {
if local == name {
return Some(ReExportSource {
re_export_type: ReExportType::Default,
source: Some(import_info.source.clone()),
});
return None;
}
}
}
Expand Down Expand Up @@ -192,30 +203,24 @@ mod tests {
fn test_find_import_default_export_named() {
let tsm = tsm_with_code(r#" import a from "./a.js"; export {a}; "#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
"ReExport from ./a.js by Default"
);
assert!(re_export_source.is_none());
}

#[test]
fn test_find_import_default_export_default() {
let tsm = tsm_with_code(r#" import a from "./a.js"; export default a;"#);

let re_export_source = tsm.find_export_source(&"default".to_string());
let re_export_source = tsm.find_skipable_export_source(&"default".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
"ReExport from ./a.js by Default"
);
assert!(re_export_source.is_none());
}
#[test]
fn test_find_import_named_export_default() {
let tsm = tsm_with_code(r#" import {a} from "./a.js"; export default a;"#);

let re_export_source = tsm.find_export_source(&"default".to_string());
let re_export_source = tsm.find_skipable_export_source(&"default".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -227,7 +232,7 @@ mod tests {
fn test_find_import_named_renamed_export_default() {
let tsm = tsm_with_code(r#" import {z as a} from "./a.js"; export default a;"#);

let re_export_source = tsm.find_export_source(&"default".to_string());
let re_export_source = tsm.find_skipable_export_source(&"default".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -239,7 +244,7 @@ mod tests {
fn test_find_import_namespace_export_default() {
let tsm = tsm_with_code(r#" import * as a from "./a.js"; export default a;"#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert!(re_export_source.is_none());
}
Expand All @@ -248,7 +253,7 @@ mod tests {
fn test_find_import_namespace_export_named() {
let tsm = tsm_with_code(r#" import * as a from "./a.js"; export { a };"#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -260,7 +265,7 @@ mod tests {
fn test_find_import_named_export_named() {
let tsm = tsm_with_code(r#" import { a } from "./a.js"; export { a };"#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -272,7 +277,7 @@ mod tests {
fn test_find_import_named_export_renamed() {
let tsm = tsm_with_code(r#" import { a } from "./a.js"; export { a as b };"#);

let re_export_source = tsm.find_export_source(&"b".to_string());
let re_export_source = tsm.find_skipable_export_source(&"b".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -284,7 +289,7 @@ mod tests {
fn test_find_import_renamed_export_renamed() {
let tsm = tsm_with_code(r#" import { a as b } from "./a.js"; export { b as c };"#);

let re_export_source = tsm.find_export_source(&"c".to_string());
let re_export_source = tsm.find_skipable_export_source(&"c".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -296,7 +301,7 @@ mod tests {
fn test_find_export_default_from() {
let tsm = tsm_with_code(r#" export { default } from "./a.js" "#);

let re_export_source = tsm.find_export_source(&"default".to_string());
let re_export_source = tsm.find_skipable_export_source(&"default".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -308,7 +313,7 @@ mod tests {
fn test_find_export_default_as_from() {
let tsm = tsm_with_code(r#" export { default as a } from "./a.js" "#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -320,7 +325,7 @@ mod tests {
fn test_find_export_named_from() {
let tsm = tsm_with_code(r#" export { a } from "./a.js" "#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -332,7 +337,7 @@ mod tests {
fn test_find_export_named_as_from() {
let tsm = tsm_with_code(r#" export { b as a } from "./a.js" "#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -344,7 +349,7 @@ mod tests {
fn test_find_export_star_as_from() {
let tsm = tsm_with_code(r#" export * as a from "./a.js" "#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -358,7 +363,7 @@ mod tests {
fn test_find_export_star_from() {
let tsm = tsm_with_code(r#" export * from "./a.js" "#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -370,7 +375,7 @@ mod tests {
fn test_find_export_default_local_ident() {
let tsm = tsm_with_code(r#"const a=1; export default a "#);

let re_export_source = tsm.find_export_source(&"default".to_string());
let re_export_source = tsm.find_skipable_export_source(&"default".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -382,7 +387,7 @@ mod tests {
fn test_find_export_default_function() {
let tsm = tsm_with_code(r#"export default function test(){} "#);

let re_export_source = tsm.find_export_source(&"default".to_string());
let re_export_source = tsm.find_skipable_export_source(&"default".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -394,7 +399,7 @@ mod tests {
fn test_find_export_default_class() {
let tsm = tsm_with_code(r#" export default class Test{} "#);

let re_export_source = tsm.find_export_source(&"default".to_string());
let re_export_source = tsm.find_skipable_export_source(&"default".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -406,7 +411,7 @@ mod tests {
fn test_find_export_named_class() {
let tsm = tsm_with_code(r#" export class TestClass{} "#);

let re_export_source = tsm.find_export_source(&"TestClass".to_string());
let re_export_source = tsm.find_skipable_export_source(&"TestClass".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -418,7 +423,7 @@ mod tests {
fn test_find_export_named_fn() {
let tsm = tsm_with_code(r#" export function fnTest(){} "#);

let re_export_source = tsm.find_export_source(&"fnTest".to_string());
let re_export_source = tsm.find_skipable_export_source(&"fnTest".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand All @@ -430,7 +435,7 @@ mod tests {
fn test_find_export_dec_expr() {
let tsm = tsm_with_code(r#" export const a = 1 "#);

let re_export_source = tsm.find_export_source(&"a".to_string());
let re_export_source = tsm.find_skipable_export_source(&"a".to_string());

assert_eq!(
re_export_source.unwrap().describe(),
Expand Down
8 changes: 7 additions & 1 deletion crates/mako/src/plugins/farm_tree_shake/shake/skip_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ fn find_ident_export_source(
return None;
}

if let Some(re_export_source) = proxy_tsm.find_export_source(used_ident) {
if let Some(re_export_source) = proxy_tsm.find_skipable_export_source(used_ident) {
if let Some(source) = &re_export_source.source {
if let Some(next_tsm_rc) =
get_imported_tree_shake_module(proxy_module_id, source, module_graph, tsm_map)
Expand Down Expand Up @@ -554,6 +554,12 @@ fn find_ident_export_source(
from_module_id: next_replace.from_module_id.clone(),
re_export_source: next_replace.re_export_source,
});
} else {
return Some(ReExportReplace {
re_export_ident: used_ident.clone(),
from_module_id: next_tsm.module_id.clone(),
re_export_source,
});
}
} else {
return Some(ReExportReplace {
Expand Down
8 changes: 7 additions & 1 deletion crates/mako/src/plugins/farm_tree_shake/statement_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ pub enum ExportInfoMatch {

impl ExportInfo {
pub fn find_export_specifier(&self, ident: &String) -> Option<&ExportSpecifierInfo> {
let mut ambiguous_specifier_candidates = vec![];

for specifier in self.specifiers.iter() {
match specifier {
ExportSpecifierInfo::Default(_) => {
Expand Down Expand Up @@ -154,11 +156,15 @@ impl ExportInfo {
return Some(specifier);
}

return None;
ambiguous_specifier_candidates.push(specifier);
}
}
}

if ambiguous_specifier_candidates.len() == 1 {
return ambiguous_specifier_candidates.pop();
}

None
}

Expand Down
6 changes: 6 additions & 0 deletions crates/node/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ export interface BuildParams {
| {
skipModules?: boolean;
};
react?: {
runtime?: 'automatic' | 'classic';
pragma?: string;
importSource?: string;
pragmaFrag?: string;
};
};
hooks: JsHooks;
watch: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ const { files } = parseBuildResult(__dirname);

const content = files['index.js'];

assert(!content.includes('node_modules/pure'), `should skip pure module`);
assert(
content.includes('node_modules/pure/index.js'),
`should not skip pure module when it use default import`,
);
assert(
content.includes('node_modules/side_effects/index.js'),
`should keep all side effects modules`,
Expand All @@ -13,5 +16,3 @@ assert(
content.includes('node_modules/side_effects/dep.js'),
`should keep all side effects modules`,
);

assert(content.includes('index.default'), `should change field name`);
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"optimization": { "skipModules": true },
"optimizePackageImports": false
"optimizePackageImports": false,
"entry":{
"index": "src/index.js"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Object(exports).value = 123;
Object(exports).value2 = 42;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { value, value2 } from "./module";

throw new Error("Should not be loaded");
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const value = 42;
export * from "./dynamic";
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./module";
export const valueUsed = __webpack_exports_info__.value.used;
Loading

0 comments on commit 705e992

Please sign in to comment.