-
Notifications
You must be signed in to change notification settings - Fork 426
feat(clerk-js): remove headless variant, add ui prop #7629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
why: when using clerkJSVariant='headless', applications only need control components and don't require the full UI bundle. loading the unnecessary @clerk/ui script adds overhead without providing value. what changed: - clerk-script.tsx: conditionally render clerk-ui script tag only when clerkJSVariant !== 'headless' - integration template: read NEXT_PUBLIC_CLERK_JS_VARIANT env var and pass to ClerkProvider users can now set NEXT_PUBLIC_CLERK_JS_VARIANT='headless' to skip loading the ~100KB @clerk/ui bundle when using only control components.
why: when using clerkJSVariant='headless', applications only need control components and don't require the full UI bundle. loading the unnecessary @clerk/ui script adds overhead without providing value. what changed: - build-clerk-hotload-script: skip generating clerk-ui script tag when clerkJsVariant === 'headless' - create-clerk-instance: getClerkUiEntryChunk returns undefined for headless variant to skip client-side hot-loading users can now set clerkJSVariant='headless' to skip loading the ~100KB @clerk/ui bundle when using only control components.
why: when using clerkJSVariant='headless', applications only need control components and don't require the full UI bundle. loading the unnecessary @clerk/ui script adds overhead without providing value. what changed: isomorphicClerk's getClerkUiEntryChunk method now returns undefined when clerkJSVariant === 'headless', skipping the loadClerkUiScript call entirely. users can now set clerkJSVariant='headless' to skip loading the ~100KB @clerk/ui bundle when using only control components.
why: when using clerkJSVariant='headless', applications only need control components and don't require the full UI bundle. loading the unnecessary @clerk/ui script adds overhead without providing value. what changed: clerkPlugin now checks if clerkJSVariant === 'headless' and skips the loadClerkUiScript call, resolving the clerkUiCtorPromise to undefined instead. users can now set clerkJSVariant='headless' to skip loading the ~100KB @clerk/ui bundle when using only control components.
why: verify that the headless variant correctly skips clerk-ui script injection across the full integration stack (env var → prop → script rendering). what changed: created headless-variant.test.ts that sets CLERK_JS_VARIANT='headless' and asserts clerk-ui script is absent while clerk-js script is present.
…ition The headless variant is no longer needed now that UI components have been moved to @clerk/ui. The browser builds are now identical in size. Changes: - Add `react-native` export condition in package.json for Expo/RN - Rename `clerkHeadless` build to `clerkNative` (no chunk splitting) - Remove `clerkHeadlessBrowser` build (identical to regular browser) - Update Expo to import from `@clerk/clerk-js` instead of `/headless` - Deprecate `clerkJSVariant` option (now ignored) - Delete headless source files and export directory BREAKING CHANGE: `@clerk/clerk-js/headless` import path removed. Expo/React Native users should import from `@clerk/clerk-js` directly.
🦋 Changeset detectedLatest commit: b85a057 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
….com:clerk/javascript into jrad/remove-headless-variant
clerkJSVariant is still used to control whether @clerk/ui loads. The option just no longer affects the clerk-js URL since the separate headless build has been removed.
Replace the clerkJSVariant: 'headless' pattern with a cleaner ui prop API:
- ui: false - Skip loading @clerk/ui (for custom UIs)
- ui: { version?, url? } - Load UI with specific version/URL
- ui: undefined (default) - Load UI normally
Also adds shouldLoadClerkUi() helper function to shared package.
Breaking change: clerkJSVariant is removed in favor of ui prop.
📝 WalkthroughWalkthroughReplaces the 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.changeset/light-eagles-stay.md:
- Around line 1-2: The changeset is empty and must document the breaking changes
introduced: explicitly list affected package names and semver bumps (use major
bumps for breaking changes), describe the removals of clerkJSVariant and the old
import path `@clerk/clerk-js/headless`, and note the new ui prop and its migration
steps; update the changeset body to include a short summary, per-package entries
(e.g., package-name: major), and a brief migration note explaining how to
replace/remove clerkJSVariant, how to update import paths to the new
entrypoints, and how to adopt the new ui prop so consumers can upgrade safely.
In `@packages/expo/src/provider/singleton/createClerkInstance.ts`:
- Around line 1-2: The import path for FapiRequestInit/FapiResponse is invalid;
instead derive request/response types from the public Clerk API: create a
Handler type from Parameters<Clerk["__internal_onBeforeRequest"]>[0], then
extract Req = Parameters<Handler>[0] and use Req as the type for the requestInit
parameter, and similarly extract the response type from
Clerk["__internal_onAfterResponse"] to replace FapiResponse usage; update
function signatures in createClerkInstance.ts to use these derived types
(referencing Clerk, __internal_onBeforeRequest, __internal_onAfterResponse,
Handler, and Req).
🧹 Nitpick comments (1)
packages/react-router/src/client/ReactRouterClerkProvider.tsx (1)
102-109: Type safety concern withas anycasts.The
as anycasts on lines 102 and 108 bypass TypeScript's type checking. While this may be a workaround for complex generic constraints withTUi, it could mask type mismatches at runtime.Consider whether these casts can be replaced with more precise type assertions or if the underlying types can be aligned to avoid the need for
any.
| --- | ||
| --- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty changeset file - missing package entries and description.
This changeset is empty but the PR introduces breaking changes (removal of clerkJSVariant, @clerk/clerk-js/headless import path, new ui prop). The changeset should document affected packages and their semver bumps.
🤖 Prompt for AI Agents
In @.changeset/light-eagles-stay.md around lines 1 - 2, The changeset is empty
and must document the breaking changes introduced: explicitly list affected
package names and semver bumps (use major bumps for breaking changes), describe
the removals of clerkJSVariant and the old import path `@clerk/clerk-js/headless`,
and note the new ui prop and its migration steps; update the changeset body to
include a short summary, per-package entries (e.g., package-name: major), and a
brief migration note explaining how to replace/remove clerkJSVariant, how to
update import paths to the new entrypoints, and how to adopt the new ui prop so
consumers can upgrade safely.
Summary
This PR removes the headless build variant from
@clerk/clerk-jsand introduces a newuiprop to control whether@clerk/uiis loaded.Background
After the UI split to
@clerk/ui, the browser builds are now identical in size:clerk.browser.js= 242Kclerk.headless.browser.js= 242KThe headless build is redundant. A new
uiprop provides cleaner control over UI loading.New
uiProp APIThe
uiprop replacesclerkJSVariant: 'headless':Changes
Build changes:
react-nativeexport condition in package.json for Expo/RNclerkHeadlessbuild →clerkNative(no chunk splitting for RN)clerkHeadlessBrowserbuild (identical to regular browser)@clerk/clerk-jsinstead of/headlessAPI changes:
clerkJSVariantprop (was only used for 'headless')uiprop to skip loading@clerk/uiwhen set tofalseshouldLoadClerkUi()helper in shared packageBreaking Changes
@clerk/clerk-js/headlessimport path removedclerkJSVariantprop removed - useui={false}instead@clerk/clerk-jsdirectlyTest plan
clerk.native.jsis built without chunk splittingui={false}skips loading clerk-uiSummary by CodeRabbit
New Features
Deprecations
Tests
✏️ Tip: You can customize this high-level summary in your review settings.