diff --git a/.prettierignore b/.prettierignore index edcab939ce4c2..baf4892dfbfbb 100644 --- a/.prettierignore +++ b/.prettierignore @@ -22,6 +22,8 @@ packages/next/src/bundles/webpack/packages/lazy-compilation-*.js packages/next-swc/crates/**/tests/**/output* packages/next-swc/crates/core/tests/loader/issue-32553/input.js packages/next-swc/crates/next-dev-tests/tests/integration/turbopack/basic/error/input/broken.js +packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw.js +packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/raw/hello.js packages/next-swc/native/**/* packages/next-codemod/transforms/__testfixtures__/** diff --git a/Cargo.lock b/Cargo.lock index 6b1e97ab484f8..3e7b985674d0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -394,7 +394,7 @@ dependencies = [ [[package]] name = "auto-hash-map" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "serde", ] @@ -3424,7 +3424,7 @@ dependencies = [ [[package]] name = "node-file-trace" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "serde", @@ -7034,7 +7034,7 @@ dependencies = [ [[package]] name = "turbo-tasks" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "auto-hash-map", @@ -7065,7 +7065,7 @@ dependencies = [ [[package]] name = "turbo-tasks-build" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "cargo-lock", @@ -7077,7 +7077,7 @@ dependencies = [ [[package]] name = "turbo-tasks-bytes" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "bytes", @@ -7092,7 +7092,7 @@ dependencies = [ [[package]] name = "turbo-tasks-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "dotenvy", @@ -7106,7 +7106,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fetch" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "indexmap", @@ -7123,7 +7123,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fs" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "auto-hash-map", @@ -7153,7 +7153,7 @@ dependencies = [ [[package]] name = "turbo-tasks-hash" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "base16", "hex", @@ -7165,7 +7165,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "convert_case 0.6.0", @@ -7179,7 +7179,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros-shared" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "proc-macro2", "quote", @@ -7189,7 +7189,7 @@ dependencies = [ [[package]] name = "turbo-tasks-malloc" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "mimalloc", ] @@ -7197,7 +7197,7 @@ dependencies = [ [[package]] name = "turbo-tasks-memory" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "auto-hash-map", @@ -7220,7 +7220,7 @@ dependencies = [ [[package]] name = "turbo-tasks-testing" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "auto-hash-map", @@ -7232,7 +7232,7 @@ dependencies = [ [[package]] name = "turbopack" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "async-recursion", @@ -7262,7 +7262,7 @@ dependencies = [ [[package]] name = "turbopack-bench" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "chromiumoxide", @@ -7292,7 +7292,7 @@ dependencies = [ [[package]] name = "turbopack-binding" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "auto-hash-map", "mdxjs", @@ -7332,7 +7332,7 @@ dependencies = [ [[package]] name = "turbopack-cli-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "clap 4.1.11", @@ -7356,7 +7356,7 @@ dependencies = [ [[package]] name = "turbopack-core" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "async-trait", @@ -7384,7 +7384,7 @@ dependencies = [ [[package]] name = "turbopack-create-test-app" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "clap 4.1.11", @@ -7397,7 +7397,7 @@ dependencies = [ [[package]] name = "turbopack-css" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "async-trait", @@ -7419,7 +7419,7 @@ dependencies = [ [[package]] name = "turbopack-dev" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "indexmap", @@ -7441,7 +7441,7 @@ dependencies = [ [[package]] name = "turbopack-dev-server" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "async-compression", @@ -7476,7 +7476,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "async-trait", @@ -7494,10 +7494,7 @@ dependencies = [ "serde", "serde_json", "serde_qs", - "styled_components", - "styled_jsx", "swc_core", - "swc_emotion", "tokio", "tracing", "turbo-tasks", @@ -7512,7 +7509,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-plugins" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "async-trait", @@ -7533,7 +7530,7 @@ dependencies = [ [[package]] name = "turbopack-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "indexmap", @@ -7549,7 +7546,7 @@ dependencies = [ [[package]] name = "turbopack-image" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "base64 0.21.0", @@ -7569,7 +7566,7 @@ dependencies = [ [[package]] name = "turbopack-json" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "serde", @@ -7584,7 +7581,7 @@ dependencies = [ [[package]] name = "turbopack-mdx" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "mdxjs", @@ -7599,7 +7596,7 @@ dependencies = [ [[package]] name = "turbopack-node" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "async-stream", @@ -7634,7 +7631,7 @@ dependencies = [ [[package]] name = "turbopack-static" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "serde", @@ -7650,7 +7647,7 @@ dependencies = [ [[package]] name = "turbopack-swc-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "swc_core", "turbo-tasks", @@ -7661,7 +7658,7 @@ dependencies = [ [[package]] name = "turbopack-test-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230522.2#cee02be048d8f402f1ad50dd2b8589cacd9ae910" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230523.2#2a0256bec14e867f8f086f82692f467e2f02cbb1" dependencies = [ "anyhow", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index f79c49e6f831d..834d31aaa4302 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,11 +42,11 @@ swc_core = { version = "0.76.18" } testing = { version = "0.33.11" } # Turbo crates -turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230522.2" } +turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230523.2" } # [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros.. -turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230522.2" } +turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230523.2" } # [TODO]: need to refactor embed_directory! macro usage in next-core -turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230522.2" } +turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230523.2" } # General Deps diff --git a/packages/next-swc/crates/next-core/js/package.json b/packages/next-swc/crates/next-core/js/package.json index e12d22bb4b853..a7e775934c7fd 100644 --- a/packages/next-swc/crates/next-core/js/package.json +++ b/packages/next-swc/crates/next-core/js/package.json @@ -10,8 +10,8 @@ "check": "tsc --noEmit" }, "dependencies": { - "@vercel/turbopack-dev": "https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230522.2", - "@vercel/turbopack-node": "https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230522.2", + "@vercel/turbopack-dev": "https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230523.2", + "@vercel/turbopack-node": "https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230523.2", "anser": "^2.1.1", "css.escape": "^1.5.1", "next": "*", diff --git a/packages/next-swc/crates/next-core/src/babel.rs b/packages/next-swc/crates/next-core/src/babel.rs index 18805f600ceec..73f89f0e7c8fd 100644 --- a/packages/next-swc/crates/next-core/src/babel.rs +++ b/packages/next-swc/crates/next-core/src/babel.rs @@ -10,9 +10,10 @@ use turbopack_binding::{ issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, resolve::{parse::RequestVc, pattern::Pattern, resolve}, }, - node::transforms::webpack::{WebpackLoaderConfigItem, WebpackLoaderConfigItemsVc}, + node::transforms::webpack::{WebpackLoaderItem, WebpackLoaderItemsVc}, turbopack::{ - module_options::WebpackLoadersOptionsVc, resolve_options, + module_options::{LoaderRuleItem, OptionWebpackRulesVc, WebpackRulesVc}, + resolve_options, resolve_options_context::ResolveOptionsContext, }, }, @@ -36,8 +37,8 @@ const BABEL_CONFIG_FILES: &[&str] = &[ #[turbo_tasks::function] pub async fn maybe_add_babel_loader( project_root: FileSystemPathVc, - webpack_options: WebpackLoadersOptionsVc, -) -> Result { + webpack_rules: Option, +) -> Result { let has_babel_config = { let mut has_babel_config = false; for filename in BABEL_CONFIG_FILES { @@ -51,30 +52,22 @@ pub async fn maybe_add_babel_loader( }; if has_babel_config { - let mut options = (*webpack_options.await?).clone(); + let mut rules = if let Some(webpack_rules) = webpack_rules { + webpack_rules.await?.clone_value() + } else { + Default::default() + }; let mut has_emitted_babel_resolve_issue = false; - for ext in [".js", ".jsx", ".ts", ".tsx", ".cjs", ".mjs"] { - let configs = options.extension_to_loaders.get(ext); - let has_babel_loader = match configs { - None => false, - Some(configs) => { - let mut has_babel_loader = false; - for config in &*configs.await? { - let name = match config { - WebpackLoaderConfigItem::LoaderName(name) => name, - WebpackLoaderConfigItem::LoaderNameWithOptions { - loader: name, - options: _, - } => name, - }; - - if name == "babel-loader" { - has_babel_loader = true; - break; - } - } - has_babel_loader - } + let mut has_changed = false; + for pattern in ["*.js", "*.jsx", "*.ts", "*.tsx", "*.cjs", "*.mjs"] { + let rule = rules.get_mut(pattern); + let has_babel_loader = if let Some(rule) = rule.as_ref() { + rule.loaders + .await? + .iter() + .any(|c| c.loader == "babel-loader") + } else { + false }; if !has_babel_loader { @@ -100,24 +93,34 @@ pub async fn maybe_add_babel_loader( has_emitted_babel_resolve_issue = true; } - let loader = WebpackLoaderConfigItem::LoaderName("babel-loader".to_owned()); - options.extension_to_loaders.insert( - ext.to_owned(), - if options.extension_to_loaders.contains_key(ext) { - let mut new_configs = (*(options.extension_to_loaders[ext].await?)).clone(); - new_configs.push(loader); - WebpackLoaderConfigItemsVc::cell(new_configs) - } else { - WebpackLoaderConfigItemsVc::cell(vec![loader]) - }, - ); + let loader = WebpackLoaderItem { + loader: "babel-loader".to_string(), + options: Default::default(), + }; + if let Some(rule) = rule { + let mut loaders = rule.loaders.await?.clone_value(); + loaders.push(loader); + rule.loaders = WebpackLoaderItemsVc::cell(loaders); + } else { + rules.insert( + pattern.to_string(), + LoaderRuleItem { + loaders: WebpackLoaderItemsVc::cell(vec![loader]), + rename_as: Some("*".to_string()), + }, + ); + } + has_changed = true; } } - Ok(options.cell()) - } else { - Ok(webpack_options) + if has_changed { + return Ok(OptionWebpackRulesVc::cell(Some(WebpackRulesVc::cell( + rules, + )))); + } } + Ok(OptionWebpackRulesVc::cell(webpack_rules)) } #[turbo_tasks::function] diff --git a/packages/next-swc/crates/next-core/src/next_client/context.rs b/packages/next-swc/crates/next-core/src/next_client/context.rs index 34259022be95f..19ee91d71ed72 100644 --- a/packages/next-swc/crates/next-core/src/next_client/context.rs +++ b/packages/next-swc/crates/next-core/src/next_client/context.rs @@ -195,22 +195,18 @@ pub async fn get_client_module_options_context( }; let jsx_runtime_options = get_jsx_transform_options(project_path, mode, Some(resolve_options_context)); - let enable_webpack_loaders = { - let options = &*next_config.webpack_loaders_options().await?; - let loaders_options = WebpackLoadersOptions { - extension_to_loaders: options.clone(), + let webpack_rules = + *maybe_add_babel_loader(project_path, *next_config.webpack_rules().await?).await?; + let webpack_rules = maybe_add_sass_loader(next_config.sass_config(), webpack_rules).await?; + let enable_webpack_loaders = webpack_rules.map(|rules| { + WebpackLoadersOptions { + rules, loader_runner_package: Some(get_external_next_compiled_package_mapping( StringVc::cell("loader-runner".to_owned()), )), - ..Default::default() } - .cell(); - - let loaders_options = maybe_add_babel_loader(project_path, loaders_options); - maybe_add_sass_loader(next_config.sass_config(), loaders_options) - .await? - .clone_if() - }; + .cell() + }); let source_transforms = vec![ *get_relay_transform_plugin(next_config).await?, diff --git a/packages/next-swc/crates/next-core/src/next_config.rs b/packages/next-swc/crates/next-core/src/next_config.rs index ff0b5a8e8ce3b..6e23aefb6f32c 100644 --- a/packages/next-swc/crates/next-core/src/next_config.rs +++ b/packages/next-swc/crates/next-core/src/next_config.rs @@ -3,7 +3,7 @@ use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; use turbo_tasks::{ - primitives::{BoolVc, JsonValueVc, StringsVc}, + primitives::{BoolVc, JsonValueVc, StringVc, StringsVc}, trace::TraceRawVcs, CompletionVc, Value, }; @@ -17,7 +17,7 @@ use turbopack_binding::{ chunk::ChunkingContext, context::AssetContext, ident::AssetIdentVc, - issue::IssueContextExt, + issue::{Issue, IssueContextExt, IssueSeverity, IssueSeverityVc, IssueVc}, reference_type::{EntryReferenceSubType, ReferenceType}, resolve::{ find_context_file, @@ -36,9 +36,12 @@ use turbopack_binding::{ node::{ evaluate::evaluate, execution_context::{ExecutionContext, ExecutionContextVc}, - transforms::webpack::{WebpackLoaderConfigItems, WebpackLoaderConfigItemsVc}, + transforms::webpack::{WebpackLoaderItem, WebpackLoaderItemsVc}, + }, + turbopack::{ + evaluate_context::node_evaluate_asset_context, + module_options::{LoaderRuleItem, OptionWebpackRulesVc, WebpackRulesVc}, }, - turbopack::evaluate_context::node_evaluate_asset_context, }, }; @@ -352,10 +355,30 @@ pub enum RemotePatternProtocal { #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct ExperimentalTurboConfig { - pub loaders: Option>, + /// This option has been replace by `rules`. + pub loaders: Option, + pub rules: Option>, pub resolve_alias: Option>, } +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(rename_all = "camelCase", untagged)] +pub enum RuleConfigItem { + Loaders(Vec), + Options { + loaders: Vec, + #[serde(default, alias = "as")] + rename_as: Option, + }, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)] +#[serde(untagged)] +pub enum LoaderItem { + LoaderName(String), + LoaderOptions(WebpackLoaderItem), +} + #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct ExperimentalConfig { @@ -461,10 +484,6 @@ pub enum RemoveConsoleConfig { Config { exclude: Option> }, } -#[derive(Default)] -#[turbo_tasks::value(transparent)] -pub struct WebpackExtensionToLoaders(IndexMap); - #[turbo_tasks::value_impl] impl NextConfigVc { #[turbo_tasks::function] @@ -539,19 +558,46 @@ impl NextConfigVc { } #[turbo_tasks::function] - pub async fn webpack_loaders_options(self) -> Result { + pub async fn webpack_rules(self) -> Result { let this = self.await?; - let Some(turbo_loaders) = this.experimental.turbo.as_ref().and_then(|t| t.loaders.as_ref()) else { - return Ok(WebpackExtensionToLoadersVc::cell(IndexMap::new())); + let Some(turbo_rules) = this.experimental.turbo.as_ref().and_then(|t| t.rules.as_ref()) else { + return Ok(OptionWebpackRulesVc::cell(None)); }; - let mut extension_to_loaders = IndexMap::new(); - for (ext, loaders) in turbo_loaders { - extension_to_loaders.insert( - ext.clone(), - WebpackLoaderConfigItemsVc::cell(loaders.0.clone()), - ); + if turbo_rules.is_empty() { + return Ok(OptionWebpackRulesVc::cell(None)); + } + let mut rules = IndexMap::new(); + for (ext, rule) in turbo_rules { + fn transform_loaders(loaders: &[LoaderItem]) -> WebpackLoaderItemsVc { + WebpackLoaderItemsVc::cell( + loaders + .iter() + .map(|item| match item { + LoaderItem::LoaderName(name) => WebpackLoaderItem { + loader: name.clone(), + options: Default::default(), + }, + LoaderItem::LoaderOptions(options) => options.clone(), + }) + .collect(), + ) + } + let rule = match rule { + RuleConfigItem::Loaders(loaders) => LoaderRuleItem { + loaders: transform_loaders(loaders), + rename_as: None, + }, + RuleConfigItem::Options { loaders, rename_as } => LoaderRuleItem { + loaders: transform_loaders(loaders), + rename_as: rename_as.clone(), + }, + }; + + rules.insert(ext.clone(), rule); } - Ok(WebpackExtensionToLoaders(extension_to_loaders).cell()) + Ok(OptionWebpackRulesVc::cell(Some(WebpackRulesVc::cell( + rules, + )))) } #[turbo_tasks::function] @@ -658,6 +704,23 @@ pub async fn load_next_config_internal( }; let next_config: NextConfig = parse_json_with_source_context(val.to_str()?)?; + if let Some(turbo) = next_config.experimental.turbo.as_ref() { + if turbo.loaders.is_some() { + OutdatedConfigIssue { + path: config_file.unwrap_or(project_path), + old_name: "experimental.turbo.loaders".to_string(), + new_name: "experimental.turbo.rules".to_string(), + description: "The new option is similar, but the key should be a glob instead of \ + an extension. +Example: loaders: { \".mdx\": [\"mdx-loader\"] } -> rules: { \"*.mdx\": [\"mdx-loader\"] }" + .to_string(), + } + .cell() + .as_issue() + .emit() + } + } + Ok(next_config.cell()) } @@ -668,3 +731,42 @@ pub async fn has_next_config(context: FileSystemPathVc) -> Result { FindContextFileResult::NotFound(_) ))) } + +#[turbo_tasks::value] +struct OutdatedConfigIssue { + path: FileSystemPathVc, + old_name: String, + new_name: String, + description: String, +} + +#[turbo_tasks::value_impl] +impl Issue for OutdatedConfigIssue { + #[turbo_tasks::function] + fn severity(&self) -> IssueSeverityVc { + IssueSeverity::Error.into() + } + + #[turbo_tasks::function] + fn category(&self) -> StringVc { + StringVc::cell("config".to_string()) + } + + #[turbo_tasks::function] + fn context(&self) -> FileSystemPathVc { + self.path + } + + #[turbo_tasks::function] + fn title(&self) -> StringVc { + StringVc::cell(format!( + "\"{}\" has been replaced by \"{}\"", + self.old_name, self.new_name + )) + } + + #[turbo_tasks::function] + fn description(&self) -> StringVc { + StringVc::cell(self.description.to_string()) + } +} diff --git a/packages/next-swc/crates/next-core/src/next_server/context.rs b/packages/next-swc/crates/next-core/src/next_server/context.rs index 2b33db3c8b793..beedcb31a7fee 100644 --- a/packages/next-swc/crates/next-core/src/next_server/context.rs +++ b/packages/next-swc/crates/next-core/src/next_server/context.rs @@ -284,22 +284,18 @@ pub async fn get_server_module_options_context( ..Default::default() }); - let enable_webpack_loaders = { - let options = &*next_config.webpack_loaders_options().await?; - let loaders_options = WebpackLoadersOptions { - extension_to_loaders: options.clone(), + let webpack_rules = + *maybe_add_babel_loader(project_path, *next_config.webpack_rules().await?).await?; + let webpack_rules = maybe_add_sass_loader(next_config.sass_config(), webpack_rules).await?; + let enable_webpack_loaders = webpack_rules.map(|rules| { + WebpackLoadersOptions { + rules, loader_runner_package: Some(get_external_next_compiled_package_mapping( StringVc::cell("loader-runner".to_owned()), )), - ..Default::default() } - .cell(); - - let loaders_options = maybe_add_babel_loader(project_path, loaders_options); - maybe_add_sass_loader(next_config.sass_config(), loaders_options) - .await? - .clone_if() - }; + .cell() + }); // EcmascriptTransformPlugins for custom transforms let styled_components_transform_plugin = diff --git a/packages/next-swc/crates/next-core/src/sass.rs b/packages/next-swc/crates/next-core/src/sass.rs index dc94291c83ff4..dbd4ee861975e 100644 --- a/packages/next-swc/crates/next-core/src/sass.rs +++ b/packages/next-swc/crates/next-core/src/sass.rs @@ -1,20 +1,27 @@ -use anyhow::Result; +use anyhow::{bail, Result}; use turbo_tasks::primitives::JsonValueVc; use turbopack_binding::turbopack::{ - node::transforms::webpack::{WebpackLoaderConfigItem, WebpackLoaderConfigItemsVc}, - turbopack::module_options::WebpackLoadersOptionsVc, + node::transforms::webpack::{WebpackLoaderItem, WebpackLoaderItemsVc}, + turbopack::module_options::{LoaderRuleItem, OptionWebpackRulesVc, WebpackRulesVc}, }; #[turbo_tasks::function] pub async fn maybe_add_sass_loader( sass_options: JsonValueVc, - webpack_options: WebpackLoadersOptionsVc, -) -> Result { - let mut options = (*webpack_options.await?).clone(); - - let sass_options = sass_options.await?.as_object().unwrap().clone(); - for ext in [".scss", ".sass"] { - let loader = WebpackLoaderConfigItem::LoaderNameWithOptions { + webpack_rules: Option, +) -> Result { + let sass_options = sass_options.await?; + let Some(sass_options) = sass_options.as_object() else { + bail!("sass_options must be an object"); + }; + let mut rules = if let Some(webpack_rules) = webpack_rules { + webpack_rules.await?.clone_value() + } else { + Default::default() + }; + for pattern in ["*.scss", "*.sass"] { + let rule = rules.get_mut(pattern); + let loader = WebpackLoaderItem { loader: "next/dist/compiled/sass-loader".to_string(), options: serde_json::json!({ //https://github.com/vercel/turbo/blob/d527eb54be384a4658243304cecd547d09c05c6b/crates/turbopack-node/src/transforms/webpack.rs#L191 @@ -26,17 +33,22 @@ pub async fn maybe_add_sass_loader( .clone(), }; - options.extension_to_loaders.insert( - ext.to_owned(), - if options.extension_to_loaders.contains_key(ext) { - let mut new_configs = (*(options.extension_to_loaders[ext].await?)).clone(); - new_configs.push(loader); - WebpackLoaderConfigItemsVc::cell(new_configs) - } else { - WebpackLoaderConfigItemsVc::cell(vec![loader]) - }, - ); + if let Some(rule) = rule { + let mut loaders = rule.loaders.await?.clone_value(); + loaders.push(loader); + rule.loaders = WebpackLoaderItemsVc::cell(loaders); + } else { + rules.insert( + pattern.to_string(), + LoaderRuleItem { + loaders: WebpackLoaderItemsVc::cell(vec![loader]), + rename_as: Some("*".to_string()), + }, + ); + } } - Ok(options.cell()) + Ok(OptionWebpackRulesVc::cell(Some(WebpackRulesVc::cell( + rules, + )))) } diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/input/next.config.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/input/next.config.js new file mode 100644 index 0000000000000..c57d50163ebef --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/input/next.config.js @@ -0,0 +1,11 @@ +module.exports = { + experimental: { + turbo: { + loaders: { + '.replace': [ + { loader: 'replace-loader', options: { defaultExport: 3 } }, + ], + }, + }, + }, +} diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/input/pages/index.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/input/pages/index.js new file mode 100644 index 0000000000000..060471b4b1508 --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/input/pages/index.js @@ -0,0 +1,11 @@ +import { useTestHarness } from '@turbo/pack-test-harness' + +export default function Home() { + useTestHarness(runTests) + + return null +} + +function runTests() { + it('run', () => {}) +} diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/issues/__quo__experimental.turbo.loaders__quo__ has been -391244.txt b/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/issues/__quo__experimental.turbo.loaders__quo__ has been -391244.txt new file mode 100644 index 0000000000000..610c77113dd3b --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/error/webpack-loaders/issues/__quo__experimental.turbo.loaders__quo__ has been -391244.txt @@ -0,0 +1,21 @@ +PlainIssue { + severity: Error, + context: "[project]/packages/next-swc/crates/next-dev-tests/tests/temp/next/error/webpack-loaders/input/next.config.js", + category: "config", + title: "\"experimental.turbo.loaders\" has been replaced by \"experimental.turbo.rules\"", + description: "The new option is similar, but the key should be a glob instead of an extension.\nExample: loaders: { \".mdx\": [\"mdx-loader\"] } -> rules: { \"*.mdx\": [\"mdx-loader\"] }", + detail: "", + documentation_link: "", + source: None, + sub_issues: [], + processing_path: Some( + [ + PlainIssueProcessingPathItem { + context: Some( + "[project]/packages/next-swc/crates/next-dev-tests/tests/temp/next/error/webpack-loaders/input/next.config.js", + ), + description: "Loading Next.js config", + }, + ], + ), +} \ No newline at end of file diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/next.config.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/next.config.js index c57d50163ebef..34e8968264d87 100644 --- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/next.config.js +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/basic-options/input/next.config.js @@ -1,8 +1,8 @@ module.exports = { experimental: { turbo: { - loaders: { - '.replace': [ + rules: { + '*.replace': [ { loader: 'replace-loader', options: { defaultExport: 3 } }, ], }, diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/emitted-errors/input/next.config.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/emitted-errors/input/next.config.js index 0e34aefe9786c..73a765218b60a 100644 --- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/emitted-errors/input/next.config.js +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/emitted-errors/input/next.config.js @@ -1,8 +1,8 @@ module.exports = { experimental: { turbo: { - loaders: { - '.emit': ['emit-loader'], + rules: { + '*.emit': ['emit-loader'], }, }, }, diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/next.config.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/next.config.js index feacb3f1225b8..06335a9f19315 100644 --- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/next.config.js +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/next.config.js @@ -1,8 +1,17 @@ module.exports = { experimental: { turbo: { - loaders: { - '.raw': ['raw-loader'], + rules: { + '*.raw.*': { + loaders: ['raw-loader'], + as: '*', + }, + '*.raw': ['raw-loader'], + '*.jraw': { + loaders: ['raw-as-json-loader'], + as: '*.json', + }, + './raw/**': ['raw-loader'], }, }, }, diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/node_modules/raw-as-json-loader/index.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/node_modules/raw-as-json-loader/index.js new file mode 100644 index 0000000000000..422794b59f718 --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/node_modules/raw-as-json-loader/index.js @@ -0,0 +1,3 @@ +module.exports = async (source) => { + return `${JSON.stringify(source.trim())}` +} diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.jraw b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.jraw new file mode 100644 index 0000000000000..557db03de997c --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.jraw @@ -0,0 +1 @@ +Hello World diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw.js new file mode 100644 index 0000000000000..557db03de997c --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw.js @@ -0,0 +1 @@ +Hello World diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw.raw b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw.raw new file mode 100644 index 0000000000000..557db03de997c --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/hello.raw.raw @@ -0,0 +1 @@ +Hello World diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js index eaacde5849404..076829d80674a 100644 --- a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/pages/index.js @@ -1,5 +1,9 @@ import { useTestHarness } from '@turbo/pack-test-harness' -import source from './hello.raw' +import source1 from './hello.raw' +import source2 from '../raw/hello.js' +import source3 from './hello.raw.raw' +import source4 from './hello.raw.js' +import source5 from './hello.jraw' export default function Home() { useTestHarness(runTests) @@ -9,6 +13,18 @@ export default function Home() { function runTests() { it('runs a simple loader', () => { - expect(source).toBe('Hello World') + expect(source1).toBe('Hello World') + }) + it('runs a loader matching relative path glob', () => { + expect(source2).toBe('}}} Hello World') + }) + it('runs a loader with "as" continue (to other match)', () => { + expect(source3).toBe('export default "Hello World";') + }) + it('runs a loader with "as" continue (to default js match)', () => { + expect(source4).toBe('Hello World') + }) + it('runs a loader with "as" to builtin type', () => { + expect(source5).toBe('Hello World') }) } diff --git a/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/raw/hello.js b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/raw/hello.js new file mode 100644 index 0000000000000..1b617ed34e23e --- /dev/null +++ b/packages/next-swc/crates/next-dev-tests/tests/integration/next/webpack-loaders/no-options/input/raw/hello.js @@ -0,0 +1 @@ +}}} Hello World \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d84871787150..9826ac9335499 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1012,8 +1012,8 @@ importers: '@types/react': 18.2.5 '@types/react-dom': 18.2.3 '@vercel/ncc': ^0.36.0 - '@vercel/turbopack-dev': https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230522.2 - '@vercel/turbopack-node': https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230522.2 + '@vercel/turbopack-dev': https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230523.2 + '@vercel/turbopack-node': https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230523.2 anser: ^2.1.1 css.escape: ^1.5.1 find-up: ^6.3.0 @@ -1025,8 +1025,8 @@ importers: stacktrace-parser: ^0.1.10 strip-ansi: ^7.0.1 dependencies: - '@vercel/turbopack-dev': '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230522.2_react-refresh@0.12.0' - '@vercel/turbopack-node': '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230522.2' + '@vercel/turbopack-dev': '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230523.2_react-refresh@0.12.0' + '@vercel/turbopack-node': '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230523.2' anser: 2.1.1 css.escape: 1.5.1 next: link:../../../../next @@ -25490,9 +25490,9 @@ packages: /zwitch/2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230522.2_react-refresh@0.12.0': - resolution: {tarball: https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230522.2} - id: '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230522.2' + '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230523.2_react-refresh@0.12.0': + resolution: {tarball: https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230523.2} + id: '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-dev/js?turbopack-230523.2' name: '@vercel/turbopack-dev' version: 0.0.0 dependencies: @@ -25502,8 +25502,8 @@ packages: - webpack dev: false - '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230522.2': - resolution: {tarball: https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230522.2} + '@gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230523.2': + resolution: {tarball: https://gitpkg.vercel.app/vercel/turbo/crates/turbopack-node/js?turbopack-230523.2} name: '@vercel/turbopack-node' version: 0.0.0 dependencies: