Implement custom Turbopack Next transformers (#47137)
Builds on https://github.com/vercel/turbo/pull/4202 to implement custom Next.js Transformers in Turbopack. This is the final piece to moving the `next-*` crates to Next. While we've _technically_ moved everything, Turbopack didn't support running custom transformers. So we're actually stuck on the last version we cut before deleting the next crates, running the transformers that exist in the turbopack repo. With the new support, we're almost back to the tip of main branch (there's still some snafu with `swc_core` upgrading that I'm working on). Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
This commit is contained in:
parent
4824d96fab
commit
02125cf3b1
11 changed files with 579 additions and 471 deletions
638
packages/next-swc/Cargo.lock
generated
638
packages/next-swc/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -8,9 +8,9 @@ members = [
|
|||
"crates/next-core",
|
||||
"crates/next-dev",
|
||||
"crates/next-dev-tests",
|
||||
# "crates/next-font",
|
||||
# "crates/next-transform-dynamic",
|
||||
# "crates/next-transform-strip-page-exports",
|
||||
"crates/next-font",
|
||||
"crates/next-transform-dynamic",
|
||||
"crates/next-transform-strip-page-exports",
|
||||
]
|
||||
|
||||
[profile.dev.package.swc_css_prefixer]
|
||||
|
@ -26,55 +26,55 @@ lto = true
|
|||
[workspace.dependencies]
|
||||
# Workspace crates
|
||||
next-binding = { path = "crates/next-binding" }
|
||||
next-core = { path = "crates/next-core" }
|
||||
next-core = { path = "crates/next-core", default-features = false }
|
||||
next-dev = { path = "crates/next-dev" }
|
||||
next-dev-tests = { path = "crates/next-dev-tests" }
|
||||
# next-font = { path = "crates/next-font" }
|
||||
# next-transform-dynamic = { path = "crates/next-transform-dynamic" }
|
||||
# next-transform-strip-page-exports = { path = "crates/next-transform-strip-page-exports" }
|
||||
next-font = { path = "crates/next-font" }
|
||||
next-transform-dynamic = { path = "crates/next-transform-dynamic" }
|
||||
next-transform-strip-page-exports = { path = "crates/next-transform-strip-page-exports" }
|
||||
|
||||
# SWC crates
|
||||
# Keep consistent with preset_env_base through swc_core
|
||||
browserslist-rs = { version = "0.12.2" }
|
||||
mdxjs = { version = "0.1.6" }
|
||||
modularize_imports = { version = "0.26.4" }
|
||||
styled_components = { version = "0.53.4" }
|
||||
styled_jsx = { version = "0.30.4" }
|
||||
swc_core = { version = "0.59.26" }
|
||||
swc_emotion = { version = "0.29.4" }
|
||||
mdxjs = { version = "0.1.8" }
|
||||
modularize_imports = { version = "0.26.10" }
|
||||
styled_components = { version = "0.53.10" }
|
||||
styled_jsx = { version = "0.30.10" }
|
||||
swc_core = { version = "0.69.6" }
|
||||
swc_emotion = { version = "0.29.10" }
|
||||
testing = { version = "0.31.31" }
|
||||
|
||||
# Turbo crates
|
||||
auto-hash-map = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
node-file-trace = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
swc-ast-explorer = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-malloc = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94", default-features = false }
|
||||
turbo-tasks = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-build = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-env = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-fetch = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-hash = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-macros = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-macros-shared = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-memory = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-tasks-testing = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbo-updater = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-cli-utils = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-core = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-create-test-app = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-css = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-dev-server = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-ecmascript = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-env = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-json = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-mdx = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-node = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-static = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-swc-utils = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-test-utils = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
turbopack-tests = { git = "https://github.com/vercel/turbo.git", rev = "8a8038f94" }
|
||||
auto-hash-map = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
node-file-trace = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
swc-ast-explorer = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-malloc = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2", default-features = false }
|
||||
turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-build = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-env = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-fetch = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2", default-features = false }
|
||||
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-hash = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-macros = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-macros-shared = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-memory = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-tasks-testing = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbo-updater = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-cli-utils = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-core = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-create-test-app = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-css = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-dev-server = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-ecmascript = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-env = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-json = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-mdx = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-node = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-static = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-swc-utils = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-test-utils = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
turbopack-tests = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230315.2" }
|
||||
|
||||
# General Deps
|
||||
|
||||
|
|
|
@ -179,7 +179,8 @@ impl Fold for NextDynamicPatcher {
|
|||
key: PropName::Ident(Ident::new("webpack".into(), DUMMY_SP)),
|
||||
value: Box::new(Expr::Arrow(ArrowExpr {
|
||||
params: vec![],
|
||||
body: BlockStmtOrExpr::Expr(Box::new(Expr::Array(ArrayLit {
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::Array(
|
||||
ArrayLit {
|
||||
elems: vec![Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(Box::new(Expr::Member(
|
||||
|
@ -216,7 +217,8 @@ impl Fold for NextDynamicPatcher {
|
|||
spread: None,
|
||||
})],
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
},
|
||||
)))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
span: DUMMY_SP,
|
||||
|
|
|
@ -191,7 +191,7 @@ impl<C: Comments> ServerActions<C> {
|
|||
);
|
||||
|
||||
if let Some(a) = arrow {
|
||||
if let BlockStmtOrExpr::BlockStmt(block) = &mut a.body {
|
||||
if let BlockStmtOrExpr::BlockStmt(block) = &mut *a.body {
|
||||
block.visit_mut_with(&mut ClosureReplacer {
|
||||
closure_arg: &closure_arg,
|
||||
used_ids: &ids_from_closure,
|
||||
|
@ -201,7 +201,7 @@ impl<C: Comments> ServerActions<C> {
|
|||
let new_arrow = ArrowExpr {
|
||||
span: DUMMY_SP,
|
||||
params: a.params.clone(),
|
||||
body: BlockStmtOrExpr::Expr(Box::new(Expr::Call(call))),
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::Call(call)))),
|
||||
is_async: a.is_async,
|
||||
is_generator: a.is_generator,
|
||||
type_params: Default::default(),
|
||||
|
@ -402,7 +402,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
|
|||
// Arrow expressions need to be visited in prepass to determine if it's
|
||||
// an action function or not.
|
||||
let is_action_fn = self.get_action_info(
|
||||
if let BlockStmtOrExpr::BlockStmt(block) = &mut a.body {
|
||||
if let BlockStmtOrExpr::BlockStmt(block) = &mut *a.body {
|
||||
Some(block)
|
||||
} else {
|
||||
None
|
||||
|
@ -503,7 +503,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
|
|||
if !self.in_action_file {
|
||||
if let Expr::Arrow(a) = n {
|
||||
let is_action_fn = self.get_action_info(
|
||||
if let BlockStmtOrExpr::BlockStmt(block) = &mut a.body {
|
||||
if let BlockStmtOrExpr::BlockStmt(block) = &mut *a.body {
|
||||
Some(block)
|
||||
} else {
|
||||
None
|
||||
|
@ -1194,7 +1194,7 @@ impl TryFrom<&'_ OptChainExpr> for Name {
|
|||
type Error = ();
|
||||
|
||||
fn try_from(value: &OptChainExpr) -> Result<Self, Self::Error> {
|
||||
match &value.base {
|
||||
match &*value.base {
|
||||
OptChainBase::Member(value) => match &value.prop {
|
||||
MemberProp::Ident(prop) => {
|
||||
let mut obj: Name = value.obj.as_ref().try_into()?;
|
||||
|
@ -1223,11 +1223,11 @@ impl From<Name> for Expr {
|
|||
expr = Expr::OptChain(OptChainExpr {
|
||||
span: DUMMY_SP,
|
||||
question_dot_token: DUMMY_SP,
|
||||
base: OptChainBase::Member(MemberExpr {
|
||||
base: Box::new(OptChainBase::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: expr.into(),
|
||||
prop: MemberProp::Ident(Ident::new(prop, DUMMY_SP)),
|
||||
}),
|
||||
})),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ turbopack-dev-server = { workspace = true }
|
|||
turbopack-ecmascript = { workspace = true }
|
||||
turbopack-env = { workspace = true }
|
||||
turbopack-node = { workspace = true }
|
||||
next-transform-strip-page-exports = { workspace = true }
|
||||
next-font = { workspace = true }
|
||||
next-transform-dynamic = { workspace = true }
|
||||
|
||||
swc_core = { workspace = true, features = ["ecma_ast", "common"] }
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(async_closure)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
mod app_render;
|
||||
mod app_source;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use next_transform_strip_page_exports::ExportFilter;
|
||||
use turbopack::module_options::ModuleRule;
|
||||
use turbopack_ecmascript::NextJsPageExportFilter;
|
||||
|
||||
use crate::{
|
||||
next_client::context::ClientContextType,
|
||||
|
@ -22,8 +22,7 @@ pub async fn get_next_client_transforms_rules(
|
|||
let pages_dir = match context_ty {
|
||||
ClientContextType::Pages { pages_dir } => {
|
||||
rules.push(
|
||||
get_next_pages_transforms_rule(pages_dir, NextJsPageExportFilter::StripDataExports)
|
||||
.await?,
|
||||
get_next_pages_transforms_rule(pages_dir, ExportFilter::StripDataExports).await?,
|
||||
);
|
||||
Some(pages_dir)
|
||||
}
|
||||
|
@ -32,9 +31,7 @@ pub async fn get_next_client_transforms_rules(
|
|||
}
|
||||
};
|
||||
|
||||
rules.push(get_next_dynamic_transform_rule(
|
||||
true, false, false, pages_dir,
|
||||
));
|
||||
rules.push(get_next_dynamic_transform_rule(true, false, false, pages_dir).await?);
|
||||
|
||||
Ok(rules)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use next_transform_strip_page_exports::ExportFilter;
|
||||
use turbopack::module_options::ModuleRule;
|
||||
use turbopack_ecmascript::NextJsPageExportFilter;
|
||||
|
||||
use crate::{
|
||||
next_server::context::ServerContextType,
|
||||
|
@ -21,11 +21,7 @@ pub async fn get_next_server_transforms_rules(
|
|||
ServerContextType::Pages { pages_dir } => (false, Some(pages_dir)),
|
||||
ServerContextType::PagesData { pages_dir } => {
|
||||
rules.push(
|
||||
get_next_pages_transforms_rule(
|
||||
pages_dir,
|
||||
NextJsPageExportFilter::StripDefaultExport,
|
||||
)
|
||||
.await?,
|
||||
get_next_pages_transforms_rule(pages_dir, ExportFilter::StripDefaultExport).await?,
|
||||
);
|
||||
(false, Some(pages_dir))
|
||||
}
|
||||
|
@ -35,12 +31,7 @@ pub async fn get_next_server_transforms_rules(
|
|||
ServerContextType::Middleware { .. } => (false, None),
|
||||
};
|
||||
|
||||
rules.push(get_next_dynamic_transform_rule(
|
||||
true,
|
||||
true,
|
||||
is_server_components,
|
||||
pages_dir,
|
||||
));
|
||||
rules.push(get_next_dynamic_transform_rule(true, true, is_server_components, pages_dir).await?);
|
||||
|
||||
Ok(rules)
|
||||
}
|
||||
|
|
|
@ -1,19 +1,34 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use turbo_tasks::primitives::StringsVc;
|
||||
use next_transform_dynamic::{next_dynamic, NextDynamicMode};
|
||||
use next_transform_strip_page_exports::{next_transform_strip_page_exports, ExportFilter};
|
||||
use swc_core::{
|
||||
common::{util::take::Take, FileName},
|
||||
ecma::{
|
||||
ast::{Module, ModuleItem, Program},
|
||||
atoms::JsWord,
|
||||
visit::{FoldWith, VisitMutWith},
|
||||
},
|
||||
};
|
||||
use turbo_tasks_fs::FileSystemPathVc;
|
||||
use turbopack::module_options::{ModuleRule, ModuleRuleCondition, ModuleRuleEffect};
|
||||
use turbopack_core::reference_type::{ReferenceType, UrlReferenceSubType};
|
||||
use turbopack_ecmascript::{
|
||||
EcmascriptInputTransform, EcmascriptInputTransformsVc, NextJsPageExportFilter,
|
||||
CustomTransformVc, CustomTransformer, EcmascriptInputTransform, EcmascriptInputTransformsVc,
|
||||
TransformContext,
|
||||
};
|
||||
|
||||
/// Returns a rule which applies the Next.js page export stripping transform.
|
||||
pub async fn get_next_pages_transforms_rule(
|
||||
pages_dir: FileSystemPathVc,
|
||||
export_filter: NextJsPageExportFilter,
|
||||
export_filter: ExportFilter,
|
||||
) -> Result<ModuleRule> {
|
||||
// Apply the Next SSG transform to all pages.
|
||||
let strip_transform = EcmascriptInputTransform::NextJsStripPageExports(export_filter);
|
||||
let strip_transform =
|
||||
EcmascriptInputTransform::Custom(CustomTransformVc::cell(box NextJsStripPageExports {
|
||||
export_filter,
|
||||
}));
|
||||
Ok(ModuleRule::new(
|
||||
ModuleRuleCondition::all(vec![
|
||||
ModuleRuleCondition::all(vec![
|
||||
|
@ -37,51 +52,111 @@ pub async fn get_next_pages_transforms_rule(
|
|||
))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NextJsStripPageExports {
|
||||
export_filter: ExportFilter,
|
||||
}
|
||||
|
||||
impl CustomTransformer for NextJsStripPageExports {
|
||||
fn transform(&self, program: &mut Program, _ctx: &TransformContext<'_>) -> Option<Program> {
|
||||
// TODO(alexkirsz) Connect the eliminated_packages to telemetry.
|
||||
let eliminated_packages = Default::default();
|
||||
|
||||
let module_program = unwrap_module_program(program);
|
||||
Some(
|
||||
module_program.fold_with(&mut next_transform_strip_page_exports(
|
||||
self.export_filter,
|
||||
eliminated_packages,
|
||||
)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a rule which applies the Next.js dynamic transform.
|
||||
pub fn get_next_dynamic_transform_rule(
|
||||
pub async fn get_next_dynamic_transform_rule(
|
||||
is_development: bool,
|
||||
is_server: bool,
|
||||
is_server_components: bool,
|
||||
pages_dir: Option<FileSystemPathVc>,
|
||||
) -> ModuleRule {
|
||||
let dynamic_transform = EcmascriptInputTransform::NextJsDynamic {
|
||||
) -> Result<ModuleRule> {
|
||||
let dynamic_transform =
|
||||
EcmascriptInputTransform::Custom(CustomTransformVc::cell(box NextJsDynamic {
|
||||
is_development,
|
||||
is_server,
|
||||
is_server_components,
|
||||
pages_dir,
|
||||
};
|
||||
ModuleRule::new(
|
||||
pages_dir: match pages_dir {
|
||||
None => None,
|
||||
Some(path) => Some(path.await?.path.clone().into()),
|
||||
},
|
||||
}));
|
||||
Ok(ModuleRule::new(
|
||||
module_rule_match_js_no_url(),
|
||||
vec![ModuleRuleEffect::AddEcmascriptTransforms(
|
||||
EcmascriptInputTransformsVc::cell(vec![dynamic_transform]),
|
||||
)],
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NextJsDynamic {
|
||||
is_development: bool,
|
||||
is_server: bool,
|
||||
is_server_components: bool,
|
||||
pages_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl CustomTransformer for NextJsDynamic {
|
||||
fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Option<Program> {
|
||||
let module_program = unwrap_module_program(program);
|
||||
Some(module_program.fold_with(&mut next_dynamic(
|
||||
self.is_development,
|
||||
self.is_server,
|
||||
self.is_server_components,
|
||||
NextDynamicMode::Turbo,
|
||||
FileName::Real(ctx.file_path_str.into()),
|
||||
self.pages_dir.clone(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a rule which applies the Next.js font transform.
|
||||
pub fn get_next_font_transform_rule() -> ModuleRule {
|
||||
#[allow(unused_mut)] // This is mutated when next-font-local is enabled
|
||||
let mut font_loaders = vec![
|
||||
"next/font/google".to_owned(),
|
||||
"@next/font/google".to_owned(),
|
||||
];
|
||||
let mut font_loaders = vec!["next/font/google".into(), "@next/font/google".into()];
|
||||
#[cfg(feature = "next-font-local")]
|
||||
{
|
||||
font_loaders.push("next/font/local".to_owned());
|
||||
font_loaders.push("@next/font/local".to_owned());
|
||||
font_loaders.push("next/font/local".into());
|
||||
font_loaders.push("@next/font/local".into());
|
||||
}
|
||||
|
||||
let transformer =
|
||||
EcmascriptInputTransform::Custom(CustomTransformVc::cell(box NextJsFont { font_loaders }));
|
||||
ModuleRule::new(
|
||||
// TODO: Only match in pages (not pages/api), app/, etc.
|
||||
module_rule_match_js_no_url(),
|
||||
vec![ModuleRuleEffect::AddEcmascriptTransforms(
|
||||
EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::NextJsFont(
|
||||
StringsVc::cell(font_loaders),
|
||||
)]),
|
||||
EcmascriptInputTransformsVc::cell(vec![transformer]),
|
||||
)],
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NextJsFont {
|
||||
font_loaders: Vec<JsWord>,
|
||||
}
|
||||
|
||||
impl CustomTransformer for NextJsFont {
|
||||
fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Option<Program> {
|
||||
let mut next_font = next_font::next_font_loaders(next_font::Config {
|
||||
font_loaders: self.font_loaders.clone(),
|
||||
relative_file_path_from_root: ctx.file_name_str.into(),
|
||||
});
|
||||
|
||||
program.visit_mut_with(&mut next_font);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn module_rule_match_js_no_url() -> ModuleRuleCondition {
|
||||
ModuleRuleCondition::all(vec![
|
||||
ModuleRuleCondition::not(ModuleRuleCondition::ReferenceType(ReferenceType::Url(
|
||||
|
@ -95,3 +170,18 @@ fn module_rule_match_js_no_url() -> ModuleRuleCondition {
|
|||
]),
|
||||
])
|
||||
}
|
||||
|
||||
fn unwrap_module_program(program: &mut Program) -> Program {
|
||||
match program {
|
||||
Program::Module(module) => Program::Module(module.take()),
|
||||
Program::Script(s) => Program::Module(Module {
|
||||
span: s.span,
|
||||
body: s
|
||||
.body
|
||||
.iter()
|
||||
.map(|stmt| ModuleItem::Stmt(stmt.clone()))
|
||||
.collect(),
|
||||
shebang: s.shebang.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,11 @@ async fn middleware_files(page_extensions: StringsVc) -> Result<StringsVc> {
|
|||
let extensions = page_extensions.await?;
|
||||
let files = ["middleware.", "src/middleware."]
|
||||
.into_iter()
|
||||
.flat_map(|f| extensions.iter().map(move |ext| String::from(f) + ext))
|
||||
.flat_map(|f| {
|
||||
extensions
|
||||
.iter()
|
||||
.map(move |ext| String::from(f) + ext.as_str())
|
||||
})
|
||||
.collect();
|
||||
Ok(StringsVc::cell(files))
|
||||
}
|
||||
|
|
|
@ -47,9 +47,7 @@ pub enum NextDynamicMode {
|
|||
/// 2. The relative imported module id.
|
||||
///
|
||||
/// This key is of the form:
|
||||
/// ```
|
||||
/// {currentModulePath} -> {relativeImportedModulePath}
|
||||
/// ```
|
||||
///
|
||||
/// It corresponds to an entry in the React Loadable Manifest generated by
|
||||
/// the React Loadable Webpack plugin.
|
||||
|
@ -262,7 +260,8 @@ impl Fold for NextDynamicPatcher {
|
|||
key: PropName::Ident(Ident::new("webpack".into(), DUMMY_SP)),
|
||||
value: Box::new(Expr::Arrow(ArrowExpr {
|
||||
params: vec![],
|
||||
body: BlockStmtOrExpr::Expr(Box::new(Expr::Array(ArrayLit {
|
||||
body: Box::new(BlockStmtOrExpr::Expr(Box::new(Expr::Array(
|
||||
ArrayLit {
|
||||
elems: vec![Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
callee: Callee::Expr(Box::new(Expr::Member(
|
||||
|
@ -295,7 +294,8 @@ impl Fold for NextDynamicPatcher {
|
|||
spread: None,
|
||||
})],
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
},
|
||||
)))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
span: DUMMY_SP,
|
||||
|
|
Loading…
Reference in a new issue