Skip to content

Commit 338f80b

Browse files
authored
fix empty externals list, pnpm special case, and project path (#56402)
### What? * node.js doesn't allow module requests starting with `.` since node.js 18, so we need to remove out .pnpm special case * externals should be resolvable from the project dir instead of the root dir * fix a problem when the list of externals is empty ### Why? ### How? Closes WEB-1703
1 parent a278e94 commit 338f80b

File tree

2 files changed

+38
-36
lines changed

2 files changed

+38
-36
lines changed

packages/next-swc/crates/next-core/src/next_server/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub async fn get_server_resolve_options_context(
109109
let unsupported_modules_resolve_plugin = UnsupportedModulesResolvePlugin::new(project_path);
110110
let server_component_externals_plugin = ExternalCjsModulesResolvePlugin::new(
111111
project_path,
112+
project_path.root(),
112113
ExternalPredicate::Only(next_config.server_component_externals()).cell(),
113114
);
114115
let ty = ty.into_value();
@@ -125,6 +126,7 @@ pub async fn get_server_resolve_options_context(
125126
};
126127
let external_cjs_modules_plugin = ExternalCjsModulesResolvePlugin::new(
127128
project_path,
129+
project_path.root(),
128130
ExternalPredicate::AllExcept(next_config.transpile_packages()).cell(),
129131
);
130132

packages/next-swc/crates/next-core/src/next_server/resolve.rs

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use anyhow::Result;
2-
use once_cell::sync::Lazy;
3-
use regex::Regex;
42
use turbo_tasks::Vc;
53
use turbopack_binding::{
64
turbo::tasks_fs::{glob::Glob, FileJsonContent, FileSystemPath},
@@ -33,15 +31,25 @@ pub enum ExternalPredicate {
3331
/// possible to resolve them at runtime.
3432
#[turbo_tasks::value]
3533
pub(crate) struct ExternalCjsModulesResolvePlugin {
34+
project_path: Vc<FileSystemPath>,
3635
root: Vc<FileSystemPath>,
3736
predicate: Vc<ExternalPredicate>,
3837
}
3938

4039
#[turbo_tasks::value_impl]
4140
impl ExternalCjsModulesResolvePlugin {
4241
#[turbo_tasks::function]
43-
pub fn new(root: Vc<FileSystemPath>, predicate: Vc<ExternalPredicate>) -> Vc<Self> {
44-
ExternalCjsModulesResolvePlugin { root, predicate }.cell()
42+
pub fn new(
43+
project_path: Vc<FileSystemPath>,
44+
root: Vc<FileSystemPath>,
45+
predicate: Vc<ExternalPredicate>,
46+
) -> Vc<Self> {
47+
ExternalCjsModulesResolvePlugin {
48+
project_path,
49+
root,
50+
predicate,
51+
}
52+
.cell()
4553
}
4654
}
4755

@@ -66,11 +74,9 @@ async fn is_node_resolveable(
6674
Ok(Vc::cell(true))
6775
}
6876

69-
static PNPM: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?:/|^)node_modules/(.pnpm/.+)").unwrap());
70-
7177
#[turbo_tasks::function]
7278
fn condition(root: Vc<FileSystemPath>) -> Vc<ResolvePluginCondition> {
73-
ResolvePluginCondition::new(root.root(), Glob::new("**/node_modules/**".to_string()))
79+
ResolvePluginCondition::new(root, Glob::new("**/node_modules/**".to_string()))
7480
}
7581

7682
#[turbo_tasks::value_impl]
@@ -101,14 +107,20 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
101107
ExternalPredicate::AllExcept(exceptions) => {
102108
let exception_glob = packages_glob(*exceptions).await?;
103109

104-
if exception_glob.execute(&raw_fs_path.path) {
105-
return Ok(ResolveResultOption::none());
110+
if let Some(exception_glob) = *exception_glob {
111+
if exception_glob.await?.execute(&raw_fs_path.path) {
112+
return Ok(ResolveResultOption::none());
113+
}
106114
}
107115
}
108116
ExternalPredicate::Only(externals) => {
109117
let external_glob = packages_glob(*externals).await?;
110118

111-
if !external_glob.execute(&raw_fs_path.path) {
119+
if let Some(external_glob) = *external_glob {
120+
if !external_glob.await?.execute(&raw_fs_path.path) {
121+
return Ok(ResolveResultOption::none());
122+
}
123+
} else {
112124
return Ok(ResolveResultOption::none());
113125
}
114126
}
@@ -141,42 +153,30 @@ impl ResolvePlugin for ExternalCjsModulesResolvePlugin {
141153

142154
// check if we can resolve the package from the project dir with node.js resolve
143155
// options (might be hidden by pnpm)
144-
if *is_node_resolveable(self.root.root(), request, fs_path).await? {
156+
if *is_node_resolveable(self.project_path, request, fs_path).await? {
145157
// mark as external
146158
return Ok(ResolveResultOption::some(
147159
ResolveResult::primary(ResolveResultItem::OriginalReferenceExternal).cell(),
148160
));
149161
}
150162

151-
// Special behavior for pnpm as we could reference all .pnpm modules by
152-
// referencing the `.pnpm` folder as module, e. g.
153-
// /node_modules/.pnpm/[email protected]/node_modules/some-package/dir/file.js
154-
// becomes
155-
// .pnpm/[email protected]/node_modules/some-package/dir/file.js
156-
if let Some(captures) = PNPM.captures(&fs_path.await?.path) {
157-
if let Some(import_path) = captures.get(1) {
158-
// we could load it directly as external, but we want to make sure node.js would
159-
// resolve it the same way e. g. that we didn't follow any special resolve
160-
// options, to come here like the `module` field in package.json
161-
if *is_node_resolveable(context, request, fs_path).await? {
162-
// mark as external
163-
return Ok(ResolveResultOption::some(
164-
ResolveResult::primary(ResolveResultItem::OriginalReferenceTypeExternal(
165-
import_path.as_str().to_string(),
166-
))
167-
.cell(),
168-
));
169-
}
170-
}
171-
}
172163
Ok(ResolveResultOption::none())
173164
}
174165
}
175166

167+
// TODO move that to turbo
168+
#[turbo_tasks::value(transparent)]
169+
pub struct OptionGlob(Option<Vc<Glob>>);
170+
176171
#[turbo_tasks::function]
177-
async fn packages_glob(packages: Vc<Vec<String>>) -> Result<Vc<Glob>> {
178-
Ok(Glob::new(format!(
179-
"**/node_modules/{{{}}}/**",
180-
packages.await?.join(",")
172+
async fn packages_glob(packages: Vc<Vec<String>>) -> Result<Vc<OptionGlob>> {
173+
let packages = packages.await?;
174+
if packages.is_empty() {
175+
return Ok(Vc::cell(None));
176+
}
177+
Ok(Vc::cell(Some(
178+
Glob::new(format!("**/node_modules/{{{}}}/**", packages.join(",")))
179+
.resolve()
180+
.await?,
181181
)))
182182
}

0 commit comments

Comments
 (0)