-
Notifications
You must be signed in to change notification settings - Fork 30.3k
Description
Link to the code that reproduces this issue
https://github.com/DoroGi/nextjs-zod-tree-shaking-issues/tree/main
I created this repo running: npx create-next-app@latest my-app --yes as suggested by NextJS "getting started".
Then, in a second commit, I installed Zod and created a simple client component called Zodder. This component simply imports Zod using import * as z from zod/mini and parses a string.
To Reproduce
- npm i
- npm run build
- npx next experimental-analyze
- navigate to http://localhost:4000/
Current vs. Expected behavior
You will see that the bundle contains all Zod locales, which are unused and very heavy;
I expect they should be tree-shaken away.
I suspect this tree-shaking issue applies to many other packages where the impact is less obvious.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.2.0: Tue Nov 18 21:09:40 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6000
Available memory (MB): 32768
Available CPU cores: 10
Binaries:
Node: 24.11.1
npm: 11.6.2
Yarn: N/A
pnpm: 10.15.0
Relevant Packages:
next: 16.1.2 // Latest available version is detected (16.1.2).
eslint-config-next: N/A
react: 19.2.3
react-dom: 19.2.3
typescript: 5.9.3
Next.js Config:
output: N/AWhich area(s) are affected? (Select all that apply)
Module Resolution
Which stage(s) are affected? (Select all that apply)
next build (local)
Additional context
A few workarounds to make it work:
To try this methods, remember to run each time the line below, so you update the .next and you can check whether the locales are present in the bundle or not:
npm run build && npx next experimental-analyze
- Importing zod instead of zod/mini in the zodder component seems to work. Locales are not present anymore.
- Going into node_modules/zod/package.json and editing the ./mini exports configuration to this seems to work:
"./mini": {
"@zod/source": "./src/mini/index.ts",
"types": "./mini/index.d.cts",
"import": "./v4/mini/external.js", <-- only line changed
"require": "./mini/index.cjs"
},
I did this because ./mini in the package.json links to zod/mini/index.js, which just imports zod/v4/mini/index.js, which just imports zod/v4/mini/externals.js.
- Removing the line
export { z };inzod/v4/mini/index.jsseems to work. Notice that the import line when using the standardimport * as z from 'zod'(which is justzod/index.js->./v4/classic/external.js) has a similar line inzod/index.js, but it's not causing any issue apparently.
Related issues
This seems to have been talked a lot in the zod issues. Everybody seems to have found their solution, the only remaining ones are the issues related to NextJS
colinhacks/zod#4433
colinhacks/zod#4572
colinhacks/zod#4637
colinhacks/zod#4798
colinhacks/zod#5206
colinhacks/zod#5561
I also created an identical issue in Zod:
colinhacks/zod#5641