@@ -300,6 +300,67 @@ pub enum ParseSegmentMode {
300
300
App ,
301
301
}
302
302
303
+ /// Parse the raw source code of a file to get the segment config local to that file.
304
+ ///
305
+ /// See [the Next.js documentation for Route Segment
306
+ /// Configs](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config).
307
+ ///
308
+ /// Pages router and middleware use this directly. App router uses
309
+ /// `parse_segment_config_from_loader_tree` instead, which aggregates configuration information
310
+ /// across multiple files.
311
+ ///
312
+ /// ## A Note on Parsing the Raw Source Code
313
+ ///
314
+ /// A better API would use `ModuleAssetContext::process` to convert the `Source` to a `Module`,
315
+ /// instead of parsing the raw source code. That would ensure that things like webpack loaders can
316
+ /// run before SWC tries to parse the file, e.g. to strip unsupported syntax using Babel. However,
317
+ /// because the config includes `runtime`, we can't know which context to use until after parsing
318
+ /// the file.
319
+ ///
320
+ /// This could be solved with speculative parsing:
321
+ /// 1. Speculatively process files and extract route segment configs using the Node.js
322
+ /// `ModuleAssetContext` first. This is the common/happy codepath.
323
+ /// 2. If we get a config specifying `runtime = "edge"`, we should use the Edge runtime's
324
+ /// `ModuleAssetContext` and re-process the file(s), extracting the segment config again.
325
+ /// 3. If we failed to get a configuration (e.g. a parse error), we need speculatively process with
326
+ /// the Edge runtime and look for a `runtime = "edge"` configuration key. If that also fails,
327
+ /// then we should report any issues/errors from the first attempt using the Node.js context.
328
+ ///
329
+ /// While a speculative parsing algorithm is straightforward, there are a few factors that make it
330
+ /// impractical to implement:
331
+ ///
332
+ /// - The app router config is loaded across many different files (page, layout, or route handler,
333
+ /// including an arbitrary number of those files in parallel routes), and once we discover that
334
+ /// something specified edge runtime, we must restart that entire loop, so try/reparse logic can't
335
+ /// be cleanly encapsulated to an operation over a single file.
336
+ ///
337
+ /// - There's a lot of tracking that needs to happen to later suppress `Issue` collectibles on
338
+ /// speculatively-executed `OperationVc`s.
339
+ ///
340
+ /// - Most things default to the node.js runtime and can be overridden to edge runtime, but
341
+ /// middleware is an exception, so different codepaths have different defaults.
342
+ ///
343
+ /// The `runtime` option is going to be deprecated, and we may eventually remove edge runtime
344
+ /// completely (in Next 18?), so it doesn't make sense to spend a ton of time improving logic around
345
+ /// that. In the future, doing this the right way with the `ModuleAssetContext` will be easy (there
346
+ /// will only be one, no speculative parsing is needed), and I think it's okay to use a hacky
347
+ /// solution for a couple years until that day comes.
348
+ ///
349
+ /// ## What does webpack do?
350
+ ///
351
+ /// The logic is in `packages/next/src/build/analysis/get-page-static-info.ts`, but it's very
352
+ /// similar to what we do here.
353
+ ///
354
+ /// There are a couple of notable differences:
355
+ ///
356
+ /// - The webpack implementation uses a regexp (`PARSE_PATTERN`) to skip parsing some files, but
357
+ /// this regexp is imperfect and may also suppress some lints that we have. The performance
358
+ /// benefit is small, so we're not currently doing this (but we could revisit that decision in the
359
+ /// future).
360
+ ///
361
+ /// - The `parseModule` helper function swallows errors (!) returning a `null` ast value when
362
+ /// parsing fails. This seems bad, as it may lead to silently-ignored segment configs, so we don't
363
+ /// want to do this.
303
364
#[ turbo_tasks:: function]
304
365
pub async fn parse_segment_config_from_source (
305
366
source : ResolvedVc < Box < dyn Source > > ,
@@ -1229,6 +1290,8 @@ async fn parse_route_matcher_from_js_value(
1229
1290
} )
1230
1291
}
1231
1292
1293
+ /// A wrapper around [`parse_segment_config_from_source`] that merges route segment configuration
1294
+ /// information from all relevant files (page, layout, parallel routes, etc).
1232
1295
#[ turbo_tasks:: function]
1233
1296
pub async fn parse_segment_config_from_loader_tree (
1234
1297
loader_tree : Vc < AppPageLoaderTree > ,
0 commit comments