Skip to content
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

feat: adapt global styles in WCs SSR #502

Merged
merged 2 commits into from
Sep 30, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const i18nCode = 3072;
const brisaSize = 5743; // TODO: Reduce this size :/
const webComponents = 1144;
const unsuspenseSize = 217;
const rpcSize = 2468; // TODO: Reduce this size
const rpcSize = 2467; // TODO: Reduce this size
const lazyRPCSize = 4171; // TODO: Reduce this size
// lazyRPC is loaded after user interaction (action, link),
// so it's not included in the initial size
Expand Down
21 changes: 21 additions & 0 deletions packages/brisa/src/utils/ssr-web-component/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -856,5 +856,26 @@ describe('utils', () => {
expect(output[2][0][2][0][2][0]).toBe('span');
expect(output[2][0][2][0][2][2]).toBe('bar');
});

it('should add style with the CSS_FILES imports when CSS_FILES comes and is not skipping global styles', async () => {
globalThis.mockConstants = {
...getConstants(),
CSS_FILES: ['foo.css', 'bar.css'],
} as unknown as BrisaConstants;
const Component = ({ foo }: any) => <div>{foo}</div>;
const selector = 'web-component';
const output = (await SSRWebComponent(
{
'ssr-Component': Component,
'ssr-selector': selector,
foo: <span id="server-part">bar</span>,
},
requestContext,
)) as any;

expect(output[2][0][2][2][1]).toEqual({
html: `<style>@import '/foo.css';@import '/bar.css'</style>`,
});
});
});
});
17 changes: 15 additions & 2 deletions packages/brisa/src/utils/ssr-web-component/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { toInline } from '@/helpers';
import { Fragment as BrisaFragment } from '@/jsx-runtime';
import type { RequestContext } from '@/types';
import { getConstants } from '@/constants';
import dangerHTML from '../danger-html';

export const AVOID_DECLARATIVE_SHADOW_DOM_SYMBOL = Symbol.for(
'AVOID_DECLARATIVE_SHADOW_DOM',
Expand Down Expand Up @@ -31,7 +32,7 @@ export default async function SSRWebComponent(
selector = props.selector;
}

const { WEB_CONTEXT_PLUGINS } = getConstants();
const { WEB_CONTEXT_PLUGINS, CSS_FILES } = getConstants();
const showContent = !store.has(AVOID_DECLARATIVE_SHADOW_DOM_SYMBOL);
const self = { shadowRoot: {}, attachInternals: voidFn } as any;
let style = '';
Expand Down Expand Up @@ -98,21 +99,33 @@ export default async function SSRWebComponent(
}
}

// This should be calculated after the Component execution because the devs can
// skip global CSS setting adoptedStyleSheets to an empty array
// (this approach works in both worlds: SSR + client-side)
const skipGlobalCSS = self.shadowRoot.adoptedStyleSheets?.length === 0;
const useCSSImports = !skipGlobalCSS && CSS_FILES.length > 0;

return (
// @ts-ignore
<Selector key={__key} {...props} __isWebComponent>
{showContent && (
<template
shadowrootmode="open"
// @ts-ignore
__skipGlobalCSS={self.shadowRoot.adoptedStyleSheets?.length === 0}
__skipGlobalCSS={skipGlobalCSS}
>
{content}
{style.length > 0 && <style>{toInline(style)}</style>}
{useCSSImports &&
dangerHTML(`<style>${getCSSImports(CSS_FILES)}</style>`)}
</template>
)}
{/* @ts-ignore */}
<BrisaFragment slot="">{props.children}</BrisaFragment>
</Selector>
);
}

function getCSSImports(CSS_FILES: string[]) {
return CSS_FILES.map((file) => `@import '/${file}'`).join(';');
}
Loading