Add auto-commonjs and update swc (#30661)
Closes #30596 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `yarn lint` - This patch contains several patches from swc. This includes https://github.com/swc-project/swc/pull/2581, which allows customizing the import path for regenerator. - This adds auto-detection of common js. If `module.exports` is found and module config is not set, module config becomes common js. - As bonus, this includes some performance improvements The logic for analyzing the input source file and parsing options as json is moved from the js thread to a background worker thread.
This commit is contained in:
parent
d8cb8c5fbc
commit
4ada314663
9 changed files with 191 additions and 62 deletions
56
packages/next/build/swc/Cargo.lock
generated
56
packages/next/build/swc/Cargo.lock
generated
|
@ -469,6 +469,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
|
@ -1578,9 +1584,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
|||
|
||||
[[package]]
|
||||
name = "swc"
|
||||
version = "0.79.2"
|
||||
version = "0.80.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c39e3a5230c137d91421ff1d71dae6a41c6a20934b19230dd586f15fbc6cffbb"
|
||||
checksum = "bc6f880c108482b5ddbe859e4da2a50617ec3ae9984d2db9c9974cd37e8b515b"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
@ -1831,9 +1837,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_minifier"
|
||||
version = "0.46.7"
|
||||
version = "0.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "352c358c3600520fd9d7f97523a3fed0e802219853d15acefbd2d0a7b5caaa66"
|
||||
checksum = "2e4898ec9f84d9d9630d2dd2debf9d593824ddecc44c8f1e1a30988af8a78ee5"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"indexmap",
|
||||
|
@ -1880,9 +1886,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_preset_env"
|
||||
version = "0.61.0"
|
||||
version = "0.62.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d43efdeffd84fcd2edacbbf5abe6bbe5696d4098347d3796ed4d7ad2bfe2402c"
|
||||
checksum = "fae8f62b754f17726a17339b08ead21121666a16bb916544f61837c6bba949d0"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"dashmap",
|
||||
|
@ -1904,9 +1910,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms"
|
||||
version = "0.90.0"
|
||||
version = "0.91.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6032d75bbca42aa6943867362c0136be74e4cf707f436358ca26bf5e1149bdc0"
|
||||
checksum = "0cf60ed2f162385b466cd1d2238ae235d81d859d63024daf8fa157aadd35fdfe"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
|
@ -1959,9 +1965,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_compat"
|
||||
version = "0.47.2"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "848a3df0611dd2c180a5c0265472b08583fae329dc6da2c79f4933be201940de"
|
||||
checksum = "cbf954ba120a43c64062d92ce0a753b19e92817272a0cba12921041da105fa5c"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"arrayvec",
|
||||
|
@ -1996,9 +2002,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_module"
|
||||
version = "0.53.0"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f3474868c30d28fdffe4ec9a009e775912076be7c8d5fd4b4c49c07e1e12786"
|
||||
checksum = "a50df9d36d5622e563e1a6d8ecc4b264b5aeef031aa6cb9c631cb5495c3d0b16"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"ahash",
|
||||
|
@ -2018,9 +2024,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_optimization"
|
||||
version = "0.60.2"
|
||||
version = "0.61.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5c1573805a8da8391c6d411a0485d345b1a9280236afc3663f392bab3d9a272"
|
||||
checksum = "8ad9e812184d0dbef37e3600b5a599b6c9f2568ce67f048c961146dd33dd274d"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"dashmap",
|
||||
|
@ -2041,9 +2047,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_proposal"
|
||||
version = "0.53.0"
|
||||
version = "0.54.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc9e665a73f580b9ec31096a88660a1bf1c9df23bc6ae187d7ad3b0095bb9b73"
|
||||
checksum = "742878426185a4365b8bcc8333116a6abf0d0417a98db1fd5817ff0a34276d14"
|
||||
dependencies = [
|
||||
"either",
|
||||
"serde",
|
||||
|
@ -2061,9 +2067,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_react"
|
||||
version = "0.55.0"
|
||||
version = "0.56.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fc5b294bcc167b2d72943ebcbb6a9d27d6a46840e6eb2b4f24295cc4254e259"
|
||||
checksum = "5e9291e184940e23e17eb29d89899a95fa163f6f932b803f183932e5e80d3c07"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"base64 0.13.0",
|
||||
|
@ -2086,14 +2092,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_testing"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fead0df8b91a0f721790fa50104af1e6a262973090ace055adb6a9a962f2b0b1"
|
||||
checksum = "4abe5a4d8f718627d2d5a9d96233d0292a2cd0a071efdfde0a14d7221f37a987"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"anyhow",
|
||||
"hex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha-1",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen",
|
||||
|
@ -2107,9 +2115,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecma_transforms_typescript"
|
||||
version = "0.56.1"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08e24e661be9fd9018ca10d6394db3e0f970c8c7fef6649740a1d96e54f8bc7d"
|
||||
checksum = "d2698634fbfc7dbed01e516ef4610507e39dd81373de3b687d453e1b1e80f456"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"swc_atoms",
|
||||
|
@ -2152,9 +2160,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swc_ecmascript"
|
||||
version = "0.82.0"
|
||||
version = "0.83.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf11dc8be7e4c7e33702fa92c1c2db4f505aa98b1995702f13fce7d05a74a18e"
|
||||
checksum = "79dca2ffcbed1a4a5a0b90265bb4b484c7540437549dcf0c807c3f30d180a79f"
|
||||
dependencies = [
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen",
|
||||
|
|
|
@ -17,12 +17,12 @@ path-clean = "0.1"
|
|||
regex = "1.5"
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
swc = "0.79.0"
|
||||
swc = "0.80.0"
|
||||
swc_atoms = "0.2.7"
|
||||
swc_common = { version = "0.14.2", features = ["concurrent", "sourcemap"] }
|
||||
swc_css = "0.20.0"
|
||||
swc_ecmascript = { version = "0.82.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
|
||||
swc_ecma_preset_env = "0.61.0"
|
||||
swc_ecmascript = { version = "0.83.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
|
||||
swc_ecma_preset_env = "0.62.0"
|
||||
swc_node_base = "0.5.1"
|
||||
swc_stylis = "0.17.0"
|
||||
fxhash = "0.2.1"
|
||||
|
@ -36,9 +36,9 @@ tracing = { version = "0.1.28", features = ["release_max_level_off"] }
|
|||
napi-build = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
swc_ecma_transforms_testing = "0.42.0"
|
||||
testing = "0.15.0"
|
||||
swc_ecma_transforms_testing = "0.42.1"
|
||||
testing = "0.15.1"
|
||||
walkdir = "2.3.2"
|
||||
|
||||
[profile.release]
|
||||
# lto = true
|
||||
lto = true
|
||||
|
|
46
packages/next/build/swc/src/auto_cjs/mod.rs
Normal file
46
packages/next/build/swc/src/auto_cjs/mod.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use swc_common::DUMMY_SP;
|
||||
use swc_ecmascript::{
|
||||
ast::*,
|
||||
visit::{Node, Visit, VisitWith},
|
||||
};
|
||||
|
||||
pub(crate) fn contains_cjs(m: &Module) -> bool {
|
||||
let mut v = CjsFinder::default();
|
||||
m.visit_with(&Invalid { span: DUMMY_SP }, &mut v);
|
||||
v.found
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
struct CjsFinder {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
/// This visitor implementation supports typescript, because the api of `swc`
|
||||
/// does not support changing configuration based on content of the file.
|
||||
impl Visit for CjsFinder {
|
||||
fn visit_member_expr(&mut self, e: &MemberExpr, _: &dyn Node) {
|
||||
if !e.computed {
|
||||
match &e.obj {
|
||||
ExprOrSuper::Super(_) => {}
|
||||
ExprOrSuper::Expr(obj) => match &**obj {
|
||||
Expr::Ident(obj) => match &*e.prop {
|
||||
Expr::Ident(prop) => {
|
||||
if &*obj.sym == "module" && &*prop.sym == "exports" {
|
||||
self.found = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
e.obj.visit_with(e, self);
|
||||
|
||||
if e.computed {
|
||||
e.prop.visit_with(e, self);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,15 +34,22 @@ extern crate napi_derive;
|
|||
/// Explicit extern crate to use allocator.
|
||||
extern crate swc_node_base;
|
||||
|
||||
use auto_cjs::contains_cjs;
|
||||
use backtrace::Backtrace;
|
||||
use napi::{CallContext, Env, JsObject, JsUndefined};
|
||||
use serde::Deserialize;
|
||||
use std::{env, panic::set_hook, path::PathBuf, sync::Arc};
|
||||
use swc::{Compiler, TransformOutput};
|
||||
use swc::{config::ModuleConfig, Compiler, TransformOutput};
|
||||
use swc_common::SourceFile;
|
||||
use swc_common::{self, chain, pass::Optional, sync::Lazy, FileName, FilePathMapping, SourceMap};
|
||||
use swc_ecmascript::visit::Fold;
|
||||
use swc_ecmascript::ast::EsVersion;
|
||||
use swc_ecmascript::{
|
||||
parser::{lexer::Lexer, Parser, StringInput},
|
||||
visit::Fold,
|
||||
};
|
||||
|
||||
pub mod amp_attributes;
|
||||
mod auto_cjs;
|
||||
pub mod hook_optimizer;
|
||||
pub mod minify;
|
||||
pub mod next_dynamic;
|
||||
|
@ -52,7 +59,7 @@ pub mod styled_jsx;
|
|||
mod transform;
|
||||
mod util;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TransformOptions {
|
||||
#[serde(flatten)]
|
||||
|
@ -126,4 +133,27 @@ pub fn complete_output(env: &Env, output: TransformOutput) -> napi::Result<JsObj
|
|||
env.to_js_value(&output)?.coerce_to_object()
|
||||
}
|
||||
|
||||
impl TransformOptions {
|
||||
pub fn patch(mut self, fm: &SourceFile) -> Self {
|
||||
self.swc.swcrc = false;
|
||||
|
||||
let should_enable_commonjs =
|
||||
self.swc.config.module.is_none() && fm.src.contains("module.exports") && {
|
||||
let syntax = self.swc.config.jsc.syntax.unwrap_or_default();
|
||||
let target = self.swc.config.jsc.target.unwrap_or(EsVersion::latest());
|
||||
let lexer = Lexer::new(syntax, target, StringInput::from(&*fm), None);
|
||||
let mut p = Parser::new_from(lexer);
|
||||
p.parse_module()
|
||||
.map(|m| contains_cjs(&m))
|
||||
.unwrap_or_default()
|
||||
};
|
||||
|
||||
if should_enable_commonjs {
|
||||
self.swc.config.module = Some(ModuleConfig::CommonJs(Default::default()));
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub type ArcCompiler = Arc<Compiler>;
|
||||
|
|
|
@ -28,7 +28,7 @@ DEALINGS IN THE SOFTWARE.
|
|||
|
||||
use crate::{
|
||||
complete_output, custom_before_pass, get_compiler,
|
||||
util::{CtxtExt, MapErr},
|
||||
util::{deserialize_json, CtxtExt, MapErr},
|
||||
TransformOptions,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _, Error};
|
||||
|
@ -46,13 +46,13 @@ use swc_ecmascript::transforms::pass::noop;
|
|||
#[derive(Debug)]
|
||||
pub enum Input {
|
||||
/// Raw source code.
|
||||
Source(Arc<SourceFile>),
|
||||
Source { src: String },
|
||||
}
|
||||
|
||||
pub struct TransformTask {
|
||||
pub c: Arc<Compiler>,
|
||||
pub input: Input,
|
||||
pub options: TransformOptions,
|
||||
pub options: String,
|
||||
}
|
||||
|
||||
impl Task for TransformTask {
|
||||
|
@ -62,13 +62,25 @@ impl Task for TransformTask {
|
|||
fn compute(&mut self) -> napi::Result<Self::Output> {
|
||||
let res = catch_unwind(AssertUnwindSafe(|| {
|
||||
try_with_handler(self.c.cm.clone(), true, |handler| {
|
||||
self.c.run(|| match self.input {
|
||||
Input::Source(ref s) => {
|
||||
let before_pass = custom_before_pass(&s.name, &self.options);
|
||||
self.c.run(|| match &self.input {
|
||||
Input::Source { src } => {
|
||||
let options: TransformOptions = deserialize_json(&self.options)?;
|
||||
|
||||
let filename = if options.swc.filename.is_empty() {
|
||||
FileName::Anon
|
||||
} else {
|
||||
FileName::Real(options.swc.filename.clone().into())
|
||||
};
|
||||
|
||||
let fm = self.c.cm.new_source_file(filename, src.to_string());
|
||||
|
||||
let options = options.patch(&fm);
|
||||
|
||||
let before_pass = custom_before_pass(&fm.name, &options);
|
||||
self.c.process_js_with_custom_pass(
|
||||
s.clone(),
|
||||
fm.clone(),
|
||||
&handler,
|
||||
&self.options.swc,
|
||||
&options.swc,
|
||||
before_pass,
|
||||
noop(),
|
||||
)
|
||||
|
@ -101,15 +113,15 @@ impl Task for TransformTask {
|
|||
/// returns `compiler, (src / path), options, plugin, callback`
|
||||
pub fn schedule_transform<F>(cx: CallContext, op: F) -> napi::Result<JsObject>
|
||||
where
|
||||
F: FnOnce(&Arc<Compiler>, String, bool, TransformOptions) -> TransformTask,
|
||||
F: FnOnce(&Arc<Compiler>, String, bool, String) -> TransformTask,
|
||||
{
|
||||
let c = get_compiler(&cx);
|
||||
|
||||
let s = cx.get::<JsString>(0)?.into_utf8()?.as_str()?.to_owned();
|
||||
let src = cx.get::<JsString>(0)?.into_utf8()?.as_str()?.to_owned();
|
||||
let is_module = cx.get::<JsBoolean>(1)?;
|
||||
let options: TransformOptions = cx.get_deserialized(2)?;
|
||||
let options = cx.get_buffer_as_string(2)?;
|
||||
|
||||
let task = op(&c, s, is_module.get_value()?, options);
|
||||
let task = op(&c, src, is_module.get_value()?, options);
|
||||
|
||||
cx.env.spawn(task).map(|t| t.promise_object())
|
||||
}
|
||||
|
@ -145,17 +157,8 @@ where
|
|||
|
||||
#[js_function(4)]
|
||||
pub fn transform(cx: CallContext) -> napi::Result<JsObject> {
|
||||
schedule_transform(cx, |c, src, _, mut options| {
|
||||
options.swc.swcrc = false;
|
||||
|
||||
let input = Input::Source(c.cm.new_source_file(
|
||||
if options.swc.filename.is_empty() {
|
||||
FileName::Anon
|
||||
} else {
|
||||
FileName::Real(options.swc.filename.clone().into())
|
||||
},
|
||||
src,
|
||||
));
|
||||
schedule_transform(cx, |c, src, _, options| {
|
||||
let input = Input::Source { src };
|
||||
|
||||
TransformTask {
|
||||
c: c.clone(),
|
||||
|
|
|
@ -26,7 +26,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::{Context, Error};
|
||||
use napi::{CallContext, JsBuffer, Status};
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::any::type_name;
|
||||
|
@ -41,6 +41,7 @@ pub trait MapErr<T>: Into<Result<T, anyhow::Error>> {
|
|||
impl<T> MapErr<T> for Result<T, anyhow::Error> {}
|
||||
|
||||
pub trait CtxtExt {
|
||||
fn get_buffer_as_string(&self, index: usize) -> napi::Result<String>;
|
||||
/// Currently this uses JsBuffer
|
||||
fn get_deserialized<T>(&self, index: usize) -> napi::Result<T>
|
||||
where
|
||||
|
@ -48,6 +49,12 @@ pub trait CtxtExt {
|
|||
}
|
||||
|
||||
impl CtxtExt for CallContext<'_> {
|
||||
fn get_buffer_as_string(&self, index: usize) -> napi::Result<String> {
|
||||
let buffer = self.get::<JsBuffer>(index)?.into_value()?;
|
||||
|
||||
Ok(String::from_utf8_lossy(buffer.as_ref()).to_string())
|
||||
}
|
||||
|
||||
fn get_deserialized<T>(&self, index: usize) -> napi::Result<T>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
|
@ -67,3 +74,11 @@ impl CtxtExt for CallContext<'_> {
|
|||
Ok(v)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize_json<T>(s: &str) -> Result<T, Error>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
serde_json::from_str(&s)
|
||||
.with_context(|| format!("failed to deserialize as {}\nJSON: {}", type_name::<T>(), s))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use next_swc::custom_before_pass;
|
||||
use next_swc::{custom_before_pass, TransformOptions};
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::path::{Path, PathBuf};
|
||||
use swc::Compiler;
|
||||
|
@ -26,10 +26,9 @@ fn test(input: &Path, minify: bool) {
|
|||
let c = Compiler::new(cm.clone());
|
||||
|
||||
let fm = cm.load_file(input).expect("failed to load file");
|
||||
match c.process_js_with_custom_pass(
|
||||
fm.clone(),
|
||||
&handler,
|
||||
&swc::config::Options {
|
||||
|
||||
let options = TransformOptions {
|
||||
swc: swc::config::Options {
|
||||
swcrc: true,
|
||||
is_module: true,
|
||||
output_path: Some(output.to_path_buf()),
|
||||
|
@ -52,6 +51,19 @@ fn test(input: &Path, minify: bool) {
|
|||
},
|
||||
..Default::default()
|
||||
},
|
||||
disable_next_ssg: false,
|
||||
disable_page_config: false,
|
||||
pages_dir: None,
|
||||
is_page_file: false,
|
||||
is_development: true,
|
||||
};
|
||||
|
||||
let options = options.patch(&fm);
|
||||
|
||||
match c.process_js_with_custom_pass(
|
||||
fm.clone(),
|
||||
&handler,
|
||||
&options.swc,
|
||||
custom_before_pass(&fm.name, &assert_json(&"{}")),
|
||||
noop(),
|
||||
) {
|
||||
|
|
7
packages/next/build/swc/tests/full/auto-cjs/1/input.js
Normal file
7
packages/next/build/swc/tests/full/auto-cjs/1/input.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import mixed from 'esm';
|
||||
|
||||
|
||||
console.log(mixed.foo);
|
||||
|
||||
|
||||
module.exports = mixed;
|
8
packages/next/build/swc/tests/full/auto-cjs/1/output.js
Normal file
8
packages/next/build/swc/tests/full/auto-cjs/1/output.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
var _esm = _interopRequireDefault(require("esm"));
|
||||
function _interopRequireDefault(a) {
|
||||
return a && a.__esModule ? a : {
|
||||
default: a
|
||||
};
|
||||
}
|
||||
console.log(_esm.default.foo), module.exports = _esm.default;
|
Loading…
Reference in a new issue