Next.js 16 and React 19 Upgrades Introduce Significant Compatibility Hurdles
TL;DR
- Upgrading Next.js to version 16 necessitates adopting Turbopack, which introduces significant compatibility challenges with existing Webpack configurations and CSS module syntax, requiring substantial code modifications.
- The transition to Next.js 16's Turbopack default requires extensive code changes, particularly adding "use client" directives to hundreds of components, impacting server-side rendering assumptions and development workflows.
- Next.js 16's Turbopack does not support the
@exportsyntax for CSS variables, forcing developers to refactor how Sass variables are shared with JavaScript, impacting features like server-side rendered embed themes. - Migrating to Next.js 16's Turbopack is blocked by its inability to correctly import GraphQL files, a common practice for Apollo client, forcing users to either disable Turbopack or seek alternative solutions.
- React 19's removal of
propTypessupport, while intended to streamline development, presents a challenge for projects not fully converted to TypeScript, aspropTypesprovided valuable client-side type-checking and editor hints. - The necessity of upgrading React to version 19 for Next.js 15 introduced hurdles, including the deprecation of
defaultPropsand changes to React DOM APIs, requiring significant refactoring of class components and editor functionality. - Sticking with older versions of Next.js and React risks security vulnerabilities and compatibility issues with libraries, creating a trade-off between immediate development ease and long-term system health.
Deep Dive
CodePen's ongoing efforts to upgrade its Next.js and React versions highlight the significant technical debt and cascading complexity inherent in maintaining modern web applications. These upgrades are not merely about adopting new features but are critical for security, compatibility, and developer efficiency, yet they introduce substantial friction due to architectural shifts and ecosystem dependencies.
The primary challenge in upgrading Next.js to version 16 revolves around the default adoption of Turbopack, which necessitates extensive code modifications. While the option to retain Webpack exists, the long-term viability of this approach is questionable as future versions may deprecate Webpack support, forcing a migration. The introduction of Turbopack, alongside architectural changes like the App Router, requires significant adjustments. For instance, the "use client" directive, essential for client-side components, impacts hundreds of files, demanding careful management to avoid breaking server-side rendering assumptions. Furthermore, Turbopack's handling of CSS modules, particularly its limited support for global styles and the @export syntax, creates additional friction, requiring syntax adjustments and potentially workarounds for features like server-side rendered editor themes. The inability to directly import GraphQL files, a common pattern for Apollo clients, also presents a significant blocker, with the immediate solution often being to disable Turbopack entirely.
Beyond Next.js, the upgrade to React 19, mandated by Next.js 15, introduced its own set of complexities. The deprecation of PropTypes, while a move towards TypeScript, removed a valuable client-side type-checking mechanism for projects not yet fully converted to TypeScript. This necessitates either a full TypeScript adoption or a shift to alternative client-side validation tools like Zod. Additionally, deprecated React APIs, particularly those used in class components and within the project editor utilizing Redux, required significant refactoring. The transition from default props to inline prop destructuring, while cleaner in some respects, increased code verbosity. These cumulative challenges underscore that framework and library upgrades, while necessary for maintaining a healthy codebase, involve considerable engineering effort that diverts resources from feature development and introduces project-specific technical hurdles.
Action Items
- Audit Next.js configuration: Identify and migrate 5 deprecated properties to support Turbopack (ref: Next.js 16 upgrade guide).
- Implement
use clientdirective: Add directive to 700+ component files to enable Turbopack's client-side rendering. - Refactor Sass syntax: Update 6 global style declarations to Turbopack's supported CSS Modules format.
- Evaluate GraphQL loader compatibility: Test 1 GraphQL import with Turbopack, enabling webpack escape hatch if necessary.
- Measure Next.js compile time: Track initial build duration before and after Next.js 16 upgrade to assess performance impact.
Key Quotes
"Huge thanks to Bramus Van Damme who saw this, triaged it at Chrome, and had a resolution within a day: I think the patch is a great change so hats off to everyone involved for getting it done so quickly. It's already in Canary and don't really know when it'll get the stable but that sure will be good."
The author expresses significant gratitude towards Bramus Van Damme for quickly addressing and resolving an issue related to iframe allow attributes. This highlights the positive impact of community involvement and rapid problem-solving in software development. The author also notes the swift integration of the fix into a pre-release version, indicating confidence in its effectiveness.
"But there's the rub: we'd rather not do any user-agent sniffing at all. If we could just put all the possible allow attributes we want on there, and not be terribly concerned if any particular browser didn't support any particular value, that would be ideal."
The author articulates a preference for a more robust and less brittle solution than user-agent sniffing. This desire points to the goal of creating cross-browser compatible code that doesn't rely on detecting specific browser versions or behaviors. The ideal scenario, as described by the author, is a system where unsupported attributes are gracefully ignored by browsers.
"We're waiting for the change to Chrome to get to stable. We're hoping Safari stays the way it is. OH HI FIREFOX."
This quote humorously summarizes the current state of a technical issue across different browsers. The author indicates that a resolution is pending in Chrome, a desired behavior is already present in Safari, and a new challenge has emerged with Firefox. This illustrates the common development challenge of managing platform-specific behaviors.
"And I think it's I think it's completely required in in next 15 um and so we had to take a look at was it because of the was it the components or whatever they call those in react I bet it is right I think so and they at least from 17 to 18 they changed like some of the react dom apis and like all that all that kind of stuff so you really had to make sure you were using the the latest for that"
The author explains that upgrading to Next.js 15 necessitated an upgrade to React 19 due to dependencies. This points to the interconnectedness of different libraries and frameworks in a development stack. The author speculates that changes in React DOM APIs between versions 17 and 18 were a key factor in this requirement.
"they dropped prop types support and which which isn't that bad like you know if if it's if it's there it can stay there but it won't be used and that that's fine it can still inform oh it didn't error or whatever I I think it I think they started throwing warnings in in react 19 about it so they were like deprecated but not they didn't kill the api or something right it it just doesn't actually do anything anymore in react 19 but we mainly used them for like client for editor hints you know so like when you're looking at a particular component you can see what what the props are for it"
The author discusses the deprecation of propTypes in React 19, noting that while the API is no longer functional, it may still provide warnings or inform developers. The author highlights that propTypes were primarily used for editor hints, offering developers visibility into component props. This illustrates how features can be phased out, even if they served a useful purpose for developer experience.
"but you know it is appealing i guess i mean that's why you're doing it i suppose is it does seem like if we get it it's faster right i haven't seen any speed increases yet because i haven't been able to get past all the error modals but i guess the error modals are delivered fast that's that's great that's good yeah but yeah i mean supposedly it will compile faster"
The author expresses a hopeful anticipation for performance improvements with a new technology, even though current progress is hindered by errors. The expectation is that the new system will offer faster compilation times. This reflects a common development scenario where the promise of speed is a significant motivator for adopting new tools, despite initial challenges.
"and then you just start running into other blockers so our we use sas for for all of our stuff and occasionally we need to use like global styles within the sas and turbopack global is like a that's a post or what do you call what do you call that thing css modules feature right I think so but that means that turbopack has its own implementation of that and so you can't just directly directly use it in the same way like they only support the like function version of it where it's colon global and then the parentheses around a selector"
The author details a specific compatibility issue encountered when integrating Sass with Turbopack. The problem arises from Turbopack's distinct implementation of CSS Modules' global styles, which deviates from the expected syntax. This highlights how different build tools can have unique interpretations of features, requiring developers to adapt their code.
Resources
External Resources
Articles & Papers
- "blog post" - Documented the issue with allow attributes on iframes for attention from Chrome and other browser makers.
- "github repo for the docs" - Referenced as a source for accessing older documentation versions when official documentation was difficult to find.
People
- Bramus Van Damme - Triaged and resolved an issue with allow attributes on iframes within a day.
- Robert - Championed the adoption of TypeScript on the team and performed the bulk of its implementation.
Tools & Software
- React - A JavaScript library used by CodePen for its editor and parts of its site, with ongoing considerations for upgrades.
- Next.js - A framework used by CodePen, with discussions around upgrading versions and its impact on deployment and development.
- GitHub Actions - Used for deployment processes, requiring updates when command changes occur.
- Webpack - A compiler that CodePen uses, with considerations for its eventual replacement by Turbopack.
- Turbopack - The new default compiler in Next.js 16, which has presented challenges and required significant changes for integration.
- Cursor - An AI tool used to assist with code modifications, such as adding the "use client" directive.
- Prettier - A code formatter used to ensure consistent code style after AI modifications.
- Zod - An application for client-side data validation, particularly for data from unknown sources.
- Apollo - A setup used for server-side rendering with Next.js, which has not yet been migrated to the App Router.
- Urkel - A data fetching library used by CodePen.
- Sass - A CSS preprocessor used by CodePen, with considerations for syntax changes in Turbopack.
- GraphQL - A query language that presented import issues with Turbopack.
Websites & Online Resources
- CodePen Embed - Pages that were affected by a Google Chrome browser update related to allow attributes on iframes.
- Canary - A version of Chrome where the patch for iframe allow attributes is available.
- Lemon Productions - Assists with video production for CodePen Radio.
Other Resources
- Allow attributes on iframes - A feature in browsers that caused JavaScript errors on CodePen embeds after a Chrome update.
- App Router - A newer routing system in Next.js that is server-side rendered first.
- Pages Router - The traditional routing system in Next.js, mapped to a "pages" folder.
- Prop types - A feature in React that was dropped in React 19, previously used for client-side type checking and editor hints.
- TypeScript - A programming language that CodePen is gradually adopting, with Robert leading its implementation.
- Default props - A feature in React function components that was moved to prop destructuring in React 19.
- String refs, context types, fine DOM node implementations - Deprecated React APIs that were used in CodePen's project editor and required updates.
- Use client flag - A directive in Next.js's App Router that designates a component as client-side.
- Global styles - A feature in Sass that required syntax adjustments for Turbopack.
- Export function - A feature in Sass that allows sending variables from Sass to JavaScript, which is not supported by Turbopack.
- At value syntax - A Sass syntax similar to the export function, also not supported by Turbopack.
- Mixins - A Sass feature that caused issues with nesting and child selectors in previous Next.js versions.
- Next.js MCP Server - An AI feature that enhances AI models with Next.js documentation and APIs for better context.