Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/next-api/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,7 @@ impl Project {
.next_config()
.turbo_nested_async_chunking(self.next_mode(), true),
debug_ids: self.next_config().turbopack_debug_ids(),
worker_asset_prefix: self.next_config().turbopack_worker_asset_prefix(),
should_use_absolute_url_references: self.next_config().inline_css(),
css_url_suffix,
hash_salt: self.next_config().output_hash_salt().to_resolved().await?,
Expand Down
3 changes: 3 additions & 0 deletions crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ pub struct ClientChunkingContextOptions {
pub scope_hoisting: Vc<bool>,
pub nested_async_chunking: Vc<bool>,
pub debug_ids: Vc<bool>,
pub worker_asset_prefix: Vc<Option<RcStr>>,
pub should_use_absolute_url_references: Vc<bool>,
pub css_url_suffix: Vc<Option<RcStr>>,
pub hash_salt: ResolvedVc<RcStr>,
Expand Down Expand Up @@ -504,6 +505,7 @@ pub async fn get_client_chunking_context(
scope_hoisting,
nested_async_chunking,
debug_ids,
worker_asset_prefix,
should_use_absolute_url_references,
css_url_suffix,
hash_salt,
Expand Down Expand Up @@ -544,6 +546,7 @@ pub async fn get_client_chunking_context(
.unused_references(unused_references.to_resolved().await?)
.module_id_strategy(module_id_strategy.to_resolved().await?)
.debug_ids(*debug_ids.await?)
.worker_asset_prefix(worker_asset_prefix.owned().await?)
.should_use_absolute_url_references(*should_use_absolute_url_references.await?)
.nested_async_availability(*nested_async_chunking.await?)
.worker_forwarded_globals(worker_forwarded_globals())
Expand Down
23 changes: 23 additions & 0 deletions crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,17 @@ pub struct ExperimentalConfig {
turbopack_input_source_maps: Option<bool>,
turbopack_tree_shaking: Option<bool>,
turbopack_scope_hoisting: Option<bool>,
/// Custom URL prefix for Web Worker URLs (the entrypoint and the module
/// chunks loaded inside the worker) produced by
/// `new Worker(new URL(..., import.meta.url))`. Mirrors webpack's
/// `output.workerPublicPath`. When unset, Worker URLs use the regular
/// chunk base path (i.e. `assetPrefix` + `/_next/`).
///
/// Like `assetPrefix`, the value is a prefix without a trailing slash
/// and without `/_next` — `/_next/` is appended automatically. An empty
/// string is a literal empty prefix; only `None` falls back to
/// `assetPrefix`.
turbopack_worker_asset_prefix: Option<RcStr>,
turbopack_client_side_nested_async_chunking: Option<bool>,
turbopack_server_side_nested_async_chunking: Option<bool>,
turbopack_import_type_bytes: Option<bool>,
Expand Down Expand Up @@ -2273,6 +2284,18 @@ impl NextConfig {
)
}

/// Returns the resolved worker chunk base path with `/_next/` appended,
/// or `None` to fall back to the regular chunk base path.
#[turbo_tasks::function]
pub fn turbopack_worker_asset_prefix(&self) -> Vc<Option<RcStr>> {
Vc::cell(
self.experimental
.turbopack_worker_asset_prefix
.as_ref()
.map(|prefix| format!("{}/_next/", prefix.trim_end_matches('/')).into()),
)
}

#[turbo_tasks::function]
pub fn typescript_tsconfig_path(&self) -> Result<Vc<Option<RcStr>>> {
Ok(Vc::cell(
Expand Down
39 changes: 20 additions & 19 deletions docs/01-app/03-api-reference/08-turbopack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -369,25 +369,26 @@ Turbopack can be configured via `next.config.js` (or `next.config.ts`) under the

Additionally, the following experimental options are available under `experimental` in `next.config.js`:

| Option | Description | Default (dev) | Default (build) |
| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | ------------- | ----------------------------- |
| [`turbopackFileSystemCacheForDev`](/docs/app/api-reference/config/next-config-js/turbopackFileSystemCache) | Enable filesystem cache for the dev server. | `true` | N/A |
| [`turbopackFileSystemCacheForBuild`](/docs/app/api-reference/config/next-config-js/turbopackFileSystemCache) | Enable filesystem cache for builds. | N/A | `false` |
| `turbopackMinify` | Enable minification. | `false` | `true` |
| `turbopackSourceMaps` | Enable source maps. | `true` | `productionBrowserSourceMaps` |
| `turbopackInputSourceMaps` | Enable extraction of source maps from input files. | `true` | `true` |
| `turbopackTreeShaking` | Use advanced module-fragments tree shaking instead of the default reexports-only mode. | `false` | `false` |
| `turbopackRemoveUnusedImports` | Enable removing unused imports. Requires `turbopackRemoveUnusedExports`. | `false` | `true` |
| `turbopackRemoveUnusedExports` | Enable removing unused exports. | `false` | `true` |
| `turbopackInferModuleSideEffects` | Enable local analysis to infer side-effect-free modules for better tree shaking. | `true` | `true` |
| `turbopackScopeHoisting` | Enable scope hoisting. Always disabled in dev mode. | `false` | `true` |
| `turbopackClientSideNestedAsyncChunking` | Enable nested async chunking for client-side assets. | `false` | `true` |
| `turbopackServerSideNestedAsyncChunking` | Enable nested async chunking for server-side assets. | `false` | `false` |
| `turbopackImportTypeBytes` | Enable support for `with {type: "bytes"}` for ESM imports. | `false` | `false` |
| `turbopackUseBuiltinBabel` | Enable automatic Babel loader configuration when a Babel config file is present. | `true` | `true` |
| `turbopackUseBuiltinSass` | Enable automatic Sass loader configuration. | `true` | `true` |
| `turbopackModuleIds` | Module ID strategy: `'named'` or `'deterministic'`. | `'named'` | `'deterministic'` |
| [`turbopackLocalPostcssConfig`](/docs/app/api-reference/config/next-config-js/turbopackLocalPostcssConfig) | Resolve `postcss.config.js` from the CSS file's directory first, then the project root. | `false` | `false` |
| Option | Description | Default (dev) | Default (build) |
| ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ----------------------------- |
| [`turbopackFileSystemCacheForDev`](/docs/app/api-reference/config/next-config-js/turbopackFileSystemCache) | Enable filesystem cache for the dev server. | `true` | N/A |
| [`turbopackFileSystemCacheForBuild`](/docs/app/api-reference/config/next-config-js/turbopackFileSystemCache) | Enable filesystem cache for builds. | N/A | `false` |
| `turbopackMinify` | Enable minification. | `false` | `true` |
| `turbopackSourceMaps` | Enable source maps. | `true` | `productionBrowserSourceMaps` |
| `turbopackInputSourceMaps` | Enable extraction of source maps from input files. | `true` | `true` |
| `turbopackTreeShaking` | Use advanced module-fragments tree shaking instead of the default reexports-only mode. | `false` | `false` |
| `turbopackRemoveUnusedImports` | Enable removing unused imports. Requires `turbopackRemoveUnusedExports`. | `false` | `true` |
| `turbopackRemoveUnusedExports` | Enable removing unused exports. | `false` | `true` |
| `turbopackInferModuleSideEffects` | Enable local analysis to infer side-effect-free modules for better tree shaking. | `true` | `true` |
| `turbopackScopeHoisting` | Enable scope hoisting. Always disabled in dev mode. | `false` | `true` |
| `turbopackClientSideNestedAsyncChunking` | Enable nested async chunking for client-side assets. | `false` | `true` |
| `turbopackServerSideNestedAsyncChunking` | Enable nested async chunking for server-side assets. | `false` | `false` |
| `turbopackImportTypeBytes` | Enable support for `with {type: "bytes"}` for ESM imports. | `false` | `false` |
| `turbopackUseBuiltinBabel` | Enable automatic Babel loader configuration when a Babel config file is present. | `true` | `true` |
| `turbopackUseBuiltinSass` | Enable automatic Sass loader configuration. | `true` | `true` |
| `turbopackModuleIds` | Module ID strategy: `'named'` or `'deterministic'`. | `'named'` | `'deterministic'` |
| [`turbopackLocalPostcssConfig`](/docs/app/api-reference/config/next-config-js/turbopackLocalPostcssConfig) | Resolve `postcss.config.js` from the CSS file's directory first, then the project root. | `false` | `false` |
| `turbopackWorkerAssetPrefix` | Custom asset prefix for Web Worker URLs (entrypoint + module chunks), overriding `assetPrefix`. Mirrors webpack's `output.workerPublicPath`. | `undefined` | `undefined` |

```js filename="next.config.js"
module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@
"pixrem": "5.0.0",
"playwright": "1.58.2",
"playwright-chromium": "1.58.2",
"postcss": "8.4.31",
"postcss": "8.5.10",
"postcss-nested": "4.2.1",
"postcss-pseudoelements": "5.0.0",
"postcss-short-size": "4.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"@swc/helpers": "0.5.15",
"baseline-browser-mapping": "^2.9.19",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
"postcss": "8.5.10",
"styled-jsx": "5.1.6"
},
"peerDependencies": {
Expand Down
19 changes: 18 additions & 1 deletion packages/next/src/build/templates/app-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,23 @@ export async function handler(
fetchMetrics,
} = metadata

// Apply the `expireTime` fallback as soon as we have the render's
// `cacheControl`, so every downstream consumer (the cache stored via
// `incrementalCache.set`, the response Cache-Control header, the outgoing
// entry returned to `handleResponse`) sees a finalized `cacheControl`
// with a populated `expire`. This mirrors the build-time fallback in
// `build/index.ts` so we don't apply an expire to routes that opt out of
// revalidation entirely (`revalidate: false`) or that are dynamic
// (`revalidate: 0`).
if (
cacheControl &&
cacheControl.revalidate !== false &&
cacheControl.revalidate > 0 &&
cacheControl.expire === undefined
) {
cacheControl.expire = nextConfig.expireTime
}

if (cacheTags) {
headers[NEXT_CACHE_TAGS_HEADER] = cacheTags
}
Expand Down Expand Up @@ -1605,7 +1622,7 @@ export async function handler(

cacheControl = {
revalidate: cacheEntry.cacheControl.revalidate,
expire: cacheEntry.cacheControl?.expire ?? nextConfig.expireTime,
expire: cacheEntry.cacheControl.expire,
}
}
// Otherwise if the revalidate value is false, then we should use the
Expand Down
12 changes: 11 additions & 1 deletion packages/next/src/build/templates/app-route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,17 @@ export async function handler(
const expire =
typeof context.renderOpts.collectedExpire === 'undefined' ||
context.renderOpts.collectedExpire >= INFINITE_CACHE
? undefined
? // Fall back to the global `expireTime` config when the
// route has a numeric `revalidate` but didn't declare an
// explicit `expire` (e.g. via `cacheLife`). This mirrors the
// build-time fallback in `build/index.ts` so cache entries
// and the response Cache-Control header agree on the route's
// effective expire. Routes that opt out of revalidation
// (`revalidate: false`) or that are dynamic (`revalidate: 0`)
// keep `expire: undefined`.
revalidate !== false && revalidate > 0
? nextConfig.expireTime
: undefined
: context.renderOpts.collectedExpire

// Create the cache entry for the response.
Expand Down
Loading
Loading