From eda3a2a19480edc823ee1195382a308e671c58de Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:11:27 -0700 Subject: [PATCH 1/4] feat: Add support for loading UI styles as first CSS stylesheet --- packages/clerk-js/src/ui/new/renderer.tsx | 11 ++++++++--- packages/clerk-js/webpack.config.js | 16 +++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/clerk-js/src/ui/new/renderer.tsx b/packages/clerk-js/src/ui/new/renderer.tsx index a90a5dc750..7359fa885b 100644 --- a/packages/clerk-js/src/ui/new/renderer.tsx +++ b/packages/clerk-js/src/ui/new/renderer.tsx @@ -1,10 +1,9 @@ -// TODO: don't import here -import '@clerk/ui/styles.css'; - +//@ts-ignore - This is treated as a string export by Webpack import { ClerkInstanceContext, OptionsContext } from '@clerk/shared/react'; import type { ClerkHostRouter } from '@clerk/shared/router'; import { ClerkHostRouterContext } from '@clerk/shared/router'; import type { ClerkOptions, LoadedClerk } from '@clerk/types'; +import stylesheetURL from '@clerk/ui/styles.css'; import type { ElementType, ReactNode } from 'react'; import { createElement, lazy } from 'react'; import { createPortal } from 'react-dom'; @@ -43,6 +42,12 @@ export function init({ wrapper }: { wrapper: ElementType }) { rootElement = document.createElement('div'); rootElement.setAttribute('id', 'clerk-components'); document.body.appendChild(rootElement); + + const stylesheet = document.createElement('link'); + stylesheet.href = stylesheetURL; + stylesheet.rel = 'stylesheet'; + // Add as first stylesheet so that application styles take precedence over our styles. + document.head.prepend(stylesheet); } const root = createRoot(rootElement); diff --git a/packages/clerk-js/webpack.config.js b/packages/clerk-js/webpack.config.js index 235bad38b4..f3ba0d186e 100644 --- a/packages/clerk-js/webpack.config.js +++ b/packages/clerk-js/webpack.config.js @@ -106,9 +106,6 @@ const common = ({ mode }) => { }, }, }, - experiments: { - css: true, - }, }; }; @@ -173,12 +170,21 @@ const typescriptLoaderDev = () => { }; }; +/** @type { () => (import('webpack').RuleSetRule) } */ +const clerkUICSSLoader = () => { + // This emits a module exporting the URL to the styles.css file. + return { + test: /packages\/ui\/dist\/styles\.css/, + type: 'asset/resource', + }; +}; + /** @type { () => (import('webpack').Configuration) } */ const commonForProd = () => { return { devtool: undefined, module: { - rules: [svgLoader(), typescriptLoaderProd()], + rules: [svgLoader(), typescriptLoaderProd(), clerkUICSSLoader()], }, output: { path: path.resolve(__dirname, 'dist'), @@ -297,7 +303,7 @@ const devConfig = ({ mode, env }) => { const commonForDev = () => { return { module: { - rules: [svgLoader(), typescriptLoaderDev()], + rules: [svgLoader(), typescriptLoaderDev(), clerkUICSSLoader()], }, plugins: [ new ReactRefreshWebpackPlugin({ overlay: { sockHost: devUrl.host } }), From eeee976c504910ab29099a6ddfe3254742fff851 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:24:33 -0700 Subject: [PATCH 2/4] fix: Put ts-ignore in correct place --- packages/clerk-js/src/ui/new/renderer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clerk-js/src/ui/new/renderer.tsx b/packages/clerk-js/src/ui/new/renderer.tsx index 7359fa885b..d9dc5f61af 100644 --- a/packages/clerk-js/src/ui/new/renderer.tsx +++ b/packages/clerk-js/src/ui/new/renderer.tsx @@ -1,8 +1,8 @@ -//@ts-ignore - This is treated as a string export by Webpack import { ClerkInstanceContext, OptionsContext } from '@clerk/shared/react'; import type { ClerkHostRouter } from '@clerk/shared/router'; import { ClerkHostRouterContext } from '@clerk/shared/router'; import type { ClerkOptions, LoadedClerk } from '@clerk/types'; +//@ts-ignore - This is treated as a string export by Webpack import stylesheetURL from '@clerk/ui/styles.css'; import type { ElementType, ReactNode } from 'react'; import { createElement, lazy } from 'react'; From 11cff3c2cb64797103619d9a248074c8fe84e4cc Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Mon, 7 Oct 2024 11:22:12 -0700 Subject: [PATCH 3/4] fix(clerk-js): Declare module type for UI stylesheet --- packages/clerk-js/global.d.ts | 4 ---- packages/clerk-js/src/global.d.ts | 4 ++++ packages/clerk-js/src/ui/new/renderer.tsx | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 packages/clerk-js/global.d.ts create mode 100644 packages/clerk-js/src/global.d.ts diff --git a/packages/clerk-js/global.d.ts b/packages/clerk-js/global.d.ts deleted file mode 100644 index 4684851c62..0000000000 --- a/packages/clerk-js/global.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.module.scss' { - const content: Record; - export default content; -} diff --git a/packages/clerk-js/src/global.d.ts b/packages/clerk-js/src/global.d.ts new file mode 100644 index 0000000000..4882a05c18 --- /dev/null +++ b/packages/clerk-js/src/global.d.ts @@ -0,0 +1,4 @@ +declare module '@clerk/ui/styles.css' { + const content: string; + export default content; +} diff --git a/packages/clerk-js/src/ui/new/renderer.tsx b/packages/clerk-js/src/ui/new/renderer.tsx index d9dc5f61af..b7c74ba3a0 100644 --- a/packages/clerk-js/src/ui/new/renderer.tsx +++ b/packages/clerk-js/src/ui/new/renderer.tsx @@ -2,7 +2,6 @@ import { ClerkInstanceContext, OptionsContext } from '@clerk/shared/react'; import type { ClerkHostRouter } from '@clerk/shared/router'; import { ClerkHostRouterContext } from '@clerk/shared/router'; import type { ClerkOptions, LoadedClerk } from '@clerk/types'; -//@ts-ignore - This is treated as a string export by Webpack import stylesheetURL from '@clerk/ui/styles.css'; import type { ElementType, ReactNode } from 'react'; import { createElement, lazy } from 'react'; From 4380da23f3261157276d511784e1859000a7fc08 Mon Sep 17 00:00:00 2001 From: Dylan Staley <88163+dstaley@users.noreply.github.com> Date: Mon, 7 Oct 2024 11:47:36 -0700 Subject: [PATCH 4/4] feat(clerk-js): Only add stylesheet if not present --- packages/clerk-js/src/ui/new/renderer.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/clerk-js/src/ui/new/renderer.tsx b/packages/clerk-js/src/ui/new/renderer.tsx index b7c74ba3a0..4c6623c3f0 100644 --- a/packages/clerk-js/src/ui/new/renderer.tsx +++ b/packages/clerk-js/src/ui/new/renderer.tsx @@ -42,11 +42,17 @@ export function init({ wrapper }: { wrapper: ElementType }) { rootElement.setAttribute('id', 'clerk-components'); document.body.appendChild(rootElement); - const stylesheet = document.createElement('link'); - stylesheet.href = stylesheetURL; - stylesheet.rel = 'stylesheet'; - // Add as first stylesheet so that application styles take precedence over our styles. - document.head.prepend(stylesheet); + // Just for completeness, we check to see if we've already added the stylesheet to the DOM. + const STYLESHEET_SIGIL = 'data-clerk-styles'; + const existingStylesheet = document.querySelector(`link[${STYLESHEET_SIGIL}]`); + if (!existingStylesheet) { + const stylesheet = document.createElement('link'); + stylesheet.href = stylesheetURL; + stylesheet.rel = 'stylesheet'; + stylesheet.setAttribute(STYLESHEET_SIGIL, ''); + // Add as first stylesheet so that application styles take precedence over our styles. + document.head.prepend(stylesheet); + } } const root = createRoot(rootElement);