chore: upgrade to React 19, Next.js 16, Apollo Client 4, Apollo Server 5#2904
chore: upgrade to React 19, Next.js 16, Apollo Client 4, Apollo Server 5#2904huumn merged 23 commits intostackernews:masterfrom
Conversation
…upgrade Apollo Client/Server, other libs that didn't support React 19 - Next.js 14.2.25 -> 15.5.14 - React 18.3.1 -> 19.2.4 - GraphQL 16.9.0 -> 16.13.2 - Apollo Client 3.11.8 -> 4.1.6 - Apollo Server 4.11.0 -> 5.5.0 - Apollo Server Integrations for Nextjs 3.1.0 -> 4.1.0 - \@yudiel/react-qr-scanner 2.0.8 -> 2.5.1 - qrcode.react 4.0.1 -> 4.2.0 - react-avatar-editor 13.0.2 -> 15.1.0 - recharts 2.13.0 -> 2.15.4 - react-is 19.2.4 override - can be removed after upgrade to recharts 3.x - eslint-plugin-next 14.2.15 -> 15.5.14 + eslint-config-next 15.5.14
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
… a server external DefinePlugin can't otherwise replace the env var internally used by next-plausible to determine if we're using the proxy or not
…get the full error where errors are manually handled
sir-opti
left a comment
There was a problem hiding this comment.
Did some code review on the diff, pre-testing.
|
Hi opti! All the things you found were added automatically by the Apollo Client 4 migration codemod. The Thanks you so much for checking this PR, I'll address immediately 🫡 |
…pollo Client where unnecessary
| if (data && !data.hasNewNotes) { | ||
| clearNotifications() | ||
| } | ||
| }, [data?.hasNewNotes]) |
There was a problem hiding this comment.
useEffect fires less often than replaced onCompleted callback
Low Severity
The useEffect with [data?.hasNewNotes] dependency only fires when the value changes, whereas the old onCompleted callback fired on every successful poll response. This means clearNotifications() is no longer called repeatedly when hasNewNotes stays false across consecutive polls. If a push notification arrives but the server-side hasNewNotes value doesn't transition (remains false), the notification won't be cleared until the next value change. The old behavior acted as a continuous cleanup sweep.
Reviewed by Cursor Bugbot for commit 7a6367c. Configure here.
There was a problem hiding this comment.
This seems like a good thing.
|
Seeing this, a lot: |
…ents that by default use their own
| <Link href={'/' + user.name} passHref legacyBehavior> | ||
| <Nav.Link eventKey='bio'>bio</Nav.Link> | ||
| </Link> | ||
| <Nav.Link as={Link} href={'/' + user.name} eventKey='bio'>bio</Nav.Link> |
There was a problem hiding this comment.
This change has been applied to every instance of NextLink used with legacyBehavior. We're giving NextLink as the component to be used in place of the default <a> tag.
passHref then becomes useless as Nav.Link, for example, gives the href to whatever as component we indicate.
@sir-opti I was ignoring that deprecation warning to avoid touching too many things, but the solution is quite straightforward.
There was a problem hiding this comment.
This is an awesome change because now my eyes only hurt 200% instead of 500% from looking at that indentation 🤣
|
Haven't found anything new between posting/deleting, editor funk, territory creation, payments/zaps/boosts, messing around with rankings and analytics - all that worked great. I have 2 more test areas to cover on this:
Also:
|
|
Thank you for the QA!
Ah yes, we do! I've added this in the custom domains PR today d466483, but I didn't make the same reasoning for this PR (or custom hosts in general...). I should come up with a way to satisfy both normal sndev and custom domains. I'll check it out tomorrow first thing.
I think you just need to add your host to the allowed origins in |
…LOWED_DEV_ORIGINS env var for additional allowed origins
There was a problem hiding this comment.
I'm not sure these should block merging, because afaict this would run fine in prod, but here's a few things I noticed:
- Dev hits the nextjs error boundary on
checkMediaifcaptureis not running and media is checked. I didn't check if this happens in prod, but it's annoying in dev and should probably be fixed. - One of the consequences of
notifyOnNetworkStatusChange: trueis that rerenders are happening when polling even if data doesn't change.- Example: create a new comment and watch the
timeSincechange - If only, this suggests I don't understand the consequences of
notifyOnNetworkStatusChange: trueand wonder what else might change.
- Example: create a new comment and watch the
components/item-popover.js,components/sub-popover.js,components/user-popover.js,components/territory-form.js,wallets/client/hooks/logger.jsall logAbortErrorstill.- Not a regression, but we pull deps from
next/dist/*likeNodeNextRequestwhich we got lucky didn't change between upgrades. Perhaps can be changed in a follow up.
I mentioned this in this PR description, thinking that it was a new default behavior lol, but it seems like it's a bug on the pages router: vercel/next.js#75299
This is a behavior present on const trusted = useMemo(() => !!(srcSet || srcSetIntital) || IMGPROXY_URL_REGEXP.test(src) || MEDIA_DOMAIN_REGEXP.test(src), [srcSet, srcSetIntital, src])
const [isImage, setIsImage] = useState((kind === 'image' || legacySrcSet?.video === false) && trusted)If an image is uploaded, We don't load the media client-side anymore to determine if it's an image or a video (or media at all), instead we always contact
Just confirmed, basically it re-renders even on
I'll handle
Probably whatever we needed from |
It's mostly cookies parsing and in
I agree - that's the safest thing. Perhaps we can switch it to the default later (assuming it's worth it).
lol that's nasty
It might be worth creating our own |
I'm sure we won't need it if we fix the way we use |
…inal Apollo Client 3 behavior (don't re-render components unless data changes)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
There are 4 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 85d3e80. Configure here.
| return devOrigins | ||
| } | ||
|
|
||
| module.exports = withPlausibleProxy({ src: 'https://plausible.io/js/pa-EScEhWlTi3E-sauvdFABb.js' })({ |
There was a problem hiding this comment.
Unrecognized src option passed to withPlausibleProxy
Medium Severity
The src option passed to withPlausibleProxy is not a recognized configuration parameter. The valid options for withPlausibleProxy are subdirectory, scriptName, and customDomain (or scriptPath/apiPath in newer versions). The src value (https://plausible.io/js/pa-EScEhWlTi3E-sauvdFABb.js) is silently ignored, meaning the proxy rewrites are configured with default paths, not the custom script URL that was clearly intended to be used.
Reviewed by Cursor Bugbot for commit 85d3e80. Configure here.
There was a problem hiding this comment.
export default function withPlausibleProxy(options: {
/**
* The site-specific script URL from your Plausible dashboard, e.g. https://plausible.io/js/pa-XXXXX.js.
*/
src: string;
/**
* The local path for the proxied script. Defaults to /js/script.js.
*/
scriptPath?: string;
/**
* The local path for the proxied API endpoint. Defaults to /api/event.
*/
apiPath?: string;
}): (nextConfig: NextConfig) => NextConfig;wdym??
I went ahead and switched This is good to go now imo. |
|
Thank you! You're right about |


Description
This PR aims at upgrading Next.js from 14 to 16.
Other than performance gains, the most recent reason to update is the introduction of the Node.js Proxy (ex-middleware), enabling custom domains (#2897) db lookup right inside the proxy, without needing an API endpoint to do so.
Upgrades
Changes
TBD
Next.js rewrites
This rewrite rule has been removed because it's not supported by Next.js 15+
but this rule already does the same thing and is supported:
Screenshots
Stacker News running on Next.js 16.2.2
Additional Context
The upgrade to Next.js 16 and React 19 required the upgrade of other core libraries, such as Apollo Client/Server.
Upgrading Apollo meant handling breaking changes to
useLazyQuery,useQuery, andApolloLink. Everything seems to be working as intended but still needs deep QA.Safari DevTools are broken since Next.js 15 vercel/next.js#78524 if Next.js is ran without Turbopack.
Next.js now catches
console.errors and show them as thrown errors in dev mode.Apollo
Apollo breaking changes
The notifyOnNetworkStatusChange option now defaults to true. This affects React hooks that provide this option (e.g. useQuery) and ObservableQuery instances created by client.watchQuery.
This change means you might see loading states more often, especially when used with refetch or other APIs that cause fetches. If this causes issues, you can revert to the v3 behavior by setting the global default back to false.
If we use
useLazyQueryto execute queries but don't read the state values returned in the result tuple, it is now recommended to useclient.querydirectly. srcThe component unmounts while the query is in flight
A new query is started by calling the execute function while a previous query is in flight
In each of these cases, the promise returned by the execute function is rejected with an AbortError. This change means it is no longer possible to run multiple queries simultaneously.
In some cases, you may need the query to run to completion, even if a new query is started or your component unmounts. In these cases, you can call the .retain() function on the promise returned by the execute function.
useQuerygot rid ofonCompletedandonErrorcallbacksNew requirements for custom cache implementations
Custom cache implementations must now implement the fragmentMatches method, which is required for fragment matching in Apollo Client 4.
Checklist
Are your changes backward compatible? Please answer below:
tbd
On a scale of 1-10 how well and how have you QA'd this change and any features it might affect? Please answer below:
7, everything seems to be working. QA done on payments, wallets, normal website interaction (post, comment, navigation), live comments, editor
For frontend changes: Tested on mobile, light and dark mode? Please answer below:
n/a
Did you introduce any new environment variables? If so, call them out explicitly here:
Yes, with Next.js 15/16
localhostis the default and only allowed dev origin. This has been modified to ensure it also always includesNEXT_PUBLIC_URLand to support additional origins, we now have a new env var:ALLOWED_DEV_ORIGINS=By default it's empty, which means that only
localhostandNEXT_PUBLIC_URLare allowed.Did you use AI for this? If so, how much did it assist you?
Note
High Risk
High risk because it upgrades core runtime dependencies (Next.js/React/Apollo) and rewires Apollo hook/query behavior (notably
useLazyQuerypromise/abort semantics and removal ofonCompleted), which can affect navigation, data fetching, and payments-related flows across the app.Overview
Upgrades the frontend stack to Next.js 16/React 19 and adapts the codebase for Apollo Client 4 by switching React hooks imports to
@apollo/client/react, enabling@clientdirective support viaLocalState, and updating client config (e.g.,ApolloLink.from, devtools config, and defaultnotifyOnNetworkStatusChange: false).Refactors multiple
useLazyQuery/useQuerycall sites to the new promise-based/abort-heavy behavior: movesonCompletedlogic into.then(...)/useEffect, adds centralizedisAbortErrorfiltering to avoid noisy errors on aborted requests, and updates a few components (popovers, upload fee refresh, suggestions, auto-retry pay-ins) to execute queries explicitly and handle errors.Adjusts Next.js config for v15+ compatibility and dev ergonomics: adds
allowedDevOriginsderived fromNEXT_PUBLIC_URLplus newALLOWED_DEV_ORIGINS, removes an unsupported rewrite, addstranspilePackages, and silences bootstrap sass deprecation warnings; also adds a new flateslint.config.mjs.Reviewed by Cursor Bugbot for commit 36ab54b. Bugbot is set up for automated code reviews on this repo. Configure here.