Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/expo_avoid_web_browser_static_require.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@clerk/clerk-expo': patch
---

Stop statically resolving `expo-web-browser` in native bundles. `ClerkProvider` previously called `require('expo-web-browser')` synchronously inside an `isWeb()` runtime gate, but Metro's static analyzer resolved the literal-string require regardless of the gate, causing production bundling to fail for native consumers who don't install `expo-web-browser` (an optional peer dependency).

The web-only call to `WebBrowser.maybeCompleteAuthSession()` has been moved into a platform-split helper (`maybeCompleteAuthSession.web.ts` for web, no-op `maybeCompleteAuthSession.ts` for native). Behavior on web is unchanged; native bundles no longer reference `expo-web-browser`.
17 changes: 6 additions & 11 deletions packages/expo/src/provider/ClerkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useNativeAuthEvents } from '../hooks/useNativeAuthEvents';
import NativeClerkModule from '../specs/NativeClerkModule';
import { tokenCache as defaultTokenCache } from '../token-cache';
import { isNative, isWeb } from '../utils/runtime';
import { maybeCompleteAuthSession } from './maybeCompleteAuthSession';
import { getClerkInstance } from './singleton';
import type { BuildClerkOptions } from './singleton/types';

Expand Down Expand Up @@ -371,18 +372,12 @@ export function ClerkProvider<TUi extends Ui = Ui>(props: ClerkProviderProps<TUi
void syncNativeAuthToJs();
}, [nativeAuthState, clerkInstance]);

// Needed for `useOAuth` / `useSSO` to work correctly on web — must stay synchronous during render
// so the redirect URL is caught before children mount. Resolves to a no-op on native via the
// sibling `maybeCompleteAuthSession.ts`, which keeps Metro from statically bundling
// `expo-web-browser` (an optional peer) for native consumers.
if (isWeb()) {
// This is needed in order for useOAuth to work correctly on web.
// Must stay synchronous during render to catch the redirect URL before children mount.
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const WebBrowser = require('expo-web-browser');
WebBrowser.maybeCompleteAuthSession();
} catch (e) {
if (__DEV__) {
console.warn('[ClerkProvider] expo-web-browser not available, OAuth/SSO on web will not work:', e);
}
}
maybeCompleteAuthSession();
}

return (
Expand Down
9 changes: 9 additions & 0 deletions packages/expo/src/provider/maybeCompleteAuthSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Native no-op. The web bundle resolves `maybeCompleteAuthSession.web.ts` instead.
*
* `expo-web-browser` is declared as an optional peer dependency of `@clerk/expo` because
* it is only required for OAuth/SSO flows. Importing it synchronously here would cause
* Metro to statically resolve `expo-web-browser` during native bundling — failing the
* build for consumers who do not install it.
*/
export function maybeCompleteAuthSession(): void {}
18 changes: 18 additions & 0 deletions packages/expo/src/provider/maybeCompleteAuthSession.web.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Web-only implementation. Resolved by Metro / the bundler in place of
* `maybeCompleteAuthSession.ts` when targeting `web`.
*
* Must stay synchronous during render so the OAuth/SSO redirect URL is caught
* before children mount.
*/
export function maybeCompleteAuthSession(): void {
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const WebBrowser = require('expo-web-browser');
WebBrowser.maybeCompleteAuthSession();
} catch (e) {
if (__DEV__) {
console.warn('[ClerkProvider] expo-web-browser not available, OAuth/SSO on web will not work:', e);
}
}
}
Loading