Upgrading NextJs v11 to 12 hopefully to 13

Upgrading NextJs v11 to 12 hopefully to 13

a year ago, April 17, 2023
Reading time: 7 mins

upgrading NextJs from v11 to 12.

Webpack@4 is no more supported so first

Upgrade Webpack v4 to v5

Simply run

yarn up webpack

Try running NextJs

yarn dev

Still uses webpack v4…

Using webpack 4. Reason: webpack5 flag is set to false in next.config.js https://nextjs.org/docs/messages/webpack5

Change webpack5 to true in next.config.js

module.exports = withTranspileModules(
  withBundleAnalyzer(
    withPWA({
      webpack5: true,
      })
    )
  )

Run NextJs again.

ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.

  • configuration[0].node should be one of these:
    false | object { __dirname?, __filename?, global? }

Fix webpack config

Update webpack config for node. If you were using fs, child_process, net, tls, etc, then needs to be gone, you can disable node config by setting false or setting __dirname, __filename, and global, false.

It will probably build again but the site will perhaps not work. I got the following on my browser console.

caught ReferenceError: __dirname is not defined

So, I just set __dirname to 'mock'.

Update node config for webpack
Update node config for webpack

Storybook build failed

Finally builds without any error, but the storybook seems empty with the following error on the console.

caught Error: Singleton client API not yet initialized, cannot call `addArgTypesEnhancer`.
    at checkMethod (ClientApi.js:89:1)
    at addArgTypesEnhancer (ClientApi.js:125:1)
    at config.js-generated-config-entry.js:46:1
 
Upgrading NextJs v11 to 12 hopefully to 13
Empty looking storybook

The problem seems to be caused due to conflicting versions of @storybook/client-api library.

To check different versions of node dependencies being used by other dependencies, you can use yarn why <package_name>. In my case I did

yarn why @storybook/client-api
|
├─ @storybook/addon-a11y@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.2 (via npm:6.3.2)
│
├─ @storybook/addon-actions@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.2 (via npm:6.3.2)
│
├─ @storybook/addon-controls@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.2 (via npm:6.3.2)
│
├─ @storybook/addon-docs@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.2 (via npm:6.3.2)
│
├─ @storybook/addon-toolbars@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.2 (via npm:6.3.2)
│
├─ @storybook/builder-webpack4@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.2 (via npm:6.3.2)
│
├─ @storybook/builder-webpack4@npm:6.5.16
│  └─ @storybook/client-api@npm:6.5.16 (via npm:6.5.16)
│
├─ @storybook/builder-webpack4@npm:6.3.2 [1742b]
│  └─ @storybook/client-api@npm:6.3.2 [43f8e] (via npm:6.3.2 [43f8e])
│
├─ @storybook/builder-webpack4@npm:6.5.16 [a132b]
│  └─ @storybook/client-api@npm:6.5.16 [2f98e] (via npm:^6.5.16 [2f98e])
│
├─ @storybook/builder-webpack5@npm:6.5.16
│  └─ @storybook/client-api@npm:6.5.16 (via npm:6.5.16)
│
├─ @storybook/core-client@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.2 (via npm:6.3.2)
│
├─ @storybook/core-client@npm:6.5.16
│  └─ @storybook/client-api@npm:6.5.16 (via npm:6.5.16)
│
├─ @storybook/core-client@npm:6.5.16 [00f21]
│  └─ @storybook/client-api@npm:6.5.16 [16c6f] (via npm:^6.5.16 [16c6f])
│
├─ @storybook/core-client@npm:6.3.2 [1b6b0]
│  └─ @storybook/client-api@npm:6.3.2 [c8ea3] (via npm:6.3.2 [c8ea3])
│
├─ @storybook/core-client@npm:6.3.2 [2a8cc]
│  └─ @storybook/client-api@npm:6.3.2 [43f8e] (via npm:6.3.2 [43f8e])
│
├─ @storybook/core-client@npm:6.5.16 [73af3]
│  └─ @storybook/client-api@npm:6.5.16 [2f98e] (via npm:^6.5.16 [2f98e])
│
├─ @storybook/core-client@npm:6.3.2 [87507]
│  └─ @storybook/client-api@npm:6.3.2 [c8ea3] (via npm:6.3.2 [c8ea3])
│
├─ @storybook/core-client@npm:6.5.16 [a132b]
│  └─ @storybook/client-api@npm:6.5.16 [2f98e] (via npm:^6.5.16 [2f98e])
│
└─ @storybook/core-client@npm:6.3.2 [d8fb9]
   └─ @storybook/client-api@npm:6.3.2 [43f8e] (via npm:6.3.2 [43f8e])

As you see lots of different versions of @storybook/client-api is required by different other dependencies.

To enforce a particular version, add resolutions in your package.json.

"resolutions": {
    ...
    "@storybook/client-api": "~6.3.13"
  }

And specifically, 6.3 worked for me. After adding the resolution, all dependencies now points to that same version of @storybook/client-api

yarn why @storybook/client-api
├─ @myorg/project-ui@workspace:packages/ui [10193]
│  └─ @storybook/client-api@npm:6.3.13 [2f98e] (via npm:~6.3.13 [2f98e])
|
├─ @storybook/addon-a11y@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.13 (via npm:~6.3.13)
│
├─ @storybook/addon-actions@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.13 (via npm:~6.3.13)
│
├─ @storybook/addon-controls@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.13 (via npm:~6.3.13)
│
├─ @storybook/addon-docs@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.13 (via npm:~6.3.13)
│
├─ @storybook/addon-toolbars@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.13 (via npm:~6.3.13)
│
├─ @storybook/builder-webpack4@npm:6.3.2
│  └─ @storybook/client-api@npm:6.3.13 (via npm:~6.3.13)
│
├─ @storybook/builder-webpack5@npm:6.5.16
│  └─ @storybook/client-api@npm:6.3.13 (via npm:~6.3.13)

And just to match the rest of the packages with it I downgraded all @storybook packages to 6.3

    "@storybook/addon-docs": "~6.3.13",
    "@storybook/addon-viewport": "~6.3.13",
    "@storybook/builder-webpack5": "~6.3.13",
    "@storybook/client-api": "~6.3.13",
    "@storybook/manager-webpack5": "~6.3.13",
    "@storybook/react": "~6.3.13",

Now the tests fail

I had switched from “@storybook/react-testing”: “^0.0.3” to “@storybook/testing-react”: “^2.0.0”,
It is really confusing, it seems like the repository was renamed at some point, why? God knows. Tried Google to find an answer but could not find relevant info.

“@storybook/testing-react”: “^2.0.0”,

Obviously, I had to go and update every test file to update the imports.

- import { composeStory } from '@storybook/react-testing';
+ import { composeStory } from '@storybook/testing-react';

With @storybook/testing-react v 1.3.0 starting the storybook failed with the following error

 TS2322: Type '{ onView: Mock<any, any>; }' is not assignable to type 'IntrinsicAttributes & Partial<unknown>'.
  Property 'onView' does not exist on type 'IntrinsicAttributes & Partial<unknown>'.

Upgrading to 2.0 suppressed that error while running the storybook, but the same error appears when running the tests.

Also, things look like have changed for getByRole(‘link’, {name: ‘XYZ’}). They seem to take content from the children of the link rather than it used to from the title attribute of the anchor tag. So need to change all those.

screen.getByRole('link', { name: '...' ...

You will need to change the value for the name to whatever is shown in the log.

Next was Story components composed using composeStory() throws type error if you are adding additional attributes/props like below


const Story = composeStory(Component, Meta);
...
      // @ts-expect-error Apparently composeStory doesnt accept additional props, so until we find out a fix
      render(<Story onChange={jest.fn()} />);

To ignore that for time being I just added @ts-expect-error with a note.

This is not a fix but I was certain that this was not going to break anything as they had been working okay so far.

Upgrading NextJs from v11 to v12

To be precise,

yarn add next@12.3.4

Harmless warning appeared!

warn  - Invalid next.config.js options detected:
- The root value has an unexpected property, ... pwa... basePath, ...

I thought I ll tackle that later.

Dev run works fine without any changes whatsoever 🎉

next build failed with some type error related to pageProps in _app.ts

The reason why the type error occurred was because of incompatible versions of NextJs between packages in the mono repo.

I added a resolution in the base package.json

"resolutions": {
   ...
   "next": "^12.0.0"
   ...
}

A very unexpected one, where I had to add, e.stopPropagation() to a click event handler that was used to close popups when clicking elsewhere on the page when a popup is open, to stop it from closing the popup as soon as it is opened by clicking on a trigger button.

My tests needed babel

Could not get my tests working with swc transform from next/jest. It was easier just to add back the babel.config.js and add forceSwcTransforms to the next.config, so that the next is built using SWC where as tests use babel.

experimental: {
    forceSwcTransforms: true
  },

And last thing that was bothering me was Storybook logging way to much info for webpack build progress.

To disable the verbose logging from storybook, added following to /.storybook/main.js

// Disable ProgressPlugin which logs verbose webpack build progress. 
    config.plugins = config.plugins.filter(({ constructor }) => constructor.name !== 'ProgressPlugin');
    

Back to the harmless warning “Invalid next.config.js options detected: – The root value has an unexpected property”

The reason why next warned is that there is only fixed set of config options we can use. In my case I was using PWA plugin. For which, I had a config entry as pwa. Which had to be removed and there was a new way to add PWA plugin to the config.

const withPWA = require('next-pwa')({
  dest: 'public',
  disable: process.env.NODE_ENV === 'development',
  runtimeCaching
});

and later

withPWA(nextConfig)

To add type checking add

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
Previous
Live coding – Flappy Bird game using P5js
Next
ESP32-S3 Pinout for WROOM-1 module
© 2024 Anil Maharjan