Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix cache kind validation #76064

Merged
merged 3 commits into from
Feb 17, 2025
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
27 changes: 20 additions & 7 deletions crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,21 @@ struct CustomRoutes {
pub struct ModularizeImports(FxIndexMap<String, ModularizeImportPackageConfig>);

#[turbo_tasks::value(transparent)]
#[derive(Clone, Debug)]
pub struct CacheKinds(FxHashSet<RcStr>);

impl CacheKinds {
pub fn extend<I: IntoIterator<Item = RcStr>>(&mut self, iter: I) {
self.0.extend(iter);
}
}

impl Default for CacheKinds {
fn default() -> Self {
CacheKinds(["default", "remote"].iter().map(|&s| s.into()).collect())
}
}

#[turbo_tasks::value(serialization = "custom", eq = "manual")]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, OperationValue)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -1421,13 +1434,13 @@ impl NextConfig {

#[turbo_tasks::function]
pub fn cache_kinds(&self) -> Vc<CacheKinds> {
Vc::cell(
self.experimental
.cache_handlers
.as_ref()
.map(|handlers| handlers.keys().cloned().collect())
.unwrap_or_default(),
)
let mut cache_kinds = CacheKinds::default();

if let Some(handlers) = self.experimental.cache_handlers.as_ref() {
cache_kinds.extend(handlers.keys().cloned());
}

cache_kinds.cell()
}

#[turbo_tasks::function]
Expand Down
4 changes: 3 additions & 1 deletion packages/next/src/build/swc/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ function getBaseSWCOptions({
isReactServerLayer,
useCacheEnabled,
hashSalt: serverReferenceHashSalt,
cacheKinds: cacheHandlers ? Object.keys(cacheHandlers) : [],
cacheKinds: ['default', 'remote'].concat(
cacheHandlers ? Object.keys(cacheHandlers) : []
),
}
: undefined,
// For app router we prefer to bundle ESM,
Expand Down
8 changes: 8 additions & 0 deletions packages/next/src/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,14 @@ export default class NextNodeServer extends BaseServer<
cacheHandlerGlobal[cacheHandlersSymbol]?.DefaultCache ||
DefaultCacheHandler
}

if (
!cacheHandlers.remote &&
cacheHandlerGlobal[cacheHandlersSymbol]?.RemoteCache
) {
cacheHandlerGlobal.__nextCacheHandlers.remote =
cacheHandlerGlobal[cacheHandlersSymbol].RemoteCache
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use cache: remote'

export default async function Page() {
return <p>hello world</p>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import DefaultCacheHandler from 'next/dist/server/lib/cache-handlers/default'

export function register() {
globalThis[Symbol.for('@next/cache-handlers')] = {
RemoteCache: DefaultCacheHandler,
}
}
2 changes: 2 additions & 0 deletions test/e2e/app-dir/use-cache-unknown-cache-kind/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
const nextConfig = {
experimental: {
dynamicIO: true,
cacheHandlers: {}, // overwrite the default config
prerenderEarlyExit: false,
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ describe('use-cache-unknown-cache-kind', () => {
process.env.__NEXT_EXPERIMENTAL_NEW_DEV_OVERLAY === 'true'

if (isNextStart) {
beforeAll(async () => {
await next.build()
})

it('should fail the build with an error', async () => {
const { cliOutput } = await next.build()
const buildOutput = getBuildOutput(cliOutput)
const buildOutput = getBuildOutput(next.cliOutput)

if (isTurbopack) {
expect(buildOutput).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -79,7 +82,16 @@ describe('use-cache-unknown-cache-kind', () => {
`)
}
})

it('should not fail the build for default cache kinds', async () => {
expect(next.cliOutput).not.toInclude('Unknown cache kind "remote"')
})
} else {
it('should not show an error for default cache kinds', async () => {
const browser = await next.browser('/remote')
await assertNoRedbox(browser)
})

it('should show a build error', async () => {
const browser = await next.browser('/')

Expand Down
5 changes: 3 additions & 2 deletions test/lib/next-modes/next-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,13 @@ export class NextDevInstance extends NextInstance {
) {
await this.handleDevWatchDelayBeforeChange(filename)
try {
const cliOutputLengthBefore = this.cliOutput.length
let cliOutputLength = this.cliOutput.length
const isServerRunning = this.childProcess && !this.isStopping

const detectServerRestart = async () => {
await retry(async () => {
const isServerReady = this.serverReadyPattern.test(
this.cliOutput.slice(cliOutputLengthBefore)
this.cliOutput.slice(cliOutputLength)
)
if (isServerRunning && !isServerReady) {
throw new Error('Server has not finished restarting.')
Expand Down Expand Up @@ -202,6 +202,7 @@ export class NextDevInstance extends NextInstance {
runWithTempContent
? async (...args) => {
await waitServerToBeReadyAfterPatchFile()
cliOutputLength = this.cliOutput.length

return runWithTempContent(...args)
}
Expand Down
Loading