@webjsdev/core 0.7.59 → 0.7.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webjsdev/core",
3
- "version": "0.7.59",
3
+ "version": "0.7.60",
4
4
  "type": "module",
5
5
  "description": "The runtime for WebJs, a full-stack JavaScript framework built on web components with server-side rendering and no build step. Ships the html and css template tags, the WebComponent base class, signals, directives, and the isomorphic renderers.",
6
6
  "types": "./index.d.ts",
@@ -22,6 +22,17 @@
22
22
  * // ...
23
23
  * }
24
24
  * MyWidget.register('my-lazy-widget');
25
+ *
26
+ * A component that another shipping module imports for registration
27
+ * (`import './my-lazy-widget.ts'`) stays lazy too (#1524): the server keeps
28
+ * that import for SSR, and the browser copy of the importer is served with
29
+ * the line rewritten to an `observeLazy({...})` call, so the module loads
30
+ * when an element with the tag is first visible: a hidden tab panel when it
31
+ * shows, a dialog's content when it opens, an element added later by a
32
+ * client render (the MutationObserver below catches it).
33
+ *
34
+ * The scan reads the light DOM (`document.querySelectorAll`), so a lazy tag
35
+ * rendered inside another component's shadow root is not found.
25
36
  */
26
37
 
27
38
  /** @type {Map<string, string>} tag → module URL */
@@ -30,6 +41,14 @@ const pending = new Map();
30
41
  /** @type {IntersectionObserver | null} */
31
42
  let observer = null;
32
43
 
44
+ /**
45
+ * ONE MutationObserver for the whole page, however often `observeLazy` runs
46
+ * (#1524): the boot script calls it, and so does every served module whose
47
+ * side-effect import of a `static lazy` component was deferred to it.
48
+ * @type {MutationObserver | null}
49
+ */
50
+ let mutations = null;
51
+
33
52
  /** @type {Map<string, Promise<unknown>>} in-flight module loads, keyed by URL */
34
53
  const inflight = new Map();
35
54
 
@@ -78,15 +97,18 @@ export function observeLazy(entries) {
78
97
  scan();
79
98
 
80
99
  // Also watch for dynamically added elements via MutationObserver.
81
- if (typeof MutationObserver !== 'undefined') {
82
- const mo = new MutationObserver(() => scan());
83
- mo.observe(document.body, { childList: true, subtree: true });
100
+ if (!mutations && typeof MutationObserver !== 'undefined') {
101
+ mutations = new MutationObserver(() => scan());
102
+ mutations.observe(document.body, { childList: true, subtree: true });
84
103
  }
85
104
  }
86
105
 
87
106
  function scan() {
88
107
  if (!observer || !pending.size) return;
89
108
  for (const tag of pending.keys()) {
109
+ // Already defined some other way (an eager import elsewhere): nothing
110
+ // left to load for this tag.
111
+ if (customElements.get(tag)) { pending.delete(tag); continue; }
90
112
  for (const el of document.querySelectorAll(tag)) {
91
113
  observer.observe(el);
92
114
  }