Skip to content

Commit 2e1e369

Browse files
committed
perf: move overlay template to server side
1 parent 5a31ce8 commit 2e1e369

File tree

3 files changed

+140
-134
lines changed

3 files changed

+140
-134
lines changed

packages/core/src/client/hmr.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ function clearOutdatedErrors() {
4141
}
4242
}
4343

44-
let createOverlay: undefined | ((err: string[]) => void);
44+
let createOverlay: undefined | ((overlay: string, errors: string[]) => void);
4545
let clearOverlay: undefined | (() => void);
4646

4747
export const registerOverlay = (
48-
createFn: (err: string[]) => void,
48+
createFn: (overlay: string, errors: string[]) => void,
4949
clearFn: () => void,
5050
): void => {
5151
createOverlay = createFn;
@@ -91,7 +91,15 @@ function handleWarnings({ text }: { text: string[] }) {
9191
}
9292

9393
// Compilation with errors (e.g. syntax error or missing modules).
94-
function handleErrors({ text, html }: { text: string[]; html: string[] }) {
94+
function handleErrors({
95+
text,
96+
html,
97+
overlay,
98+
}: {
99+
text: string[];
100+
html: string[];
101+
overlay: string;
102+
}) {
95103
clearOutdatedErrors();
96104

97105
isFirstCompilation = false;
@@ -103,7 +111,7 @@ function handleErrors({ text, html }: { text: string[]; html: string[] }) {
103111
}
104112

105113
if (createOverlay) {
106-
createOverlay(html);
114+
createOverlay(overlay, html);
107115
}
108116
}
109117

packages/core/src/client/overlay.ts

Lines changed: 5 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -28,134 +28,13 @@ function linkedText(root: ShadowRoot, selector: string, text: string): void {
2828
el.insertAdjacentHTML('beforeend', frag);
2929
}
3030

31-
const overlayTemplate = `
32-
<style>
33-
.root {
34-
position: fixed;
35-
z-index: 9999;
36-
top: 0;
37-
left: 0;
38-
width: 100%;
39-
height: 100%;
40-
overflow-y: scroll;
41-
margin: 0;
42-
background: rgba(0, 0, 0, 0.66);
43-
cursor: pointer;
44-
}
45-
.container {
46-
font-family: Menlo, Consolas, monospace;
47-
line-height: 1.6;
48-
width: 960px;
49-
max-width: 85%;
50-
color: #d8d8d8;
51-
margin: 32px auto;
52-
padding: 32px 40px;
53-
position: relative;
54-
background: #181818;
55-
border-radius: 24px;
56-
box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);
57-
overflow: hidden;
58-
direction: ltr;
59-
text-align: left;
60-
box-sizing: border-box;
61-
cursor: default;
62-
}
63-
.title {
64-
margin: 0 0 20px;
65-
padding-bottom: 12px;
66-
font-size: 17px;
67-
font-weight: 600;
68-
color: #fb6a6a;
69-
border-bottom: 2px solid rgba(252,94,94,.66);
70-
}
71-
.content {
72-
margin: 0;
73-
font-size: 14px;
74-
font-family: inherit;
75-
overflow-x: scroll;
76-
scrollbar-width: none;
77-
}
78-
.content::-webkit-scrollbar {
79-
display: none;
80-
}
81-
.file-link {
82-
cursor: pointer;
83-
color: #6eecf7;
84-
text-decoration: underline;
85-
text-underline-offset: 3px;
86-
&:hover {
87-
opacity: 0.8;
88-
}
89-
&:active {
90-
opacity: 0.6;
91-
}
92-
}
93-
.close {
94-
position: absolute;
95-
top: 27px;
96-
right: 32px;
97-
width: 32px;
98-
height: 32px;
99-
cursor: pointer;
100-
}
101-
.close:hover {
102-
opacity: 0.8;
103-
}
104-
.close:active {
105-
opacity: 0.6;
106-
}
107-
.close:before,
108-
.close:after {
109-
position: absolute;
110-
left: 16px;
111-
top: 8px;
112-
content: ' ';
113-
height: 18px;
114-
width: 2px;
115-
border-radius: 4px;
116-
background-color: #b8b8b8;
117-
}
118-
.close:before {
119-
transform: rotate(45deg);
120-
}
121-
.close:after {
122-
transform: rotate(-45deg);
123-
}
124-
.footer {
125-
font-size: 12px;
126-
color: #7e6a92;
127-
margin-top: 20px;
128-
padding-top: 12px;
129-
border-top: 2px solid rgba(126,106,146,.6);
130-
}
131-
.footer p {
132-
margin: 4px 0 0;
133-
}
134-
.footer span {
135-
color: #a88dc3;
136-
}
137-
</style>
138-
139-
<div class="root">
140-
<div class="container">
141-
<div class="close"></div>
142-
<p class="title">Build failed</p>
143-
<pre class="content"></pre>
144-
<footer class="footer">
145-
<p><span>Fix error</span>, click outside, or press Esc to close the overlay.</p>
146-
<p>Disable overlay by setting Rsbuild's <span>dev.client.overlay</span> config to false.<p>
147-
</footer>
148-
</div>
149-
</div>
150-
`;
151-
15231
const {
15332
HTMLElement = class {} as typeof globalThis.HTMLElement,
15433
customElements,
15534
} = typeof window !== 'undefined' ? window : globalThis;
15635

15736
class ErrorOverlay extends HTMLElement {
158-
constructor(message: string[]) {
37+
constructor(overlay: string, errors: string[]) {
15938
super();
16039

16140
if (!this.attachShadow) {
@@ -166,15 +45,12 @@ class ErrorOverlay extends HTMLElement {
16645
}
16746

16847
const root = this.attachShadow({ mode: 'open' });
169-
root.innerHTML = overlayTemplate;
170-
171-
linkedText(root, '.content', message.join('\n\n').trim());
48+
root.innerHTML = overlay;
17249

50+
linkedText(root, '.content', errors.join('\n\n').trim());
17351
root.querySelector('.close')?.addEventListener('click', this.close);
174-
17552
// close overlay when click outside
17653
this.addEventListener('click', this.close);
177-
17854
root.querySelector('.container')!.addEventListener('click', (e) => {
17955
e.stopPropagation();
18056
});
@@ -185,7 +61,6 @@ class ErrorOverlay extends HTMLElement {
18561
}
18662
document.removeEventListener('keydown', onEscKeydown);
18763
};
188-
18964
document.addEventListener('keydown', onEscKeydown);
19065
}
19166

@@ -209,9 +84,9 @@ if (customElements && !customElements.get(overlayId)) {
20984
customElements.define(overlayId, ErrorOverlay);
21085
}
21186

212-
function createOverlay(err: string[]) {
87+
function createOverlay(overlay: string, errors: string[]) {
21388
clearOverlay();
214-
document.body.appendChild(new ErrorOverlay(err));
89+
document.body.appendChild(new ErrorOverlay(overlay, errors));
21590
}
21691

21792
function clearOverlay() {

packages/core/src/server/socketServer.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,128 @@ interface ExtWebSocket extends Ws {
1717
isAlive: boolean;
1818
}
1919

20+
// HTML template for error overlay
21+
const overlayTemplate = `
22+
<style>
23+
.root {
24+
position: fixed;
25+
z-index: 9999;
26+
top: 0;
27+
left: 0;
28+
width: 100%;
29+
height: 100%;
30+
overflow-y: scroll;
31+
margin: 0;
32+
background: rgba(0, 0, 0, 0.66);
33+
cursor: pointer;
34+
}
35+
.container {
36+
font-family: Menlo, Consolas, monospace;
37+
line-height: 1.6;
38+
width: 960px;
39+
max-width: 85%;
40+
color: #d8d8d8;
41+
margin: 32px auto;
42+
padding: 32px 40px;
43+
position: relative;
44+
background: #181818;
45+
border-radius: 24px;
46+
box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);
47+
overflow: hidden;
48+
direction: ltr;
49+
text-align: left;
50+
box-sizing: border-box;
51+
cursor: default;
52+
}
53+
.title {
54+
margin: 0 0 20px;
55+
padding-bottom: 12px;
56+
font-size: 17px;
57+
font-weight: 600;
58+
color: #fb6a6a;
59+
border-bottom: 2px solid rgba(252,94,94,.66);
60+
}
61+
.content {
62+
margin: 0;
63+
font-size: 14px;
64+
font-family: inherit;
65+
overflow-x: scroll;
66+
scrollbar-width: none;
67+
}
68+
.content::-webkit-scrollbar {
69+
display: none;
70+
}
71+
.file-link {
72+
cursor: pointer;
73+
color: #6eecf7;
74+
text-decoration: underline;
75+
text-underline-offset: 3px;
76+
&:hover {
77+
opacity: 0.8;
78+
}
79+
&:active {
80+
opacity: 0.6;
81+
}
82+
}
83+
.close {
84+
position: absolute;
85+
top: 27px;
86+
right: 32px;
87+
width: 32px;
88+
height: 32px;
89+
cursor: pointer;
90+
}
91+
.close:hover {
92+
opacity: 0.8;
93+
}
94+
.close:active {
95+
opacity: 0.6;
96+
}
97+
.close:before,
98+
.close:after {
99+
position: absolute;
100+
left: 16px;
101+
top: 8px;
102+
content: ' ';
103+
height: 18px;
104+
width: 2px;
105+
border-radius: 4px;
106+
background-color: #b8b8b8;
107+
}
108+
.close:before {
109+
transform: rotate(45deg);
110+
}
111+
.close:after {
112+
transform: rotate(-45deg);
113+
}
114+
.footer {
115+
font-size: 12px;
116+
color: #7e6a92;
117+
margin-top: 20px;
118+
padding-top: 12px;
119+
border-top: 2px solid rgba(126,106,146,.6);
120+
}
121+
.footer p {
122+
margin: 4px 0 0;
123+
}
124+
.footer span {
125+
color: #a88dc3;
126+
}
127+
</style>
128+
129+
<div class="root">
130+
<div class="container">
131+
<div class="close"></div>
132+
<p class="title">Build failed</p>
133+
<pre class="content"></pre>
134+
<footer class="footer">
135+
<p><span>Fix error</span>, click outside, or press Esc to close the overlay.</p>
136+
<p>Disable overlay by setting Rsbuild's <span>dev.client.overlay</span> config to false.<p>
137+
</footer>
138+
</div>
139+
</div>
140+
`;
141+
20142
function isEqualSet(a: Set<string>, b: Set<string>): boolean {
21143
if (a.size !== b.size) {
22144
return false;
@@ -297,6 +419,7 @@ export class SocketServer {
297419
data: {
298420
text: formattedErrors,
299421
html: formattedErrors.map((item) => ansiHTML(escapeHtml(item))),
422+
overlay: overlayTemplate,
300423
},
301424
});
302425
}

0 commit comments

Comments
 (0)