clerk / javascript

Official Javascript repository for Clerk authentication
https://clerk.com
MIT License
1.05k stars 238 forks source link

Decrease the bundle size #1847

Closed hornta closed 10 months ago

hornta commented 11 months ago

Preliminary Checks

Description

Clerk is almost 50% of my bundle size. It's built with Vite and I only use it like this:

import Clerk from "@clerk/clerk-js";

export const clerkClient = new Clerk(
  import.meta.env.VITE_APP_CLERK_PUBLISHABLE_KEY,
);

It would be nice to have the react clerk package export Clerk so that I can initialize the client outside of React, then I wouldn't need to install the @clerk/clerk-js package.

This report is generated using this rollup plugin https://www.npmjs.com/package/rollup-plugin-analyzer

image

Affected Packages

@clerk/clerk-js

fmoessle commented 11 months ago

I would love to see the separation of authentication logic (clerk.load(), clerk.user...) from the UI parts (clerk.mountSignIn()...). Bundle size seems to be mostly impacted by the UI parts and could only be imported when needed, e.g. a login page.

panteliselef commented 11 months ago

Hello @fmoessle @hornta , could u give the following snippet a try ? Instead of doing

import Clerk from "@clerk/clerk-js";

import Clerk like this

import Clerk from "@clerk/clerk-js/headless";

This should bring the bundle size down significantly.

panteliselef commented 11 months ago

On another note @hornta , do you mind sharing why you have chose to import Clerk like that in an React application ? What are you trying to access from clerk-js that clerk-react does not re-export or does not give you access through hooks ?

hornta commented 11 months ago

@panteliselef That decreases the size, although it's still the largest dependency which is weird because it's "just authentication" compared to for example the react footprint :-) But I'm OK with it being like this for now.

For some reason vscode couln't find out that the package exported that and there seems to be no typings for this headless as well, but it works at runtime and it can build it.

On another note @hornta , do you mind sharing why you have chose to import

I need to use Clerk outside of the "react world", for example in redux toolkit querys createApi and in react router dom createBrowserRouter.

image

hornta commented 11 months ago

I mean for what Clerk do, it being larger than or equally large as react feels like it has unoptimized code and/or imports things bundlers can't treeshake away. It's mostly communication with Clerk backend.

fmoessle commented 11 months ago

I also experience missing types. As a workaround, you can import the type like this

import type ClerkType from '@clerk/clerk-js'

and tell typescript to handle the headless clerk instance to be of the type

const clerk: ClerkType = new Clerk('...')
fmoessle commented 11 months ago

@panteliselef If using '@clerk/clerk-js/headless' what is the suggested way of loading the UI-Components later on?

I ended up having two instances of clerk in my app: 1 global instance ('@clerk/clerk-js/headless') and the other only on my login page ('@clerk/clerk-js')

panteliselef commented 11 months ago

@panteliselef If using '@clerk/clerk-js/headless' what is the suggested way of loading the UI-Components later on?

I ended up having two instances of clerk in my app: 1 global instance ('@clerk/clerk-js/headless') and the other only on my login page ('@clerk/clerk-js')

@fmoessle I believe the following would work for you


import Clerk from "@clerk/clerk-js/headless";

const clerkJSinstance = new Clerk(
  import.meta.env.VITE_APP_CLERK_PUBLISHABLE_KEY,
);

<ClerkProvider Clerk={clerkJSinstance}>
 {...}
</ClerkProvider>