vercel / vercel/next.js

Next does not tree-shake Zod correctly

Open
#88,643 3 comments 17 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

linear: turbopack Module Resolution Turbopack
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

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/A
Which 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
  1. Importing zod instead of zod/mini in the zodder component seems to work. Locales are not present anymore.
  2. 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.

  1. Removing the line export { z }; in zod/v4/mini/index.js seems to work. Notice that the import line when using the standard import * as z from 'zod' (which is just zod/index.js -> ./v4/classic/external.js) has a similar line in zod/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

https://github.com/colinhacks/zod/issues/4433
https://github.com/colinhacks/zod/issues/4572
https://github.com/colinhacks/zod/issues/4637
https://github.com/colinhacks/zod/issues/4798
https://github.com/colinhacks/zod/issues/5206
https://github.com/colinhacks/zod/issues/5561

I also created an identical issue in Zod:
https://github.com/colinhacks/zod/issues/5641

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked reproduction repository and run npm i, npm run build, then npx next experimental-analyze. Inspect the bundle for Zod locales and compare the zod/mini export path in node_modules/zod/package.json with zod/v4/mini/index.js; done means unused locales are absent when importing zod/mini without editing dependencies.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, next.js, react
Domain
build-system, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.