Skip to content

Commit 90da726

Browse files
authoredAug 6, 2024··
fix(runtime): render component styles at the end of the head tag (#5926)
* fix(runtime): render component styles at the end of the head tag * prettier
1 parent ab8e748 commit 90da726

File tree

2 files changed

+42
-13
lines changed

2 files changed

+42
-13
lines changed
 

‎src/runtime/styles.ts

+10-12
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,17 @@ export const addStyle = (styleContainerNode: any, cmpMeta: d.ComponentRuntimeMet
9292
}
9393

9494
/**
95-
* only attach style tag to <head /> section if:
95+
* attach styles at the end of the head tag if we render shadow components
9696
*/
97-
const injectStyle =
98-
/**
99-
* we render a scoped component
100-
*/
101-
!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation) ||
102-
/**
103-
* we are using shadow dom and render the style tag within the shadowRoot
104-
*/
105-
(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation && styleContainerNode.nodeName !== 'HEAD');
106-
if (injectStyle) {
107-
styleContainerNode.insertBefore(styleElm, styleContainerNode.querySelector('link'));
97+
if (!(cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation)) {
98+
styleContainerNode.append(styleElm);
99+
}
100+
101+
/**
102+
* attach styles at the beginning of a shadow root node if we render shadow components
103+
*/
104+
if (cmpMeta.$flags$ & CMP_FLAGS.shadowDomEncapsulation && styleContainerNode.nodeName !== 'HEAD') {
105+
styleContainerNode.insertBefore(styleElm);
108106
}
109107
}
110108

‎test/end-to-end/src/miscellaneous/renderToString.e2e.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,37 @@ describe('renderToString', () => {
4949
);
5050
});
5151

52+
it('puts style last in the head tag', async () => {
53+
const { html } = await renderToString(
54+
`<html>
55+
<head>
56+
<link rel="preconnect" href="https://some-url.com" />
57+
</head>
58+
59+
<body>
60+
<div class="__next">
61+
<main>
62+
<scoped-car-list cars=${JSON.stringify([vento, beetle])}></scoped-car-list>
63+
</main>
64+
</div>
65+
66+
<script type="module">
67+
import { defineCustomElements } from "./static/loader/index.js";
68+
defineCustomElements().catch(console.error);
69+
</script>
70+
</body>
71+
</html>`,
72+
{ fullDocument: true, serializeShadowRoot: false },
73+
);
74+
75+
expect(html).toContain(
76+
'<link rel="preconnect" href="https://some-url.com"> <style sty-id="sc-scoped-car-list">.sc-scoped-car-list-h{',
77+
);
78+
expect(html).toContain(
79+
'.selected.sc-scoped-car-list{font-weight:bold;background:rgb(255, 255, 210)}</style></head> <body> <div class="__next"> <main> <scoped-car-list cars',
80+
);
81+
});
82+
5283
it('allows to hydrate whole HTML page with using a scoped component', async () => {
5384
const { html } = await renderToString(
5485
`<html>
@@ -79,7 +110,7 @@ describe('renderToString', () => {
79110
* renders hydration styles and custom link tag within the head tag
80111
*/
81112
expect(html).toContain(
82-
'.selected.sc-scoped-car-list{font-weight:bold;background:rgb(255, 255, 210)}</style><link rel="stylesheet" href="whatever.css"> </head> <body> <div class="__next"> <main> <scoped-car-list cars=',
113+
'<link rel="stylesheet" href="whatever.css"> <style sty-id="sc-scoped-car-list">.sc-scoped-car-list-h{display:block;margin:10px;padding:10px;border:1px solid blue}ul.sc-scoped-car-list{display:block;margin:0;padding:0}li.sc-scoped-car-list{list-style:none;margin:0;padding:20px}.selected.sc-scoped-car-list{font-weight:bold;background:rgb(255, 255, 210)}</style></head> <body> <div class="__next"> <main> <scoped-car-list cars=',
83114
);
84115
});
85116
});

0 commit comments

Comments
 (0)
Please sign in to comment.