Conversation
There was a problem hiding this comment.
Pull request overview
Upgrades the next/ frontend to Next.js 15 + React 19 and replaces the abandoned @neshca/cache-handler integration with @fortedigital/nextjs-cache-handler, including the related async Next.js 15 API migrations (params, searchParams, draftMode() as Promises).
Changes:
- Upgrade Next.js to v15 and React to v19; update related ESLint and type packages.
- Replace
@neshca/cache-handlerusage with Next’sunstable_cachepatterns and switch the runtime cache handler to@fortedigital/nextjs-cache-handler(+@redis/client). - Migrate App Router pages/layouts to await
params/searchParamsanddraftMode()per Next.js 15 behavior.
Reviewed changes
Copilot reviewed 25 out of 27 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| next/src/lib/hooks/use-event-listener.ts | Adjust useRef initialization for updated React typings. |
| next/src/lib/drupal/get-node.ts | Replace neshCache wrapper with unstable_cache + React cache. |
| next/src/lib/drupal/get-menus.ts | Replace neshCache wrapper with unstable_cache + React cache. |
| next/src/instrumentation.ts | Switch instrumentation import to @fortedigital/nextjs-cache-handler. |
| next/src/components/draft-alert.tsx | Await draftMode() (Next.js 15 async API). |
| next/src/app/api/search/route.ts | Align route handler signature with updated Next.js types. |
| next/src/app/[locale]/layout.tsx | Await params in layout + metadata generator. |
| next/src/app/[locale]/(static)/search/page.tsx | Client page unwraps promised params via React use(). |
| next/src/app/[locale]/(static)/page.tsx | Await params and draftMode(); set static revalidate literal. |
| next/src/app/[locale]/(static)/nodepreview/page.tsx | Await params/searchParams in preview page. |
| next/src/app/[locale]/(static)/layout.tsx | Await params in static layout. |
| next/src/app/[locale]/(static)/dashboard/webforms/[webformName]/[webformSubmissionUuid]/page.tsx | Await promised params and keep locale setup. |
| next/src/app/[locale]/(static)/dashboard/page.tsx | Await params in page + metadata generator. |
| next/src/app/[locale]/(static)/auth/register/page.tsx | Await params for locale. |
| next/src/app/[locale]/(static)/auth/login/page.tsx | Await params for locale. |
| next/src/app/[locale]/(static)/all-articles/page.tsx | Await params/searchParams; set static revalidate literal. |
| next/src/app/[locale]/(dynamic)/[...slug]/page.tsx | Await params/draftMode(); adjust generateStaticParams; set static revalidate. |
| next/src/app/[locale]/(dynamic)/[...slug]/layout.tsx | Await promised params in dynamic layout. |
| next/package.json | Bump Next/React, swap cache handler deps, add @redis/client. |
| next/package-lock.json | Lockfile updates for upgraded dependencies and new cache handler/redis client. |
| next/next.config.mjs | Replace experimental.swrDelta with expireTime; keep cache handler wiring. |
| next/next-env.d.ts | Add routes typing reference and update docs link. |
| next/cache-handler.mjs | Migrate cache handler implementation to @fortedigital/nextjs-cache-handler + @redis/client. |
| next/.gitignore | Ignore TS build info file. |
| .github/copilot-instructions.md | Add repo-specific dev + migration guidance (Next 15, cache handler, env var conventions). |
| .ddev/config.yaml | Bump Node version to 22 for local development. |
| .circleci/config.yml | Switch CI executor image (Node 22). |
Files not reviewed (1)
- next/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| CacheHandler.onCreation(async ({ buildId }) => { | ||
| /** @type {import("redis").RedisClientType | undefined} */ | ||
| let client; | ||
| /** @type {import("@neshca/cache-handler").Handler | undefined} */ | ||
| /** @type {any} */ | ||
| let handler; | ||
|
|
There was a problem hiding this comment.
CacheHandler.onCreation can return handlers: [undefined] when Redis env vars are missing or during the build phase, because handler is only assigned inside the if (...) block. Initialize handler to createLruHandler() by default (and only swap to Redis when ready), or ensure the returned handlers array contains only defined handlers.
|
|
||
| **Behaviour:** | ||
| - Cache keys are prefixed with `cache-{buildId}:` so deploys don't serve stale entries from a previous build | ||
| - If Redis is unavailable or the connection times out (3 s), it **falls back silently to an in-memory LRU** handler — the app keeps working |
There was a problem hiding this comment.
This documentation says the Redis connection times out after 3s and falls back to LRU, but next/cache-handler.mjs currently calls client.connect() without a timeout and can block startup. Either implement the connect timeout/fallback behavior in code or adjust this bullet to match the actual behavior.
| - If Redis is unavailable or the connection times out (3 s), it **falls back silently to an in-memory LRU** handler — the app keeps working | |
| - Redis connectivity (including timeouts and any fallbacks) is handled by `@fortedigital/nextjs-cache-handler` / `@redis/client`; there is currently **no custom 3 s connect-timeout or guaranteed automatic fallback to an in-memory LRU** implemented in `next/cache-handler.mjs` |
| if (client?.isReady) { | ||
| /** @type {import("@neshca/cache-handler/redis-strings").CreateRedisStringsHandlerOptions} */ | ||
| const redisHandlerOptions = { | ||
| client, | ||
| keyPrefix: `cache-${buildId}:`, |
There was a problem hiding this comment.
timeoutMs here only applies to Redis operations after the client is connected; client.connect() earlier can still block startup if Redis is unreachable. If you expect a 3s failover to LRU, add an explicit connect timeout (e.g., Redis socket options or racing connect() against a timer) and fall back when it elapses.
next/package.json
Outdated
| "@hookform/resolvers": "^3.9.1", | ||
| "@neshca/cache-handler": "^1.9.0", | ||
| "@fortedigital/nextjs-cache-handler": "^2", | ||
| "@redis/client": "^5", |
There was a problem hiding this comment.
@fortedigital/nextjs-cache-handler declares a peer dependency on @redis/client >= 5.5.6 (per the lockfile). Declaring "@redis/client": "^5" allows versions <5.5.6; consider pinning the range to ^5.5.6 (or higher) to reflect the actual minimum requirement and avoid future installs resolving to an incompatible 5.x release.
| "@redis/client": "^5", | |
| "@redis/client": "^5.5.6", |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 27 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Link to ticket:
https://wunder.atlassian.net/browse/NEX-200
Link to feature environment:
[Add link to feature environment]
Changes proposed in this PR:
Update next.js to version 15, switch to @fortedigital/nextjs-cache-handler , since the previous package is now abandoned and does not work with next 15.
This seemed like an idea task for copilot cli, so the changed are pretty much all done by the AI. We have to check this one carefully.
How to test:
Testing locally:
./setup-ddev.sh -cddev npx cypress installddev exec ./install-cypress-deps.shnextdirectory, open another terminal window while both frontend and backend are running and run the Cypress tests:ddev npm run cypress:run