I regularly work in a codebase running on Next.js 12, and recently updated its TypeScript dependency to 4.9, looking forward to being able to take advantage of useful new features such as the satisfies
operator.
Unfortunately, the moment I tried to use anything 4.9-specific, things went sideways rather quickly, as the dev server and build command didn't recognize the feature, due to their use of SWC. Since Next.js 12 hasn't had new releases for a while, the accompanying version of SWC is now significantly out-of-date.
This wouldn't be an issue if the codebase were on Next.js 13, but we haven't made the jump yet for a variety of reasons. Fortunately, I was able to overcome this obstacle while remaining on Next.js 12; if you find yourself in a similar situation, hopefully this process can work for you as well.
Version-Pinning SWC
Both npm and yarn provide a way to override installed versions of packages in package.json
: npm through the overrides
property (only in npm 8 or higher), and yarn through the resolutions
property.
Unfortunately, as I found out, yarn's resolutions
property has a long history of not playing well with optionalDependencies
: anything placed into resolutions
is treated as required and will abruptly fail to install if it is, for example, a platform-specific package appropriate for your deploy environment but not your dev environment or vice versa, as is the case here.
Since this particular codebase also relied on yarn, this warranted an impromptu switch to npm to see how overrides
would fare. Fortunately, synp
exists to migrate between package lockfile formats. (npm also evidently supports yarn.lock
files directly, which I only found out after converting, so I didn't put that to the test.)
npm's overrides
had no issue working, with the following configuration:
"overrides": {
"next": {
"@next/swc-darwin-x64": "13.1.6",
"@next/swc-linux-x64-gnu": "13.1.6",
"@swc/helpers": "0.4.14"
}
}
By forcing the version of relevant platform-specific @next/swc-*
packages (in this particular case, OS X for dev and Linux for CI/deployment) to their latest v13 counterparts, and updating @swc/helpers
to match the dependency listed in v13, we can get support for TypeScript's new features while still running Next.js 12, and there don't seem to be any adverse side effects.
Other Potential Gotchas
We've tackled the dev server and build process itself above, but other parts of your toolchain may also require updating to support TypeScript 4.9 if they haven't been in a while. Make sure to test all aspects of local development (including your code editor and its extensions), and of course keep an eye on CI processes when merging the update.
I encountered a couple more hiccups:
Jest
The codebase relied on Jest 27, using babel-jest
and babel-loader
. This similarly ran into issues failing to parse TypeScript 4.9 features. I ended up doing a few things on the way to resolving this:
- Upgraded to Jest 29
- Updated a couple of packages (
isbot
anduuid
) to incorporate fixes that resolved errors that would come up in newer versions of Jest - Switched from
babel-jest
andbabel-loader
tots-jest
(note that this requires a customtsconfig.json
with"jsx": "react"
, as opposed to Next requiring"jsx": "preserve"
)
Prettier
In my case, Prettier was still on a rather old version, so I needed to update it to 2.8 in order for next lint
to pass, since the codebase uses eslint-plugin-prettier
.
Top comments (0)