Repository: vercel/next.js
Pull request: Turbopack: query conditions in rules follow-ups

Rebase of https://github.com/vercel/next.js/pull/87291

Changed files:
filename: crates/next-core/src/next_config.rs
patch: @@ -2106,6 +2106,13 @@ mod tests {
                         "browser",
                         {
                             "path": { "type": "glob", "value": "*.svg"},
+                            "query": {
+                                "type": "regex",
+                                "value": {
+                                    "source": "@someQuery",
+                                    "flags": ""
+                                }
+                            },
                             "content": {
                                 "source": "@someTag",
                                 "flags": ""
@@ -2140,7 +2147,10 @@ mod tests {
                                         source: rcstr!("@someTag"),
                                         flags: rcstr!(""),
                                     }),
-                                    query: None,
+                                    query: Some(ConfigConditionQuery::Regex(RegexComponents {
+                                        source: rcstr!("@someQuery"),
+                                        flags: rcstr!(""),
+                                    })),
                                 },
                             ]
                             .into(),

filename: docs/01-app/03-api-reference/05-config/01-next-config-js/turbopack.mdx
patch: @@ -197,6 +197,9 @@ module.exports = {
             {
               any: [
                 { path: '*.svg' },
+                // 'query' matches anywhere in the full query string,
+                // which can be empty, or start with `?`.
+                { query: /[?&]svgr(?=&|$)/ },
                 // 'content' is always a RegExp, and can match
                 // anywhere in the file.
                 { content: /\<svg\W/ },

filename: test/e2e/turbopack-loader-config/app/api/route.ts
patch: @@ -1,6 +1,7 @@
 import { NextResponse } from 'next/server'
 import foo from '../../foo.js'
-import bar from '../../bar.js'
+// @ts-expect-error -- ignore
+import bar from '../../bar.js?test=hi'
 
 export async function GET(_req) {
   return NextResponse.json(

filename: test/e2e/turbopack-loader-config/next.config.ts
patch: @@ -35,7 +35,10 @@ export default {
           condition: {
             any: [
               {
-                all: ['development', { not: { not: { content: /export/ } } }],
+                all: [
+                  'development',
+                  { not: { not: { query: /test=hi/, content: /export/ } } },
+                ],
               },
             ],
           },
@@ -49,7 +52,10 @@ export default {
         // this should match on production
         {
           condition: {
-            all: [{ not: 'development' }, { content: /export/ }],
+            all: [
+              { not: 'development' },
+              { query: /test=hi/, content: /export/ },
+            ],
           },
           loaders: [
             {

filename: turbopack/crates/turbopack/src/module_options/mod.rs
patch: @@ -132,9 +132,6 @@ async fn rule_condition_from_webpack_condition(
                 }
                 None => {}
             }
-            if let Some(content) = content {
-                rule_conditions.push(RuleCondition::ResourceContentEsRegex(content.await?));
-            }
             match &query {
                 Some(ConditionQuery::Constant(value)) => {
                     rule_conditions.push(RuleCondition::ResourceQueryEquals(value.clone().into()));
@@ -144,6 +141,10 @@ async fn rule_condition_from_webpack_condition(
                 }
                 None => {}
             }
+            // Add the content condition last since matching requires a more expensive file read.
+            if let Some(content) = content {
+                rule_conditions.push(RuleCondition::ResourceContentEsRegex(content.await?));
+            }
             RuleCondition::All(rule_conditions)
         }
     })