Skip to content

Commit d433c68

Browse files
authored
Merge pull request #8124 from QwikDev/v2-fix-adding-script-before-style
fix: don't emit script before qwik style element
2 parents 349dcc6 + 0b2db41 commit d433c68

File tree

3 files changed

+65
-8
lines changed

3 files changed

+65
-8
lines changed

.changeset/large-turtles-write.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: don't emit script before qwik style element
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { describe, it, expect, vi } from 'vitest';
2+
import { ssrCreateContainer } from './ssr-container';
3+
import { QStyle } from './qwik-copy';
4+
5+
vi.hoisted(() => {
6+
vi.stubGlobal('QWIK_LOADER_DEFAULT_MINIFIED', 'min');
7+
vi.stubGlobal('QWIK_LOADER_DEFAULT_DEBUG', 'debug');
8+
});
9+
10+
describe('SSR Container', () => {
11+
it('should not emit Qwik loader before style elements', async () => {
12+
const writer = {
13+
chunks: [] as string[],
14+
write(text: string) {
15+
this.chunks.push(text);
16+
},
17+
toString() {
18+
return this.chunks.join('');
19+
},
20+
};
21+
22+
const container = ssrCreateContainer({
23+
tagName: 'div',
24+
writer,
25+
renderOptions: {
26+
qwikLoader: 'inline', // Force inline loader
27+
},
28+
});
29+
30+
// Open container
31+
container.openContainer();
32+
// Add a large content to exceed 30KB while opening the next element
33+
const largeContent = 'x'.repeat(30 * 1024);
34+
container.openElement('div', null);
35+
container.textNode(largeContent);
36+
await container.closeElement();
37+
// Add a style element with QStyle attribute
38+
container.openElement('style', [QStyle, 'my-style-id']);
39+
container.write('.my-class { color: red; }');
40+
await container.closeElement();
41+
// Add another regular elementm
42+
container.openElement('div', null);
43+
await container.closeElement();
44+
await container.closeContainer();
45+
46+
const html = writer.toString();
47+
expect(html.indexOf('id="qwikloader"')).toBeGreaterThan(html.indexOf('my-style-id'));
48+
});
49+
});

packages/qwik/src/server/ssr-container.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,6 @@ class SSRContainer extends _SharedContainer implements ISSRContainer {
350350
openContainer() {
351351
if (this.tag == 'html') {
352352
this.write('<!DOCTYPE html>');
353-
// -1 so we only emit inside body
354-
this.$noScriptHere$ = -1;
355353
}
356354

357355
const containerAttributes = this.renderOptions.containerAttributes || {};
@@ -383,7 +381,6 @@ class SSRContainer extends _SharedContainer implements ISSRContainer {
383381
return this.closeElement();
384382
}
385383

386-
// -1 so we only emit inside body
387384
private $noScriptHere$: number = 0;
388385

389386
/** Renders opening tag for DOM element */
@@ -393,21 +390,27 @@ class SSRContainer extends _SharedContainer implements ISSRContainer {
393390
constAttrs?: SsrAttrs | null,
394391
currentFile?: string | null
395392
): string | undefined {
396-
if (this.qlInclude === QwikLoaderInclude.Inline) {
397-
if (this.$noScriptHere$ === 0 && this.size > 30 * 1024) {
393+
const isQwikStyle =
394+
isQwikStyleElement(elementName, varAttrs) || isQwikStyleElement(elementName, constAttrs);
395+
396+
if (
397+
// don't append qwik loader before qwik style elements
398+
// it will confuse the resuming, because styles are expected to be the first nodes in subtree
399+
!isQwikStyle &&
400+
this.qlInclude === QwikLoaderInclude.Inline
401+
) {
402+
if (this.$noScriptHere$ === 0 && this.size > 30 * 1024 && elementName !== 'body') {
398403
// We waited long enough, on slow connections the page is already partially visible
399404
this.emitQwikLoaderInline();
400405
}
401406
// keep track of noscript and template, and for html we only emit inside body
402-
else if (elementName === 'noscript' || elementName === 'template' || elementName === 'body') {
407+
else if (elementName === 'noscript' || elementName === 'template') {
403408
this.$noScriptHere$++;
404409
}
405410
}
406411

407412
let innerHTML: string | undefined = undefined;
408413
this.lastNode = null;
409-
const isQwikStyle =
410-
isQwikStyleElement(elementName, varAttrs) || isQwikStyleElement(elementName, constAttrs);
411414
if (!isQwikStyle && this.currentElementFrame) {
412415
vNodeData_incrementElementCount(this.currentElementFrame.vNodeData);
413416
}

0 commit comments

Comments
 (0)