-
Notifications
You must be signed in to change notification settings - Fork 439
Expand file tree
/
Copy pathindex.ts
More file actions
73 lines (61 loc) · 2.67 KB
/
index.ts
File metadata and controls
73 lines (61 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
* Copyright (c) 2025, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
type RootNode = Node & DocumentOrShadowRoot & NonElementParentNode;
const stylesheetCache = new Map();
class StyleDeduplicator extends HTMLElement {
connectedCallback() {
const styleId = this.getAttribute('style-id');
if (!styleId) {
throw new Error('"style-id" attribute must be supplied for <lwc-style> element');
}
const root = this.getRootNode() as RootNode;
let stylesheet = stylesheetCache.get(styleId);
if (stylesheet) {
root.adoptedStyleSheets.push(stylesheet);
const placeholder = document.createElement('style');
placeholder.setAttribute('type', 'text/css');
// TODO [#2869]: `<style>`s should not have scope token classes but they are required for hydration to function correctly (W-19087941).
this.classList.forEach((className) => placeholder.classList.add(className));
// Not-first <lwc-style> should be replaced with a placeholder <style>, since that's
// what the diffing algorithm and hydration logic will expect to find
this.replaceWith(placeholder);
} else {
stylesheet = new CSSStyleSheet();
const element = root.getElementById(styleId);
if (!element) {
throw new Error(
`<lwc-style> tag found with no corresponding <style id="${styleId}"> tag`
);
}
stylesheet.replaceSync(element.innerHTML);
stylesheetCache.set(styleId, stylesheet);
// The first <lwc-style> should be removed, because it already has a <style> next to it
this.remove();
}
}
}
/**
* This function should be called in a <script> tag in the <head>
* before server-rendered markup is encountered while parsing an HTML
* document. This ensures that deduplicated styles will be in effect
* for components that insert an <lwc-style> tag in place of a full
* stylesheet.
* It can also be implicitly invoked by importing `@lwc/ssr-client-utils/register-lwc-style` as a bare import.
*/
export function registerLwcStyleComponent() {
customElements.define('lwc-style', StyleDeduplicator);
}
// Only used in LWC's Karma tests
// See PR-5281 for precedence on extra guards
if (
typeof process === 'object' &&
typeof process?.env === 'object' &&
process.env &&
process.env.NODE_ENV === 'test-karma-lwc'
) {
(window as any).__lwcClearStylesheetCache = () => stylesheetCache.clear();
}