diff --git a/.changeset/olive-humans-leave.md b/.changeset/olive-humans-leave.md new file mode 100644 index 0000000000..01f1ef14f3 --- /dev/null +++ b/.changeset/olive-humans-leave.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': minor +--- + +Lazily load components related to `` functionality when used with the combined flow in ``. diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index fe0ea8fb26..7f2ac0b297 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -11,8 +11,8 @@ { "path": "./dist/organizationprofile*.js", "maxSize": "12KB" }, { "path": "./dist/organizationswitcher*.js", "maxSize": "5KB" }, { "path": "./dist/organizationlist*.js", "maxSize": "5.5KB" }, - { "path": "./dist/signin*.js", "maxSize": "12.1KB" }, - { "path": "./dist/signup*.js", "maxSize": "10KB" }, + { "path": "./dist/signin*.js", "maxSize": "12.4KB" }, + { "path": "./dist/signup*.js", "maxSize": "6.4KB" }, { "path": "./dist/userbutton*.js", "maxSize": "5KB" }, { "path": "./dist/userprofile*.js", "maxSize": "15KB" }, { "path": "./dist/userverification*.js", "maxSize": "5KB" }, diff --git a/packages/clerk-js/rspack.config.js b/packages/clerk-js/rspack.config.js index 9c6b23a7c6..68b3df3ec3 100644 --- a/packages/clerk-js/rspack.config.js +++ b/packages/clerk-js/rspack.config.js @@ -85,6 +85,14 @@ const common = ({ mode, disableRHC = false }) => { name: 'coinbase-wallet-sdk', chunks: 'all', }, + /** + * Sign up is shared between the SignUp component and the SignIn component. + */ + signUp: { + minChunks: 1, + name: 'signup', + test: module => module.resource && module.resource.includes('/ui/components/SignUp'), + }, common: { minChunks: 1, name: 'ui-common', diff --git a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx index a767b6dbf1..c30b60ed5a 100644 --- a/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx +++ b/packages/clerk-js/src/ui/components/SignIn/SignIn.tsx @@ -13,12 +13,16 @@ import { withCoreSessionSwitchGuard, } from '../../contexts'; import { Flow } from '../../customizables'; +import { useFetch } from '../../hooks'; import { Route, Switch, VIRTUAL_ROUTER_BASE_PATH } from '../../router'; -import { SignUpContinue } from '../SignUp/SignUpContinue'; -import { SignUpSSOCallback } from '../SignUp/SignUpSSOCallback'; -import { SignUpStart } from '../SignUp/SignUpStart'; -import { SignUpVerifyEmail } from '../SignUp/SignUpVerifyEmail'; -import { SignUpVerifyPhone } from '../SignUp/SignUpVerifyPhone'; +import { + LazySignUpContinue, + LazySignUpSSOCallback, + LazySignUpStart, + LazySignUpVerifyEmail, + LazySignUpVerifyPhone, + preloadSignUp, +} from './lazy-sign-up'; import { ResetPassword } from './ResetPassword'; import { ResetPasswordSuccess } from './ResetPasswordSuccess'; import { SignInAccountSwitcher } from './SignInAccountSwitcher'; @@ -76,22 +80,23 @@ function SignInRoutes(): JSX.Element { redirectUrl='../factor-two' /> + {signInContext.isCombinedFlow && ( !!clerk.client.signUp.emailAddress} > - + !!clerk.client.signUp.phoneNumber} > - + - !!clerk.client.signUp.emailAddress} > - + !!clerk.client.signUp.phoneNumber} > - + - + - + )} + @@ -143,6 +149,9 @@ function SignInRoutes(): JSX.Element { ); } +const usePreloadSignUp = (enabled = false) => + useFetch(enabled ? preloadSignUp : undefined, 'preloadComponent', { staleTime: Infinity }); + function SignInRoot() { const signInContext = useSignInContext(); const normalizedSignUpContext = { @@ -156,6 +165,11 @@ function SignInRoot() { ...normalizeRoutingOptions({ routing: signInContext?.routing, path: signInContext?.path }), } as SignUpContextType; + /** + * Preload Sign Up when in Combined Flow. + */ + usePreloadSignUp(signInContext.isCombinedFlow); + return ( diff --git a/packages/clerk-js/src/ui/components/SignIn/handleCombinedFlowTransfer.ts b/packages/clerk-js/src/ui/components/SignIn/handleCombinedFlowTransfer.ts index 1337057372..c9b426a795 100644 --- a/packages/clerk-js/src/ui/components/SignIn/handleCombinedFlowTransfer.ts +++ b/packages/clerk-js/src/ui/components/SignIn/handleCombinedFlowTransfer.ts @@ -2,7 +2,7 @@ import type { LoadedClerk, SignUpModes, SignUpResource } from '@clerk/types'; import { SIGN_UP_MODES } from '../../../core/constants'; import type { RouteContextValue } from '../../router/RouteContext'; -import { completeSignUpFlow } from '../SignUp/util'; +import { lazyCompleteSignUpFlow } from './lazy-sign-up'; type HandleCombinedFlowTransferProps = { identifierAttribute: 'emailAddress' | 'phoneNumber' | 'username'; @@ -65,7 +65,8 @@ export function handleCombinedFlowTransfer({ .create({ [identifierAttribute]: identifierValue, }) - .then(res => { + .then(async res => { + const completeSignUpFlow = await lazyCompleteSignUpFlow(); return completeSignUpFlow({ signUp: res, verifyEmailPath: 'create/verify-email-address', diff --git a/packages/clerk-js/src/ui/components/SignIn/lazy-sign-up.ts b/packages/clerk-js/src/ui/components/SignIn/lazy-sign-up.ts new file mode 100644 index 0000000000..e3c08113fd --- /dev/null +++ b/packages/clerk-js/src/ui/components/SignIn/lazy-sign-up.ts @@ -0,0 +1,22 @@ +import { lazy } from 'react'; + +const preloadSignUp = () => import(/* webpackChunkName: "signUp" */ '../SignUp'); + +const LazySignUpVerifyPhone = lazy(() => preloadSignUp().then(m => ({ default: m.SignUpVerifyPhone }))); +const LazySignUpVerifyEmail = lazy(() => preloadSignUp().then(m => ({ default: m.SignUpVerifyEmail }))); +const LazySignUpStart = lazy(() => preloadSignUp().then(m => ({ default: m.SignUpStart }))); +const LazySignUpSSOCallback = lazy(() => preloadSignUp().then(m => ({ default: m.SignUpSSOCallback }))); +const LazySignUpContinue = lazy(() => preloadSignUp().then(m => ({ default: m.SignUpContinue }))); + +const lazyCompleteSignUpFlow = () => + import(/* webpackChunkName: "signUp" */ '../SignUp/util').then(m => m.completeSignUpFlow); + +export { + preloadSignUp, + LazySignUpVerifyPhone, + LazySignUpVerifyEmail, + LazySignUpStart, + LazySignUpSSOCallback, + LazySignUpContinue, + lazyCompleteSignUpFlow, +}; diff --git a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx index 430ae2f53a..c96abac836 100644 --- a/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx +++ b/packages/clerk-js/src/ui/components/SignUp/SignUp.tsx @@ -117,3 +117,5 @@ export const SignUpModal = (props: SignUpModalProps): JSX.Element => { ); }; + +export { SignUpContinue, SignUpSSOCallback, SignUpStart, SignUpVerifyEmail, SignUpVerifyPhone }; diff --git a/packages/clerk-js/src/ui/hooks/useFetch.ts b/packages/clerk-js/src/ui/hooks/useFetch.ts index ba9337dadb..f7ad937678 100644 --- a/packages/clerk-js/src/ui/hooks/useFetch.ts +++ b/packages/clerk-js/src/ui/hooks/useFetch.ts @@ -103,7 +103,8 @@ export const useFetch = ( useEffect(() => { const fetcherMissing = !fetcherRef.current; - const isCacheStale = Date.now() - (getCache()?.cachedAt || 0) >= staleTime; + const isCacheStale = + typeof getCache()?.cachedAt === 'undefined' ? true : Date.now() - (getCache()?.cachedAt || 0) >= staleTime; const isRequestOnGoing = getCache()?.isValidating ?? false; if (fetcherMissing || !isCacheStale || isRequestOnGoing) {