Skip to content

fix(shims): add unstable_cacheLife and unstable_cacheTag to next/cache#1202

Merged
james-elicx merged 1 commit into
mainfrom
fix/shim-unstable-cache
May 14, 2026
Merged

fix(shims): add unstable_cacheLife and unstable_cacheTag to next/cache#1202
james-elicx merged 1 commit into
mainfrom
fix/shim-unstable-cache

Conversation

@james-elicx
Copy link
Copy Markdown
Collaborator

Summary

Adds unstable_cacheLife and unstable_cacheTag exports to packages/vinext/src/shims/cache.ts as deprecation-warning aliases that delegate to the stabilized cacheLife and cacheTag.

This unblocks 6 build failures in the Next.js deploy suite where apps import the unstable_-prefixed names and Rolldown rejects the build with:

[MISSING_EXPORT] "unstable_cacheLife" is not exported by ".../vinext/dist/shims/cache.js"
[MISSING_EXPORT] "unstable_cacheTag"  is not exported by ".../vinext/dist/shims/cache.js"

Behavior: deprecation-warning aliases (not hard aliases)

Next.js wraps each call in a one-time console.error(new Error(...)) and then delegates to the stabilized counterpart. We mirror that exactly.

Evidence — Next.js source (packages/next/cache.js):

let didWarnCacheLife = false
function unstable_cacheLife() {
  if (!didWarnCacheLife) {
    didWarnCacheLife = true
    const error = new Error(
      '`unstable_cacheLife` was recently stabilized and should be imported as `cacheLife`. The `unstable` prefixed form will be removed in a future version of Next.js.'
    )
    console.error(error)
  }
  return cacheExports.cacheLife.apply(this, arguments)
}

(Same shape for unstable_cacheTag.)

Next.js test asserts CLI output literally contains the warning text:

The "Error: " prefix in the assertion comes from passing an Error instance to console.error — so we pass new Error(...) rather than a bare string to keep the exact surface behavior.

Implementation

  • packages/vinext/src/shims/cache.ts:

    • Add unstable_cacheLife(profile: string | CacheLifeConfig) — emits the deprecation warning once, then delegates to cacheLife(profile). Signature matches cacheLife.
    • Add unstable_cacheTag(...tags: string[]) — emits the deprecation warning once, then delegates to cacheTag(...tags). Signature matches cacheTag.
    • Both gated by a module-level _unstable*Warned flag (mirrors Next.js's didWarnCacheLife / didWarnCacheTag).
    • JSDoc links back to the Next.js source and the asserting test.
  • tests/shims.test.ts:

    • unstable_cacheLife is exported as a deprecation alias for cacheLife — asserts the export is a function, both (profile: string) and (profile: object) forms work without throwing, and console.error is called with a message containing `unstable_cacheLife` was recently stabilized.
    • unstable_cacheTag is exported as a deprecation alias for cacheTag — asserts the export is a function, variadic tag form works without throwing, and console.error is called with the matching warning text.
    • Tests follow the same shape as the existing unstable_io deprecation-alias test in this file.

Checks

  • vp test run tests/shims.test.ts — both new tests pass (plus all sibling cache shim tests).
  • vp check — clean (1241 files formatted, 548 files lint/type-clean).
  • Touches only packages/vinext/src/shims/cache.ts and tests/shims.test.ts per the task constraints.

Test Plan

vp test run tests/shims.test.ts -t "unstable_cache"
vp check

Next.js exports unstable_cacheLife and unstable_cacheTag as deprecation
aliases that emit a one-time console.error and delegate to the stabilized
cacheLife / cacheTag. Several Next.js apps in the deploy suite still
import the unstable_ names, so vinext apps fail to build with
[MISSING_EXPORT] errors. Match Next.js's behavior exactly: same warning
text, same one-time-per-process gating, same delegation.
@james-elicx
Copy link
Copy Markdown
Collaborator Author

/bigbonk review

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 14, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vinext@1202

commit: d1bc6c3

@github-actions
Copy link
Copy Markdown

Example Preview Production Original
app-router-cloudflare preview production
pages-router-cloudflare preview production
app-router-playground preview production original
realworld-api-rest preview production
nextra-docs-template preview production
benchmarks preview production
hackernews preview production original

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Clean, well-scoped change that matches the established unstable_io deprecation alias pattern already in this file.

What I checked:

  • Implementation mirrors the exact Next.js packages/next/cache.js pattern: module-level didWarn flag, console.error(new Error(...)) (not a bare string), then delegation to the stabilized function. The Error wrapping is important because the Next.js test asserts "Error: \unstable_cacheLife`..."in CLI output, which comes fromconsole.error(new Error(...))`.

  • Signatures match: unstable_cacheLife(profile: string | CacheLifeConfig) matches cacheLife, and unstable_cacheTag(...tags: string[]) matches cacheTag. Both return void (matching the delegation targets).

  • Tests follow the same shape as the existing unstable_io test at line 2336 — spy on console, call the function, assert the warning fires. The instanceof Error check in the warned assertion is correct since the implementation passes new Error(...).

  • The test-ordering sensitivity from module-level _unstableCacheLifeWarned / _unstableCacheTagWarned flags is the same as _unstableIoWarned — the warned flag can only fire once per module load. Since the tests only assert the warning was seen (.some(...)) and don't assert it fires on the second call, this is fine. If these tests run after some other test that already triggered the alias, the flag would be true and no warning would fire. But since the module is dynamically imported and Vitest's module cache is per-file, this isn't a practical problem here.

  • JSDoc links back to the Next.js source and the asserting test file. Placement in the file is correct (between cacheTag and the unstable_cache section).

  • Check passed, and the change is purely additive (no behavioral changes to existing exports).

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 14, 2026

Approved PR #1202. The change is clean and well-scoped:

  • Follows the exact same deprecation-alias pattern as the existing unstable_io shim
  • Correctly mirrors Next.js behavior: console.error(new Error(...)) with one-time warning, then delegates to the stabilized function
  • Tests match the existing convention and assert the warning content
  • Purely additive, no behavioral changes to existing exports
  • Check is green, CI still running on the remaining jobs

github run

@james-elicx james-elicx marked this pull request as ready for review May 14, 2026 15:12
@james-elicx james-elicx merged commit a713463 into main May 14, 2026
54 of 56 checks passed
@james-elicx james-elicx deleted the fix/shim-unstable-cache branch May 14, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant