Unused Constants From Next/Dist Are Not Tree-Shaken In Client Bundles Due To CJS Resolution
Next.js client bundles include unused constants from next/dist/shared/lib/constants.js and next/dist/lib/constants.js because client entrypoints resolve to CommonJS files, preventing Webpack/Turbopack from performing tree shaking. A user-provided webpack workaround redirects imports to ESM equivalents.
Next.js internally transpiles and points client entrypoints to CommonJS modules under node_modules/next/dist instead of the ESM equivalents under node_modules/next/dist/esm. CJS modules cannot be tree-shaken by bundlers, so unused constants from constants.js remain in the production client bundle. The issue has existed since several commits that use direct CJS imports in client code.
1. Clone https://github.com/seyoon20087/nextjs-constants-not-treeshaked-demo
2. Run `yarn build`
3. Inspect .next/static/chunks/main-*.js and observe unused constants from node_modules/next/dist/shared/lib/constants.js and node_modules/next/dist/lib/constants.js are included.
4. Verify via bundle analysis that no tree-shaking occurs.
This webpack plugin intercepts non-ESM imports from next/dist during client builds and rewrites them to their ESM equivalents under next/dist/esm, if present. ESM enables bundlers to tree-shake unused exports, eliminating unused constants from constants.js. The fallback to CJS preserves modules that lack an ESM version.
Edge Case Audit
This hotfix only works for webpack (not Turbopack) and rewrites all matching next/dist imports; some ESM equivalents may have subtle side-effect differences or missing polyfills that cause runtime errors. Sync filesystem checks may slightly increase build time. Testing in all environments is required. Rollback by removing the webpack plugin from next.config. For Turbopack users, no equivalent workaround currently exists; consider staying on webpack or waiting for an official fix.