-
Notifications
You must be signed in to change notification settings - Fork 26.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add shake exports transform to next-swc (#32253)
* Add shake exports transform to next-swc * Less cloning * Use JsWord instead of String
- Loading branch information
Showing
8 changed files
with
227 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
use serde::Deserialize; | ||
use swc_atoms::js_word; | ||
use swc_atoms::JsWord; | ||
use swc_ecmascript::ast::*; | ||
use swc_ecmascript::transforms::optimization::simplify::dce::{dce, Config as DCEConfig}; | ||
use swc_ecmascript::visit::{Fold, FoldWith}; | ||
|
||
#[derive(Clone, Debug, Deserialize)] | ||
pub struct Config { | ||
pub ignore: Vec<JsWord>, | ||
} | ||
|
||
pub fn shake_exports(config: Config) -> impl Fold { | ||
ExportShaker { | ||
ignore: config.ignore, | ||
..Default::default() | ||
} | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
struct ExportShaker { | ||
ignore: Vec<JsWord>, | ||
remove_export: bool, | ||
} | ||
|
||
impl Fold for ExportShaker { | ||
fn fold_module(&mut self, module: Module) -> Module { | ||
let module = module.fold_children_with(self); | ||
let module = module.fold_with(&mut dce(DCEConfig::default())); | ||
|
||
module | ||
} | ||
|
||
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> { | ||
let mut new_items = vec![]; | ||
for item in items { | ||
let item = item.fold_children_with(self); | ||
if !self.remove_export { | ||
new_items.push(item) | ||
} | ||
self.remove_export = false; | ||
} | ||
new_items | ||
} | ||
|
||
fn fold_export_decl(&mut self, mut decl: ExportDecl) -> ExportDecl { | ||
match &mut decl.decl { | ||
Decl::Fn(fn_decl) => { | ||
if !self.ignore.contains(&fn_decl.ident.sym) { | ||
self.remove_export = true; | ||
} | ||
} | ||
Decl::Class(class_decl) => { | ||
if !self.ignore.contains(&class_decl.ident.sym) { | ||
self.remove_export = true; | ||
} | ||
} | ||
Decl::Var(var_decl) => { | ||
var_decl.decls = var_decl | ||
.decls | ||
.iter() | ||
.filter_map(|var_decl| { | ||
if let Pat::Ident(BindingIdent { id, .. }) = &var_decl.name { | ||
if self.ignore.contains(&id.sym) { | ||
return Some(var_decl.to_owned()); | ||
} | ||
} | ||
None | ||
}) | ||
.collect(); | ||
if var_decl.decls.is_empty() { | ||
self.remove_export = true; | ||
} | ||
} | ||
_ => {} | ||
} | ||
decl | ||
} | ||
|
||
fn fold_named_export(&mut self, mut export: NamedExport) -> NamedExport { | ||
export.specifiers = export | ||
.specifiers | ||
.into_iter() | ||
.filter_map(|spec| { | ||
if let ExportSpecifier::Named(named_spec) = spec { | ||
if let Some(ident) = &named_spec.exported { | ||
if self.ignore.contains(&ident.sym) { | ||
return Some(ExportSpecifier::Named(named_spec)); | ||
} | ||
} else if self.ignore.contains(&named_spec.orig.sym) { | ||
return Some(ExportSpecifier::Named(named_spec)); | ||
} | ||
} | ||
None | ||
}) | ||
.collect(); | ||
if export.specifiers.is_empty() { | ||
self.remove_export = true | ||
} | ||
export | ||
} | ||
|
||
fn fold_export_default_decl(&mut self, decl: ExportDefaultDecl) -> ExportDefaultDecl { | ||
if !self.ignore.contains(&js_word!("default")) { | ||
self.remove_export = true | ||
} | ||
decl | ||
} | ||
|
||
fn fold_export_default_expr(&mut self, expr: ExportDefaultExpr) -> ExportDefaultExpr { | ||
if !self.ignore.contains(&js_word!("default")) { | ||
self.remove_export = true | ||
} | ||
expr | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
packages/next-swc/crates/core/tests/fixture/shake-exports/keep-default/input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
let shouldBeRemoved = 'should be removed' | ||
export function removeFunction() { | ||
console.log(shouldBeRemoved); | ||
} | ||
|
||
let shouldBeKept = 'should be kept' | ||
export default function shouldBeKept() { | ||
console.log(shouldBeKept) | ||
} |
4 changes: 4 additions & 0 deletions
4
packages/next-swc/crates/core/tests/fixture/shake-exports/keep-default/output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
let shouldBeKept = "should be kept"; | ||
export default function shouldBeKept() { | ||
console.log(shouldBeKept); | ||
} |
36 changes: 36 additions & 0 deletions
36
packages/next-swc/crates/core/tests/fixture/shake-exports/most-usecases/input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
let shouldBeKept = 'should be kept' | ||
export async function keep() { | ||
console.log(shouldBeKept) | ||
} | ||
|
||
let shouldBeRemoved = 'should be removed' | ||
export function removeFunction() { | ||
console.log(shouldBeRemoved); | ||
} | ||
|
||
export let removeVarDeclaration = 'should be removed' | ||
export let removeVarDeclarationUndefined // should also be removed | ||
export let multipleDecl = 'should be removed', keep1 = 'should be kept' | ||
export let keep2 = 'should be kept' | ||
|
||
export class RemoveClass { | ||
remove() { | ||
console.log('should be removed') | ||
} | ||
} | ||
|
||
let x = 'x' | ||
let y = 'y' | ||
|
||
// This should be removed | ||
export {x, y as z} | ||
|
||
let keep3 = 'should be kept' | ||
let asKeep = 'should be kept' | ||
let removeNamed = 'should be removed' | ||
|
||
export {keep3, asKeep as keep4, removeNamed} | ||
|
||
export default function removeDefault() { | ||
console.log('should be removed') | ||
} |
9 changes: 9 additions & 0 deletions
9
packages/next-swc/crates/core/tests/fixture/shake-exports/most-usecases/output.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
let shouldBeKept = "should be kept"; | ||
export async function keep() { | ||
console.log(shouldBeKept); | ||
} | ||
export let keep1 = "should be kept"; | ||
export let keep2 = "should be kept"; | ||
let keep3 = "should be kept"; | ||
let asKeep = "should be kept"; | ||
export { keep3, asKeep as keep4 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters