-
-
Notifications
You must be signed in to change notification settings - Fork 150
Bug: Duplicate <style> tags per component instance with serializeShadowRoot: 'scoped' in Next.js runtime SSR #773
Copy link
Copy link
Open
Labels
needs reproductiona code reproduction is needed from the issue authora code reproduction is needed from the issue authortype: bugSomething isn't workingSomething isn't working
Description
Bug Description
When using serializeShadowRoot: "scoped" with the Next.js runtime-based SSR approach, each component instance renders with duplicate <style> tags in the server-rendered HTML. This leads to unnecessary bloat in the SSR output and potential performance issues.
Reproduction
Setup
- Next.js 15 with React 19
@stencil/react-output-targetwith runtime-based SSR- Stencil component with
shadow: trueand scoped styles - Using
serializeShadowRoot: "scoped"option
Steps to Reproduce
- Create a Stencil component with shadow DOM and styles (e.g.,
my-counter) - Set up Next.js runtime SSR with
serializeShadowRoot: "scoped" - Render multiple instances of the same component on a page
- View the SSR'd HTML source
Demo Code
A demonstration page has been created in the local branch demo/scoped-style-duplication-bug:
- File:
example-project/next-15-runtime-based/src/app/dedup-test/page.tsx - Renders: 5 instances of
<MyCounter />component
import { MyCounter } from 'component-library-react/next';
export default function DedupTest() {
return (
<div style={{ padding: '2rem' }}>
<h1>Style Deduplication Test</h1>
<p>This page renders 5 instances of MyCounter to demonstrate style deduplication.</p>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<MyCounter />
<MyCounter />
<MyCounter />
<MyCounter />
<MyCounter />
</div>
</div>
);
}Expected Behavior
When rendering 5 instances of MyCounter, the scoped styles should be deduplicated:
- ✅ Expected: Single
<style>tag (or shared style component) for all instances - ✅ Expected: Lightweight instance wrappers that reference the shared styles
Actual Behavior
Currently, each component instance gets its own duplicate <style> tag:
- ❌ Actual: 5 instances = 5 identical
<style>tags - ❌ Actual: Each instance wrapper includes the full CSS
Performance Issues
- HTML Bloat: With N instances, styles are duplicated N times
- Bandwidth: Larger SSR payloads, especially for components with extensive styles
- Parse Time: Browser has to parse duplicate style blocks
- Memory: More DOM nodes than necessary
Environment
- Package:
@stencil/react-output-target - Version: Latest (main branch)
- Framework: Next.js 15 + React 19
- SSR Mode: Runtime-based with
serializeShadowRoot: "scoped"
Verification
To verify this bug:
- Checkout the demo branch:
git checkout demo/scoped-style-duplication-bug - Build the component library:
cd example-project/component-library && npm run build - Build the React library:
cd ../component-library-react && npm run build - Run Next.js dev server:
cd ../next-15-runtime-based && npm run dev - Navigate to
/dedup-test - View page source (disable JavaScript to see pure SSR output)
- Search for
<style>tags - you'll find 5 duplicate blocks
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
needs reproductiona code reproduction is needed from the issue authora code reproduction is needed from the issue authortype: bugSomething isn't workingSomething isn't working