Repository: vercel/next.js
Pull request: feat(turbopack): add resolve plugin condition variant of Always and Never

This PR refactors the Resolution Plugin traits to add new `Always` or `Never` enum variants to `resolve condition`. This allow plugins (like [ExternalsPlugin](https://github.com/utooland/utoo/pull/2494) when no externals are configured) to skip the expensive `matches()` task calls entirely. Testing on a medium project showed a reduction of ~1.4k `resolve_call` tasks. I think this can be shared to upstream for future improvement of `resolve plugin`

See the metrics for improvements.
<img width="1400" height="600" alt="image" src="https://github.com/user-attachments/assets/06eae96e-070a-43c3-9f68-a3a27ee7dc0d" />



Changed files:
filename: crates/next-core/src/next_server/resolve.rs
patch: @@ -65,7 +65,7 @@ impl ExternalCjsModulesResolvePlugin {
 
 #[turbo_tasks::function]
 fn condition(root: FileSystemPath) -> Vc<AfterResolvePluginCondition> {
-    AfterResolvePluginCondition::new(
+    AfterResolvePluginCondition::new_with_glob(
         root,
         Glob::new(rcstr!("**/node_modules/**"), GlobOptions::default()),
     )

filename: crates/next-core/src/next_shared/resolve.rs
patch: @@ -224,7 +224,7 @@ impl NextExternalResolvePlugin {
 impl AfterResolvePlugin for NextExternalResolvePlugin {
     #[turbo_tasks::function]
     async fn after_resolve_condition(&self) -> Result<Vc<AfterResolvePluginCondition>> {
-        Ok(AfterResolvePluginCondition::new(
+        Ok(AfterResolvePluginCondition::new_with_glob(
             self.project_path.root().owned().await?,
             Glob::new(
                 rcstr!("**/next/dist/**/*.{external,runtime.dev,runtime.prod}.js"),
@@ -282,7 +282,7 @@ impl NextNodeSharedRuntimeResolvePlugin {
 impl AfterResolvePlugin for NextNodeSharedRuntimeResolvePlugin {
     #[turbo_tasks::function]
     async fn after_resolve_condition(&self) -> Result<Vc<AfterResolvePluginCondition>> {
-        Ok(AfterResolvePluginCondition::new(
+        Ok(AfterResolvePluginCondition::new_with_glob(
             self.root.root().owned().await?,
             Glob::new(
                 rcstr!("**/next/dist/**/*.shared-runtime.js"),
@@ -410,7 +410,7 @@ impl NextSharedRuntimeResolvePlugin {
 impl AfterResolvePlugin for NextSharedRuntimeResolvePlugin {
     #[turbo_tasks::function]
     async fn after_resolve_condition(&self) -> Result<Vc<AfterResolvePluginCondition>> {
-        Ok(AfterResolvePluginCondition::new(
+        Ok(AfterResolvePluginCondition::new_with_glob(
             self.root.root().owned().await?,
             Glob::new(
                 rcstr!("**/next/dist/esm/**/*.shared-runtime.js"),

filename: turbopack/crates/turbopack-core/src/resolve/plugin.rs
patch: @@ -10,41 +10,53 @@ use crate::{
 };
 
 /// A condition which determines if the hooks of a resolve plugin gets called.
-#[turbo_tasks::value]
-pub struct AfterResolvePluginCondition {
-    root: FileSystemPath,
-    glob: ResolvedVc<Glob>,
+#[turbo_tasks::value(shared)]
+pub enum AfterResolvePluginCondition {
+    Glob {
+        root: FileSystemPath,
+        glob: ResolvedVc<Glob>,
+    },
+    Always,
+    Never,
 }
 
 #[turbo_tasks::value_impl]
 impl AfterResolvePluginCondition {
     #[turbo_tasks::function]
-    pub fn new(root: FileSystemPath, glob: ResolvedVc<Glob>) -> Vc<Self> {
-        AfterResolvePluginCondition { root, glob }.cell()
+    pub fn new_with_glob(root: FileSystemPath, glob: ResolvedVc<Glob>) -> Vc<Self> {
+        AfterResolvePluginCondition::Glob { root, glob }.cell()
     }
+}
 
+#[turbo_tasks::value_impl]
+impl AfterResolvePluginCondition {
     #[turbo_tasks::function]
     pub async fn matches(&self, fs_path: FileSystemPath) -> Result<Vc<bool>> {
-        let root = self.root.clone();
-        let glob = self.glob.await?;
+        match self {
+            AfterResolvePluginCondition::Glob { root, glob } => {
+                let path = fs_path;
 
-        let path = fs_path;
+                if let Some(path) = root.get_path_to(&path)
+                    && glob.await?.matches(path)
+                {
+                    return Ok(Vc::cell(true));
+                }
 
-        if let Some(path) = root.get_path_to(&path)
-            && glob.matches(path)
-        {
-            return Ok(Vc::cell(true));
+                Ok(Vc::cell(false))
+            }
+            AfterResolvePluginCondition::Always => Ok(Vc::cell(true)),
+            AfterResolvePluginCondition::Never => Ok(Vc::cell(false)),
         }
-
-        Ok(Vc::cell(false))
     }
 }
 
 /// A condition which determines if the hooks of a resolve plugin gets called.
-#[turbo_tasks::value]
+#[turbo_tasks::value(shared)]
 pub enum BeforeResolvePluginCondition {
     Request(ResolvedVc<Glob>),
     Modules(FxHashSet<RcStr>),
+    Always,
+    Never,
 }
 
 #[turbo_tasks::value_impl]
@@ -76,6 +88,8 @@ impl BeforeResolvePluginCondition {
                     false
                 }
             }
+            BeforeResolvePluginCondition::Always => true,
+            BeforeResolvePluginCondition::Never => false,
         }))
     }
 }