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 8975d5f971..6c42c4938a 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 @@ -127,6 +127,7 @@ pub async fn get_client_module_options_context( postcss_package: Some(get_postcss_package_mapping(project_path)), ..Default::default() }), + enable_webpack_loaders: next_config.webpack_loaders_options().await?.clone_if(), enable_typescript_transform: true, rules: vec![( foreign_code_context_condition(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 e909d284cd..045de6ea28 100644 --- a/packages/next-swc/crates/next-core/src/next_config.rs +++ b/packages/next-swc/crates/next-core/src/next_config.rs @@ -1,13 +1,17 @@ use std::collections::HashMap; use anyhow::Result; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use turbo_tasks::{ primitives::{BoolVc, StringsVc}, trace::TraceRawVcs, Value, }; -use turbopack::evaluate_context::node_evaluate_asset_context; +use turbopack::{ + evaluate_context::node_evaluate_asset_context, + module_options::{WebpackLoadersOptions, WebpackLoadersOptionsVc}, +}; use turbopack_core::{ asset::Asset, reference_type::{EntryReferenceSubType, ReferenceType}, @@ -127,11 +131,12 @@ pub enum RemotePatternProtocal { Https, } -#[derive(Clone, Debug, Ord, PartialOrd, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] #[serde(rename_all = "camelCase")] pub struct ExperimentalConfig { pub server_components_external_packages: Option>, pub app_dir: Option, + pub turbopack_webpack_loaders: Option>>, } #[derive(Clone, Debug, Ord, PartialOrd, PartialEq, Eq, Serialize, Deserialize, TraceRawVcs)] @@ -209,6 +214,23 @@ impl NextConfigVc { self.await?.transpile_packages.clone().unwrap_or_default(), )) } + + #[turbo_tasks::function] + pub async fn webpack_loaders_options(self) -> Result { + let this = self.await?; + let Some(turbopack_webpack_loaders) = this.experimental.as_ref().and_then(|experimental| experimental.turbopack_webpack_loaders.as_ref()) else { + return Ok(WebpackLoadersOptionsVc::cell(WebpackLoadersOptions::default())); + }; + let mut extension_to_loaders = IndexMap::new(); + for (ext, loaders) in turbopack_webpack_loaders { + extension_to_loaders.insert(ext.clone(), StringsVc::cell(loaders.clone())); + } + Ok(WebpackLoadersOptions { + extension_to_loaders, + ..Default::default() + } + .cell()) + } } fn next_configs() -> StringsVc { 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 a3ea72b459..5ff5eaab15 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 @@ -118,6 +118,7 @@ pub async fn get_server_module_options_context( postcss_package: Some(get_postcss_package_mapping(project_path)), ..Default::default() }), + enable_webpack_loaders: next_config.webpack_loaders_options().await?.clone_if(), enable_typescript_transform: true, rules: vec![( foreign_code_context_condition(next_config).await?, @@ -138,6 +139,7 @@ pub async fn get_server_module_options_context( postcss_package: Some(get_postcss_package_mapping(project_path)), ..Default::default() }), + enable_webpack_loaders: next_config.webpack_loaders_options().await?.clone_if(), enable_typescript_transform: true, rules: vec![( foreign_code_context_condition(next_config).await?, @@ -160,6 +162,7 @@ pub async fn get_server_module_options_context( postcss_package: Some(get_postcss_package_mapping(project_path)), ..Default::default() }), + enable_webpack_loaders: next_config.webpack_loaders_options().await?.clone_if(), enable_typescript_transform: true, rules: vec![( foreign_code_context_condition(next_config).await?, diff --git a/packages/next-swc/crates/next-dev/src/lib.rs b/packages/next-swc/crates/next-dev/src/lib.rs index 2bd022da4e..4c5ddc3328 100644 --- a/packages/next-swc/crates/next-dev/src/lib.rs +++ b/packages/next-swc/crates/next-dev/src/lib.rs @@ -35,9 +35,9 @@ use turbopack_core::{ environment::ServerAddr, issue::IssueSeverity, resolve::{parse::RequestVc, pattern::QueryMapVc}, + server_fs::ServerFileSystemVc, }; use turbopack_dev_server::{ - fs::DevServerFileSystemVc, introspect::IntrospectionSource, source::{ combined::CombinedContentSourceVc, router::RouterContentSource, @@ -279,7 +279,7 @@ async fn source( let output_root = output_fs.root().join(".next/server"); let server_addr = ServerAddr::new(*server_addr).cell(); - let dev_server_fs = DevServerFileSystemVc::new().as_file_system(); + let dev_server_fs = ServerFileSystemVc::new().as_file_system(); let dev_server_root = dev_server_fs.root(); let entry_requests = entry_requests .iter() diff --git a/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/hello.raw b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/hello.raw new file mode 100644 index 0000000000..557db03de9 --- /dev/null +++ b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/hello.raw @@ -0,0 +1 @@ +Hello World diff --git a/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/index.js b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/index.js new file mode 100644 index 0000000000..400c55352f --- /dev/null +++ b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/index.js @@ -0,0 +1,5 @@ +import source from "./hello.raw"; + +it("runs a simple loader", () => { + expect(source).toBe("Hello World"); +}); diff --git a/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/next.config.js b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/next.config.js new file mode 100644 index 0000000000..2eee3650ef --- /dev/null +++ b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/next.config.js @@ -0,0 +1,7 @@ +module.exports = { + experimental: { + turbopackWebpackLoaders: { + ".raw": ["raw-loader"], + }, + }, +}; diff --git a/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/node_modules/raw-loader/index.js b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/node_modules/raw-loader/index.js new file mode 100644 index 0000000000..a2cae480a2 --- /dev/null +++ b/packages/next-swc/crates/next-dev/tests/integration/turbopack/basic/webpack-loaders/node_modules/raw-loader/index.js @@ -0,0 +1,3 @@ +module.exports = async (source) => { + return `export default ${JSON.stringify(source.trim())};` +} diff --git a/packages/next-swc/crates/next-dev/tests/package.json b/packages/next-swc/crates/next-dev/tests/package.json index 62a64317cd..33861764b5 100644 --- a/packages/next-swc/crates/next-dev/tests/package.json +++ b/packages/next-swc/crates/next-dev/tests/package.json @@ -4,11 +4,12 @@ "devDependencies": { "@turbo/pack-test-harness": "*", "autoprefixer": "^10.4.13", + "loader-runner": "^4.3.0", "next": "13.0.8-canary.2", "postcss": "^8.4.20", - "react": "^18.2.0", "react-dom": "^18.2.0", "react-test-renderer": "^18.2.0", + "react": "^18.2.0", "styled-jsx": "^5.1.0", "tailwindcss": "^3.2.4" }