next/dynamic
: Accept pagesDir
(#29055)
* Add pages_dir * Add `pages_dir` to `next/dynamic` pass * Dep * Fix next/dynamic psss * Fix * Update test refs * Add a test
This commit is contained in:
parent
c38e702347
commit
fd2af1422d
9 changed files with 311 additions and 250 deletions
1
packages/next/build/swc/Cargo.lock
generated
1
packages/next/build/swc/Cargo.lock
generated
|
@ -706,6 +706,7 @@ dependencies = [
|
|||
"napi-build",
|
||||
"napi-derive",
|
||||
"path-clean",
|
||||
"pathdiff",
|
||||
"regex",
|
||||
"retain_mut",
|
||||
"serde",
|
||||
|
|
|
@ -24,6 +24,7 @@ swc_ecma_preset_env = "0.42"
|
|||
fxhash = "0.2.1"
|
||||
retain_mut = "0.1.3"
|
||||
log = "0.4.14"
|
||||
pathdiff = "0.2.0"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -1,214 +1,261 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use pathdiff::diff_paths;
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::{FileName, DUMMY_SP};
|
||||
use swc_ecmascript::ast::{
|
||||
ArrayLit, ArrowExpr, BinExpr, BinaryOp, BlockStmtOrExpr, CallExpr, Expr, ExprOrSpread,
|
||||
ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, ObjectLit, Prop,
|
||||
PropName, PropOrSpread, Str, StrKind,
|
||||
ArrayLit, ArrowExpr, BinExpr, BinaryOp, BlockStmtOrExpr, CallExpr, Expr, ExprOrSpread,
|
||||
ExprOrSuper, Ident, ImportDecl, ImportSpecifier, KeyValueProp, Lit, MemberExpr, ObjectLit,
|
||||
Prop, PropName, PropOrSpread, Str, StrKind,
|
||||
};
|
||||
use swc_ecmascript::utils::{
|
||||
ident::{Id, IdentLike},
|
||||
HANDLER,
|
||||
ident::{Id, IdentLike},
|
||||
HANDLER,
|
||||
};
|
||||
use swc_ecmascript::visit::{Fold, FoldWith};
|
||||
|
||||
pub fn next_dynamic(filename: FileName) -> impl Fold {
|
||||
NextDynamicPatcher {
|
||||
filename,
|
||||
dynamic_bindings: vec![],
|
||||
}
|
||||
pub fn next_dynamic(filename: FileName, pages_dir: Option<PathBuf>) -> impl Fold {
|
||||
NextDynamicPatcher {
|
||||
pages_dir,
|
||||
filename,
|
||||
dynamic_bindings: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NextDynamicPatcher {
|
||||
filename: FileName,
|
||||
dynamic_bindings: Vec<Id>,
|
||||
pages_dir: Option<PathBuf>,
|
||||
filename: FileName,
|
||||
dynamic_bindings: Vec<Id>,
|
||||
}
|
||||
|
||||
impl Fold for NextDynamicPatcher {
|
||||
fn fold_import_decl(&mut self, decl: ImportDecl) -> ImportDecl {
|
||||
let ImportDecl {
|
||||
ref src,
|
||||
ref specifiers,
|
||||
..
|
||||
} = decl;
|
||||
if &src.value == "next/dynamic" {
|
||||
for specifier in specifiers {
|
||||
if let ImportSpecifier::Default(default_specifier) = specifier {
|
||||
self.dynamic_bindings.push(default_specifier.local.to_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decl
|
||||
}
|
||||
|
||||
fn fold_call_expr(&mut self, expr: CallExpr) -> CallExpr {
|
||||
let mut expr = expr.fold_children_with(self);
|
||||
if let ExprOrSuper::Expr(i) = &expr.callee {
|
||||
if let Expr::Ident(identifier) = &**i {
|
||||
if self.dynamic_bindings.contains(&identifier.to_id()) {
|
||||
if expr.args.len() == 0 {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
identifier.span,
|
||||
"next/dynamic requires at least one argument",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
} else if expr.args.len() > 2 {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(identifier.span, "next/dynamic only accepts 2 arguments")
|
||||
.emit()
|
||||
});
|
||||
}
|
||||
|
||||
let mut import_specifier = None;
|
||||
if let Expr::Arrow(ArrowExpr {
|
||||
body: BlockStmtOrExpr::Expr(e),
|
||||
fn fold_import_decl(&mut self, decl: ImportDecl) -> ImportDecl {
|
||||
let ImportDecl {
|
||||
ref src,
|
||||
ref specifiers,
|
||||
..
|
||||
}) = &*expr.args[0].expr
|
||||
{
|
||||
if let Expr::Call(CallExpr {
|
||||
args: a, callee, ..
|
||||
}) = &**e
|
||||
{
|
||||
if let ExprOrSuper::Expr(e) = callee {
|
||||
if let Expr::Ident(Ident { sym, .. }) = &**e {
|
||||
if sym == "import" {
|
||||
if a.len() == 0 {
|
||||
// Do nothing, import_specifier will remain None
|
||||
// triggering error below
|
||||
} else if let Expr::Lit(Lit::Str(Str { value, .. })) = &*a[0].expr {
|
||||
import_specifier = Some(value.clone());
|
||||
}
|
||||
}
|
||||
} = decl;
|
||||
if &src.value == "next/dynamic" {
|
||||
for specifier in specifiers {
|
||||
if let ImportSpecifier::Default(default_specifier) = specifier {
|
||||
self.dynamic_bindings.push(default_specifier.local.to_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let None = import_specifier {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
identifier.span,
|
||||
"First argument for next/dynamic must be an arrow function returning a valid \
|
||||
dynamic import call e.g. `dynamic(() => import('../some-component'))`",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
}
|
||||
|
||||
// loadableGenerated: {
|
||||
// webpack: () => [require.resolveWeak('../components/hello')],
|
||||
// modules:
|
||||
// ["/project/src/file-being-transformed.js -> " + '../components/hello'] }
|
||||
let generated = Box::new(Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
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 {
|
||||
elems: vec![Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
callee: ExprOrSuper::Expr(Box::new(Expr::Member(MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(Expr::Ident(Ident {
|
||||
sym: js_word!("require"),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}))),
|
||||
prop: Box::new(Expr::Ident(Ident {
|
||||
sym: "resolveWeak".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
})),
|
||||
computed: false,
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
args: vec![ExprOrSpread {
|
||||
expr: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: self.filename.to_string().into(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Synthesized {},
|
||||
has_escape: false,
|
||||
}))),
|
||||
spread: None,
|
||||
}],
|
||||
span: DUMMY_SP,
|
||||
type_args: None,
|
||||
})),
|
||||
spread: None,
|
||||
})],
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
span: DUMMY_SP,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
})),
|
||||
}))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new("modules".into(), DUMMY_SP)),
|
||||
value: Box::new(Expr::Array(ArrayLit {
|
||||
elems: vec![Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
op: BinaryOp::Add,
|
||||
left: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: format!("{} -> ", self.filename).into(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Synthesized {},
|
||||
has_escape: false,
|
||||
}))),
|
||||
right: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: import_specifier.unwrap(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Normal {
|
||||
contains_quote: false,
|
||||
},
|
||||
has_escape: false,
|
||||
}))),
|
||||
})),
|
||||
spread: None,
|
||||
})],
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
}))),
|
||||
],
|
||||
}));
|
||||
|
||||
let mut props = vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new("loadableGenerated".into(), DUMMY_SP)),
|
||||
value: generated,
|
||||
})))];
|
||||
|
||||
if expr.args.len() == 2 {
|
||||
if let Expr::Object(ObjectLit {
|
||||
props: options_props,
|
||||
..
|
||||
}) = &*expr.args[1].expr
|
||||
{
|
||||
props.extend(options_props.iter().cloned());
|
||||
}
|
||||
}
|
||||
|
||||
let second_arg = ExprOrSpread {
|
||||
spread: None,
|
||||
expr: Box::new(Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props,
|
||||
})),
|
||||
};
|
||||
|
||||
expr.args.push(second_arg);
|
||||
}
|
||||
}
|
||||
|
||||
decl
|
||||
}
|
||||
|
||||
fn fold_call_expr(&mut self, expr: CallExpr) -> CallExpr {
|
||||
let mut expr = expr.fold_children_with(self);
|
||||
if let ExprOrSuper::Expr(i) = &expr.callee {
|
||||
if let Expr::Ident(identifier) = &**i {
|
||||
if self.dynamic_bindings.contains(&identifier.to_id()) {
|
||||
if expr.args.len() == 0 {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
identifier.span,
|
||||
"next/dynamic requires at least one argument",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
} else if expr.args.len() > 2 {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
identifier.span,
|
||||
"next/dynamic only accepts 2 arguments",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
}
|
||||
|
||||
let mut import_specifier = None;
|
||||
if let Expr::Arrow(ArrowExpr {
|
||||
body: BlockStmtOrExpr::Expr(e),
|
||||
..
|
||||
}) = &*expr.args[0].expr
|
||||
{
|
||||
if let Expr::Call(CallExpr {
|
||||
args: a, callee, ..
|
||||
}) = &**e
|
||||
{
|
||||
if let ExprOrSuper::Expr(e) = callee {
|
||||
if let Expr::Ident(Ident { sym, .. }) = &**e {
|
||||
if sym == "import" {
|
||||
if a.len() == 0 {
|
||||
// Do nothing, import_specifier will
|
||||
// remain None
|
||||
// triggering error below
|
||||
} else if let Expr::Lit(Lit::Str(Str { value, .. })) =
|
||||
&*a[0].expr
|
||||
{
|
||||
import_specifier = Some(value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let None = import_specifier {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
identifier.span,
|
||||
"First argument for next/dynamic must be an arrow function \
|
||||
returning a valid dynamic import call e.g. `dynamic(() => \
|
||||
import('../some-component'))`",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
}
|
||||
|
||||
// loadableGenerated: {
|
||||
// webpack: () => [require.resolveWeak('../components/hello')],
|
||||
// modules:
|
||||
// ["/project/src/file-being-transformed.js -> " + '../components/hello'] }
|
||||
let generated = Box::new(Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props: vec![
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
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 {
|
||||
elems: vec![Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Call(CallExpr {
|
||||
callee: ExprOrSuper::Expr(Box::new(Expr::Member(
|
||||
MemberExpr {
|
||||
obj: ExprOrSuper::Expr(Box::new(
|
||||
Expr::Ident(Ident {
|
||||
sym: js_word!("require"),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
}),
|
||||
)),
|
||||
prop: Box::new(Expr::Ident(Ident {
|
||||
sym: "resolveWeak".into(),
|
||||
span: DUMMY_SP,
|
||||
optional: false,
|
||||
})),
|
||||
computed: false,
|
||||
span: DUMMY_SP,
|
||||
},
|
||||
))),
|
||||
args: vec![ExprOrSpread {
|
||||
expr: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: self.filename.to_string().into(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Synthesized {},
|
||||
has_escape: false,
|
||||
}))),
|
||||
spread: None,
|
||||
}],
|
||||
span: DUMMY_SP,
|
||||
type_args: None,
|
||||
})),
|
||||
spread: None,
|
||||
})],
|
||||
span: DUMMY_SP,
|
||||
}))),
|
||||
is_async: false,
|
||||
is_generator: false,
|
||||
span: DUMMY_SP,
|
||||
return_type: None,
|
||||
type_params: None,
|
||||
})),
|
||||
}))),
|
||||
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new("modules".into(), DUMMY_SP)),
|
||||
value: Box::new(Expr::Array(ArrayLit {
|
||||
elems: vec![Some(ExprOrSpread {
|
||||
expr: Box::new(Expr::Bin(BinExpr {
|
||||
span: DUMMY_SP,
|
||||
op: BinaryOp::Add,
|
||||
left: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: format!(
|
||||
"{} -> ",
|
||||
rel_filename(
|
||||
self.pages_dir.as_deref(),
|
||||
&self.filename
|
||||
)
|
||||
)
|
||||
.into(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Synthesized {},
|
||||
has_escape: false,
|
||||
}))),
|
||||
right: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
value: import_specifier.unwrap(),
|
||||
span: DUMMY_SP,
|
||||
kind: StrKind::Normal {
|
||||
contains_quote: false,
|
||||
},
|
||||
has_escape: false,
|
||||
}))),
|
||||
})),
|
||||
spread: None,
|
||||
})],
|
||||
span: DUMMY_SP,
|
||||
})),
|
||||
}))),
|
||||
],
|
||||
}));
|
||||
|
||||
let mut props =
|
||||
vec![PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new("loadableGenerated".into(), DUMMY_SP)),
|
||||
value: generated,
|
||||
})))];
|
||||
|
||||
if expr.args.len() == 2 {
|
||||
if let Expr::Object(ObjectLit {
|
||||
props: options_props,
|
||||
..
|
||||
}) = &*expr.args[1].expr
|
||||
{
|
||||
props.extend(options_props.iter().cloned());
|
||||
}
|
||||
}
|
||||
|
||||
let second_arg = ExprOrSpread {
|
||||
spread: None,
|
||||
expr: Box::new(Expr::Object(ObjectLit {
|
||||
span: DUMMY_SP,
|
||||
props,
|
||||
})),
|
||||
};
|
||||
|
||||
expr.args.push(second_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
expr
|
||||
}
|
||||
expr
|
||||
}
|
||||
}
|
||||
|
||||
fn rel_filename(base: Option<&Path>, file: &FileName) -> String {
|
||||
let base = match base {
|
||||
Some(v) => v,
|
||||
None => return file.to_string(),
|
||||
};
|
||||
|
||||
let file = match file {
|
||||
FileName::Real(v) => v,
|
||||
_ => {
|
||||
return file.to_string();
|
||||
}
|
||||
};
|
||||
|
||||
let rel_path = diff_paths(&file, base);
|
||||
|
||||
let rel_path = match rel_path {
|
||||
Some(v) => v,
|
||||
None => return file.display().to_string(),
|
||||
};
|
||||
|
||||
rel_path.display().to_string()
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ use crate::{
|
|||
use anyhow::{Context as _, Error};
|
||||
use napi::{CallContext, Env, JsBoolean, JsObject, JsString, Task};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
use swc::{try_with_handler, Compiler, TransformOutput};
|
||||
use swc_common::{chain, pass::Optional, FileName, SourceFile};
|
||||
use swc_ecmascript::ast::Program;
|
||||
|
@ -51,13 +51,16 @@ pub enum Input {
|
|||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TransformOptions {
|
||||
#[serde(flatten)]
|
||||
swc: swc::config::Options,
|
||||
pub swc: swc::config::Options,
|
||||
|
||||
#[serde(default)]
|
||||
pub disable_next_ssg: bool,
|
||||
|
||||
#[serde(default)]
|
||||
pub pages_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub struct TransformTask {
|
||||
|
@ -78,7 +81,7 @@ impl Task for TransformTask {
|
|||
hook_optimizer(),
|
||||
Optional::new(next_ssg(), !self.options.disable_next_ssg),
|
||||
amp_attributes(),
|
||||
next_dynamic(s.name.clone()),
|
||||
next_dynamic(s.name.clone(), self.options.pages_dir.clone()),
|
||||
);
|
||||
self.c.process_js_with_custom_pass(
|
||||
s.clone(),
|
||||
|
@ -175,3 +178,12 @@ pub fn transform_sync(cx: CallContext) -> napi::Result<JsObject> {
|
|||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deser() {
|
||||
const JSON_STR: &str = r#"{"jsc":{"parser":{"syntax":"ecmascript","dynamicImport":true,"jsx":true},"transform":{"react":{"runtime":"automatic","pragma":"React.createElement","pragmaFrag":"React.Fragment","throwIfNamespace":true,"development":false,"useBuiltins":true}},"target":"es5"},"filename":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js","sourceMaps":false,"sourceFileName":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js"}"#;
|
||||
|
||||
let tr: TransformOptions = serde_json::from_str(&JSON_STR).unwrap();
|
||||
|
||||
println!("{:#?}", tr);
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ use std::path::PathBuf;
|
|||
use swc_common::{chain, comments::SingleThreadedComments, FileName};
|
||||
use swc_ecma_transforms_testing::{test, test_fixture};
|
||||
use swc_ecmascript::{
|
||||
parser::{EsConfig, Syntax},
|
||||
transforms::react::jsx,
|
||||
parser::{EsConfig, Syntax},
|
||||
transforms::react::jsx,
|
||||
};
|
||||
use testing::fixture;
|
||||
|
||||
|
@ -18,59 +18,60 @@ mod next_dynamic;
|
|||
mod next_ssg;
|
||||
|
||||
fn syntax() -> Syntax {
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
dynamic_import: true,
|
||||
..Default::default()
|
||||
})
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
dynamic_import: true,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/amp/**/input.js")]
|
||||
fn amp_attributes_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(syntax(), &|_tr| amp_attributes(), &input, &output);
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(syntax(), &|_tr| amp_attributes(), &input, &output);
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/next-dynamic/**/input.js")]
|
||||
fn next_dynamic_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|_tr| {
|
||||
next_dynamic(FileName::Real(PathBuf::from(
|
||||
"/some-project/src/some-file.js",
|
||||
)))
|
||||
},
|
||||
&input,
|
||||
&output,
|
||||
);
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|_tr| {
|
||||
next_dynamic(
|
||||
FileName::Real(PathBuf::from("/some-project/src/some-file.js")),
|
||||
Some("/some-project/src".into()),
|
||||
)
|
||||
},
|
||||
&input,
|
||||
&output,
|
||||
);
|
||||
}
|
||||
|
||||
#[fixture("tests/fixture/ssg/**/input.js")]
|
||||
fn next_ssg_fixture(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|tr| {
|
||||
let jsx = jsx::<SingleThreadedComments>(
|
||||
tr.cm.clone(),
|
||||
None,
|
||||
swc_ecmascript::transforms::react::Options {
|
||||
next: false,
|
||||
runtime: None,
|
||||
import_source: "".into(),
|
||||
pragma: "__jsx".into(),
|
||||
pragma_frag: "__jsxFrag".into(),
|
||||
throw_if_namespace: false,
|
||||
development: false,
|
||||
use_builtins: true,
|
||||
use_spread: true,
|
||||
refresh: Default::default(),
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|tr| {
|
||||
let jsx = jsx::<SingleThreadedComments>(
|
||||
tr.cm.clone(),
|
||||
None,
|
||||
swc_ecmascript::transforms::react::Options {
|
||||
next: false,
|
||||
runtime: None,
|
||||
import_source: "".into(),
|
||||
pragma: "__jsx".into(),
|
||||
pragma_frag: "__jsxFrag".into(),
|
||||
throw_if_namespace: false,
|
||||
development: false,
|
||||
use_builtins: true,
|
||||
use_spread: true,
|
||||
refresh: Default::default(),
|
||||
},
|
||||
);
|
||||
chain!(next_ssg(), jsx)
|
||||
},
|
||||
);
|
||||
chain!(next_ssg(), jsx)
|
||||
},
|
||||
&input,
|
||||
&output,
|
||||
);
|
||||
&input,
|
||||
&output,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ import dynamic2 from 'next/dynamic'
|
|||
const DynamicComponent1 = dynamic1(() => import('../components/hello1'), {
|
||||
loadableGenerated: {
|
||||
webpack: () => [require.resolveWeak('/some-project/src/some-file.js')],
|
||||
modules: ['/some-project/src/some-file.js -> ' + '../components/hello1'],
|
||||
modules: ['some-file.js -> ' + '../components/hello1'],
|
||||
},
|
||||
})
|
||||
const DynamicComponent2 = dynamic2(() => import('../components/hello2'), {
|
||||
loadableGenerated: {
|
||||
webpack: () => [require.resolveWeak('/some-project/src/some-file.js')],
|
||||
modules: ['/some-project/src/some-file.js -> ' + '../components/hello2'],
|
||||
modules: ['some-file.js -> ' + '../components/hello2'],
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import dynamic from 'next/dynamic'
|
||||
import somethingElse from 'something-else'
|
||||
|
||||
const DynamicComponent = dynamic(() => import('../components/hello'), {
|
||||
loadableGenerated: {
|
||||
webpack: () => [require.resolveWeak('/some-project/src/some-file.js')],
|
||||
modules: ['/some-project/src/some-file.js -> ' + '../components/hello'],
|
||||
modules: ['some-file.js -> ' + '../components/hello'],
|
||||
},
|
||||
})
|
||||
somethingElse.dynamic('should not be transformed')
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import dynamic from 'next/dynamic'
|
||||
|
||||
const DynamicComponent = dynamic(() => import('../components/hello'), {
|
||||
loadableGenerated: {
|
||||
webpack: () => [require.resolveWeak('/some-project/src/some-file.js')],
|
||||
modules: ['/some-project/src/some-file.js -> ' + '../components/hello'],
|
||||
modules: ['some-file.js -> ' + '../components/hello'],
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import dynamic from 'next/dynamic'
|
||||
|
||||
const DynamicComponentWithCustomLoading = dynamic(
|
||||
() => import('../components/hello'),
|
||||
{ loading: () => <p>...</p> },
|
||||
{
|
||||
loading: () => <p>...</p>,
|
||||
},
|
||||
{
|
||||
loadableGenerated: {
|
||||
webpack: () => [require.resolveWeak('/some-project/src/some-file.js')],
|
||||
modules: ['/some-project/src/some-file.js -> ' + '../components/hello'],
|
||||
modules: ['some-file.js -> ' + '../components/hello'],
|
||||
},
|
||||
loading: () => <p>...</p>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue