clerk / clerk/javascript

@clerk/nextjs: no subpath export for ClerkProvider, so the root barrel puts every UI component into an App Router app's first load

Open
#9,476 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
1.8k
Forks
472
Avg merge
2d 11h
Merged PRs (30d)
189

Description

Package

@clerk/nextjs@7.7.0 (re-checked against 7.7.7 — unchanged)

What

An App Router root layout must import ClerkProvider, and the only supported specifier is the root barrel:

// app/layout.tsx — a Server Component
import { ClerkProvider } from "@clerk/nextjs";

dist/esm/index.js statically imports three "use client" modules — client-boundary/uiComponents, client-boundary/controlComponents, client-boundary/hooks — alongside the provider. A Server Component importing a "use client" barrel registers every export of that barrel as a client reference, whether or not it renders them. So an app that renders one <UserButton> ships the client wrappers for PricingTable, OrganizationProfile, OrganizationSwitcher, APIKeys, Waitlist and the rest, on every route.

The package's own exports map has no client-component subpath and no wildcard:

".", "./server", "./errors", "./internal", "./webhooks", "./experimental", "./legacy", "./types"

/internal is not an alternative — it imports client-boundary/uiComponents itself.

The provider is already clean internally

ClerkProvider resolves through the package-private #components condition (declared in dist/esm/package.json) to dist/esm/components.server.js, which imports none of the UI modules:

// dist/esm/components.server.js
import { ClerkProvider } from "./app-router/server/ClerkProvider";
import { Show } from "./app-router/server/controlComponents";

A specifier landing there would give an App Router app the provider without the UI barrel. There just isn't one — #components is package-private and the root exports map has no wildcard.

Measured

Nine cold production builds of a Next.js 16 App Router app (Turbopack, Cache Components), NEXT_SERVER_ACTIONS_ENCRYPTION_KEY pinned so builds are byte-comparable; the reverted tree rebuilt byte-identical to the baseline:

configuration total client JS (gz) Δ
as shipped today 579,569
provider aliased to components.server.js + every Clerk component behind one client module 574,801 −4,768

That −4,768 gz (0.82% of the app's client JS) is what a supported subpath would buy for free. Reaching it today needs a bundler alias onto dist/esm/components.server.js — a path outside your exports map, through a condition the alias bypasses — which we measured, priced and then declined to ship: a rename on your side fails our build loudly (fine), but a content change fails nothing and would land at runtime in the root layout of every page.

Ask

A supported subpath that exports ClerkProvider (and Show) without the client-component barrel — e.g. @clerk/nextjs/provider, or simply exposing what #components already resolves to under the react-server condition. Naming it in exports is most of the work; the module exists.

Related

Filed alongside a request for sideEffects: false on @clerk/react and @clerk/shared, which is the other half — with a subpath but without that flag, @clerk/react's rollup-merged dist still carries the UI implementations into the provider's chunk.

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 by inspecting the package exports map and the existing dist/esm/components.server.js and dist/esm/package.json entries, then compare them with dist/esm/index.js. Add a supported subpath or react-server export for ClerkProvider and Show without the UI barrel, and verify it with the App Router production build measurement described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs, react, typescript
Domain
build-system, frontend, performance
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
56/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.