Skip to content

Commit

Permalink
feat(transforms): turbopack ecma plugin for next.js transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Jan 11, 2024
1 parent 3c065a1 commit a7d4da8
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
pub(crate) mod emotion;
pub(crate) mod modularize_imports;
pub(crate) mod next_amp_attributes;
pub(crate) mod next_cjs_optimizer;
pub(crate) mod next_disallow_re_export_all_in_page;
pub(crate) mod next_dynamic;
pub(crate) mod next_font;
pub(crate) mod next_optimize_server_react;
pub(crate) mod next_page_config;
pub(crate) mod next_pure;
pub(crate) mod next_react_server_components;
pub(crate) mod next_shake_exports;
pub(crate) mod next_strip_page_exports;
pub(crate) mod relay;
pub(crate) mod server_actions;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use anyhow::Result;
use async_trait::async_trait;
use next_custom_transforms::transforms::amp_attributes::amp_attributes;
use turbo_tasks::Vc;
use turbopack_binding::{
swc::core::{
common::util::take::Take,
ecma::{ast::*, visit::FoldWith},
},
turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
},
};

use super::module_rule_match_js_no_url;

pub fn get_next_amp_attr_rule(enable_mdx_rs: bool) -> ModuleRule {
let transformer =
EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextAmpAttributes {}) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}

#[derive(Debug)]
struct NextAmpAttributes {}

#[async_trait]
impl CustomTransformer for NextAmpAttributes {
async fn transform(&self, program: &mut Program, _ctx: &TransformContext<'_>) -> Result<()> {
let p = std::mem::replace(program, Program::Module(Module::dummy()));
*program = p.fold_with(&mut amp_attributes());
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use anyhow::Result;
use async_trait::async_trait;
use next_custom_transforms::transforms::cjs_optimizer::{cjs_optimizer, Config};
use turbo_tasks::Vc;
use turbopack_binding::{
swc::core::{
common::SyntaxContext,
ecma::{ast::*, visit::VisitMutWith},
},
turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
},
};

use super::module_rule_match_js_no_url;

pub fn get_next_cjs_optimizer_rule(enable_mdx_rs: bool, config: Config) -> ModuleRule {
let transformer =
EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextCjsOptimizer { config }) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}

#[derive(Debug)]
struct NextCjsOptimizer {
config: Config,
}

#[async_trait]
impl CustomTransformer for NextCjsOptimizer {
async fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Result<()> {
let mut visitor = cjs_optimizer(
self.config.clone(),
SyntaxContext::empty().apply_mark(ctx.unresolved_mark),
);

program.visit_mut_with(&mut visitor);
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use anyhow::Result;
use async_trait::async_trait;
use next_custom_transforms::transforms::disallow_re_export_all_in_page::disallow_re_export_all_in_page;
use turbo_tasks::Vc;
use turbopack_binding::{
swc::core::{
common::util::take::Take,
ecma::{ast::*, visit::FoldWith},
},
turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
},
};

use super::module_rule_match_js_no_url;

pub fn get_next_disallow_export_all_in_page_rule(
enable_mdx_rs: bool,
is_page_file: bool,
) -> ModuleRule {
let transformer =
EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextDisallowReExportAllInPage {
is_page_file,
}) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}

#[derive(Debug)]
struct NextDisallowReExportAllInPage {
is_page_file: bool,
}

#[async_trait]
impl CustomTransformer for NextDisallowReExportAllInPage {
async fn transform(&self, program: &mut Program, _ctx: &TransformContext<'_>) -> Result<()> {
let p = std::mem::replace(program, Program::Module(Module::dummy()));
*program = p.fold_with(&mut disallow_re_export_all_in_page(self.is_page_file));
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use anyhow::Result;
use async_trait::async_trait;
use next_custom_transforms::transforms::optimize_server_react::{optimize_server_react, Config};
use turbo_tasks::Vc;
use turbopack_binding::{
swc::core::{
common::util::take::Take,
ecma::{ast::*, visit::FoldWith},
},
turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
},
};

use super::module_rule_match_js_no_url;

pub fn get_next_optimize_server_react_rule(
enable_mdx_rs: bool,
optimize_use_state: bool,
) -> ModuleRule {
let transformer =
EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextOptimizeServerReact {
optimize_use_state,
}) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}

#[derive(Debug)]
struct NextOptimizeServerReact {
optimize_use_state: bool,
}

#[async_trait]
impl CustomTransformer for NextOptimizeServerReact {
async fn transform(&self, program: &mut Program, _ctx: &TransformContext<'_>) -> Result<()> {
let p = std::mem::replace(program, Program::Module(Module::dummy()));

*program = p.fold_with(&mut optimize_server_react(Config {
optimize_use_state: self.optimize_use_state,
}));
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use anyhow::Result;
use async_trait::async_trait;
use next_custom_transforms::transforms::page_config::page_config;
use turbo_tasks::Vc;
use turbopack_binding::{
swc::core::{
common::util::take::Take,
ecma::{ast::*, visit::FoldWith},
},
turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
},
};

use super::module_rule_match_js_no_url;

pub fn get_next_page_config_rule(enable_mdx_rs: bool, is_page_file: bool) -> ModuleRule {
let transformer = EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextPageConfig {
// [TODO]: update once turbopack build works
is_development: true,
is_page_file,
}) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}

#[derive(Debug)]
struct NextPageConfig {
is_development: bool,
is_page_file: bool,
}

#[async_trait]
impl CustomTransformer for NextPageConfig {
async fn transform(&self, program: &mut Program, _ctx: &TransformContext<'_>) -> Result<()> {
let p = std::mem::replace(program, Program::Module(Module::dummy()));

*program = p.fold_with(&mut page_config(self.is_development, self.is_page_file));
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use anyhow::Result;
use async_trait::async_trait;
use next_custom_transforms::transforms::pure::pure_magic;
use turbo_tasks::Vc;
use turbopack_binding::{
swc::core::ecma::{ast::*, visit::VisitMutWith},
turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
},
};

use super::module_rule_match_js_no_url;

pub fn get_next_pure_rule(enable_mdx_rs: bool) -> ModuleRule {
let transformer = EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextPure {}) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}

#[derive(Debug)]
struct NextPure {}

#[async_trait]
impl CustomTransformer for NextPure {
async fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Result<()> {
program.visit_mut_with(&mut pure_magic(ctx.comments.clone()));
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use anyhow::Result;
use async_trait::async_trait;
use next_custom_transforms::transforms::shake_exports::{shake_exports, Config};
use turbo_tasks::Vc;
use turbopack_binding::{
swc::core::{
common::util::take::Take,
ecma::{ast::*, visit::FoldWith},
},
turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
},
};

use super::module_rule_match_js_no_url;

pub fn get_next_shake_exports_rule(enable_mdx_rs: bool, ignore: Vec<String>) -> ModuleRule {
let transformer =
EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextShakeExports { ignore }) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}

#[derive(Debug)]
struct NextShakeExports {
ignore: Vec<String>,
}

#[async_trait]
impl CustomTransformer for NextShakeExports {
async fn transform(&self, program: &mut Program, _ctx: &TransformContext<'_>) -> Result<()> {
let p = std::mem::replace(program, Program::Module(Module::dummy()));

*program = p.fold_with(&mut shake_exports(Config {
ignore: self.ignore.iter().map(|s| s.clone().into()).collect(),
}));
Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc};
use either::Either;
use fxhash::FxHashSet;
use serde::Deserialize;
use swc_core::ecma::visit::as_folder;
use turbopack_binding::swc::{
core::{
common::{
Expand Down Expand Up @@ -275,11 +276,11 @@ where
},
match &opts.cjs_require_optimizer {
Some(config) => {
Either::Left(crate::transforms::cjs_optimizer::cjs_optimizer(config.clone(), SyntaxContext::empty().apply_mark(unresolved_mark)))
Either::Left(as_folder(crate::transforms::cjs_optimizer::cjs_optimizer(config.clone(), SyntaxContext::empty().apply_mark(unresolved_mark))))
},
None => Either::Right(noop()),
},
crate::transforms::pure::pure_magic(comments),
as_folder(crate::transforms::pure::pure_magic(comments)),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@ use turbopack_binding::swc::core::{
},
atoms::{Atom, JsWord},
utils::{prepend_stmts, private_ident, ExprFactory, IdentRenamer},
visit::{
as_folder, noop_visit_mut_type, noop_visit_type, Fold, Visit, VisitMut, VisitMutWith,
VisitWith,
},
visit::{noop_visit_mut_type, noop_visit_type, Visit, VisitMut, VisitMutWith, VisitWith},
},
};

pub fn cjs_optimizer(config: Config, unresolved_ctxt: SyntaxContext) -> impl Fold + VisitMut {
as_folder(CjsOptimizer {
pub fn cjs_optimizer(config: Config, unresolved_ctxt: SyntaxContext) -> CjsOptimizer {
CjsOptimizer {
data: State::default(),
packages: config.packages,
unresolved_ctxt,
})
}
}

#[derive(Clone, Debug, Deserialize)]
Expand All @@ -35,7 +32,7 @@ pub struct PackageConfig {
pub transforms: FxHashMap<JsWord, JsWord>,
}

struct CjsOptimizer {
pub struct CjsOptimizer {
data: State,
packages: FxHashMap<String, PackageConfig>,
unresolved_ctxt: SyntaxContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ pub mod disallow_re_export_all_in_page;
pub mod dynamic;
pub mod fonts;
pub mod import_analyzer;
pub mod named_import_transform;
pub mod next_ssg;
pub mod optimize_barrel;
pub mod optimize_server_react;
pub mod page_config;
pub mod pure;
pub mod react_server_components;
pub mod server_actions;
pub mod shake_exports;
pub mod strip_page_exports;

//[TODO] PACK-1564: need to decide reuse vs. turbopack specific
pub mod named_import_transform;
pub mod optimize_barrel;
Loading

0 comments on commit a7d4da8

Please sign in to comment.