The Next.js 13 was released a few weeks ago. We updated the Next.js for Acquia CMS starter kit to the latest version and wanted to take the opportunity to share how the experience was.
If you prefer to just view the code changes needed, you can see that each section of this blog post roughly maps into its own commit on this pull request.
I started by manually updating all of the version constraints.
--- a/package.json+++ b/package.json@@ -15,11 +15,11 @@ "classnames": "^2.3.2", "drupal-jsonapi-params": "^2.1.0", "html-react-parser": "^3.0.4",- "next": "^12.3.2",+ "next": "^13.0.0", "next-acms": "^1.0.0", "next-drupal": "^1.5.0",- "react": "^17.0.2",- "react-dom": "^17.0.2",+ "react": "^18.2.0",+ "react-dom": "^18.2.0", "sharp": "^0.31.2" }, "devDependencies": {
After updating the version constraints, I was able to simply install dependencies again.
yarn install
I was getting some TypeScript type errors and realized that I needed to update the @types/react
package to get the correct TypeScript types.
--- a/starters/basic-starter/package.json+++ b/starters/basic-starter/package.json@@ -25,7 +25,7 @@ "devDependencies": { "@babel/core": "^7.20.2", "@types/node": "^18.11.9",- "@types/react": "^17.0.4",+ "@types/react": "^18.0.25", "autoprefixer": "^10.4.13", "eslint": "^8.27.0", "eslint-config-next": "^12.3.2",
After installing dependencies again, the TypeScript error was fixed.
yarn install
After this, I ran into some issues with the Link
component. The required changes are documented in the release notes. This was pretty straightforward to address - all that was needed was to remove the inner from the
Link
component children.
--- a/components/formatted-text.tsx+++ b/components/formatted-text.tsx@@ -44,8 +44,8 @@ const options: HTMLReactParserOptions = { if (href && isRelative(href)) { return (-
-
+
+ {domToReact(domNode.children)} ); }
Here's the full commit.
After resolving the exceptions caused by the Link
component, I noticed that I had some errors in the console because we were still using deprecated APIs from the Image
component. This was also documented in the release notes.
The biggest change needed to address this was to update the MediaImage
component to work with the new Image
component. Next.js 13 ships with a simplified Image
component that requires less client side code that should improve the client side performance. The new Image
component also provides better developer experience by providing more HTML like interface, and by providing more validation to help address misconfigured uses of the Image
component.
The minimum requirement to get the MediaImage
to work was to remove the objectFit
and layout
properties since those properties had been deprecated on the upstream component.
--- a/components/media--image.tsx+++ b/components/media--image.tsx@@ -12,13 +12,16 @@ MediaImage.type = 'media--image'; export function MediaImage({ media,- layout = 'responsive',- objectFit,+ imageStyle,+ fill = false, width, height, priority,+ quality, sizes,- imageStyle,+ placeholder,+ blurDataURL,+ loading, ...props }: MediaImageProps) { const image = media?.image;@@ -29,13 +32,12 @@ export function MediaImage({ let sizeProps; let srcURL;- sizeProps =- layout === 'fill'- ? null- : {- width: width || image.resourceIdObjMeta.width,- height: height || image.resourceIdObjMeta.height,- };+ sizeProps = fill+ ? null+ : {+ width: width || image.resourceIdObjMeta.width,+ height: height || image.resourceIdObjMeta.height,+ }; srcURL = absoluteURL(image.uri.url); // Use the image style to render an image if specified.@@ -64,13 +66,16 @@ export function MediaImage({
);
Here's the full commit.
I also noticed a React warning in the console that indicated that there were multiple nodes inside the element. This was caused by the fact that the
title
tag contained an expression within the children.
To address this issue, I converted the children of the element into an expression that outputs a single text node. This is different from having an expression within text. In order for React to hydrate the expression, it adds additional comment nodes to the server rendered output to separate the expression from the text. Since
title
natively does not assume it could contain anything other than text nodes, this leads into the comment nodes being rendered as text in the browser title. This could have also led to a forced re-rendering on the client side. This was mentioned in the React 18.10 release notes.
--- a/components/layout.tsx+++ b/components/layout.tsx@@ -20,7 +20,7 @@ export function Layout({ title, menus, children }: LayoutProps) { return ( -
+
If this content did not answer your questions, try searching or contacting our support team for further assistance.
Fri Sep 12 2025 06:11:30 GMT+0000 (Coordinated Universal Time)