remote-components 0.0.33 → 0.0.34

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.
Files changed (50) hide show
  1. package/dist/{component-loader-28ad0083.d.ts → component-loader-8951c052.d.ts} +6 -4
  2. package/dist/html/host.cjs +227 -13
  3. package/dist/html/host.cjs.map +1 -1
  4. package/dist/html/host.js +227 -13
  5. package/dist/html/host.js.map +1 -1
  6. package/dist/html/remote.cjs +198 -0
  7. package/dist/html/remote.cjs.map +1 -0
  8. package/dist/html/remote.d.ts +2 -0
  9. package/dist/html/remote.js +197 -0
  10. package/dist/html/remote.js.map +1 -0
  11. package/dist/internal/next/host/app-router-client.cjs +56 -4
  12. package/dist/internal/next/host/app-router-client.cjs.map +1 -1
  13. package/dist/internal/next/host/app-router-client.d.ts +3 -3
  14. package/dist/internal/next/host/app-router-client.js +58 -5
  15. package/dist/internal/next/host/app-router-client.js.map +1 -1
  16. package/dist/internal/shared/client/remote-component.cjs +99 -0
  17. package/dist/internal/shared/client/remote-component.cjs.map +1 -1
  18. package/dist/internal/shared/client/remote-component.d.ts +11 -4
  19. package/dist/internal/shared/client/remote-component.js +97 -0
  20. package/dist/internal/shared/client/remote-component.js.map +1 -1
  21. package/dist/internal/shared/error.cjs.map +1 -1
  22. package/dist/internal/shared/error.d.ts +1 -1
  23. package/dist/internal/shared/error.js.map +1 -1
  24. package/dist/internal/shared/ssr/dom-flight.cjs +17 -5
  25. package/dist/internal/shared/ssr/dom-flight.cjs.map +1 -1
  26. package/dist/internal/shared/ssr/dom-flight.d.ts +1 -1
  27. package/dist/internal/shared/ssr/dom-flight.js +17 -5
  28. package/dist/internal/shared/ssr/dom-flight.js.map +1 -1
  29. package/dist/internal/shared/ssr/fetch-remote-component.cjs +7 -3
  30. package/dist/internal/shared/ssr/fetch-remote-component.cjs.map +1 -1
  31. package/dist/internal/shared/ssr/fetch-remote-component.d.ts +2 -1
  32. package/dist/internal/shared/ssr/fetch-remote-component.js +7 -3
  33. package/dist/internal/shared/ssr/fetch-remote-component.js.map +1 -1
  34. package/dist/next/host/app-router-server.cjs +1 -0
  35. package/dist/next/host/app-router-server.cjs.map +1 -1
  36. package/dist/next/host/app-router-server.js +1 -0
  37. package/dist/next/host/app-router-server.js.map +1 -1
  38. package/dist/next/host/client/index.cjs +292 -103
  39. package/dist/next/host/client/index.cjs.map +1 -1
  40. package/dist/next/host/client/index.d.ts +1 -1
  41. package/dist/next/host/client/index.js +289 -102
  42. package/dist/next/host/client/index.js.map +1 -1
  43. package/dist/react/index.cjs +197 -103
  44. package/dist/react/index.cjs.map +1 -1
  45. package/dist/react/index.d.ts +2 -2
  46. package/dist/react/index.js +196 -102
  47. package/dist/react/index.js.map +1 -1
  48. package/dist/{types-7c207455.d.ts → types-4e7dea94.d.ts} +2 -1
  49. package/dist/{types-e4a3fa37.d.ts → types-cbf6c34f.d.ts} +2 -2
  50. package/package.json +8 -1
package/dist/html/host.js CHANGED
@@ -715,6 +715,106 @@ var init_webpack_adapter = __esm({
715
715
  }
716
716
  });
717
717
 
718
+ // src/shared/client/static-loader.ts
719
+ async function loadStaticRemoteComponent(scripts, url) {
720
+ const self = globalThis;
721
+ if (self.__remote_script_entrypoint_mount__?.[url.href]) {
722
+ self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
723
+ }
724
+ if (self.__remote_script_entrypoint_unmount__?.[url.href]) {
725
+ self.__remote_script_entrypoint_unmount__[url.href] = /* @__PURE__ */ new Set();
726
+ }
727
+ const mountUnmountSets = await Promise.all(
728
+ scripts.map(async (script) => {
729
+ try {
730
+ let src = typeof script.getAttribute === "function" ? script.getAttribute("src") ?? script.src : script.src;
731
+ if (!src && script.textContent) {
732
+ const blob = new Blob(
733
+ [
734
+ script.textContent.replace(
735
+ /import\.meta\.url/g,
736
+ JSON.stringify(url)
737
+ )
738
+ ],
739
+ {
740
+ type: "text/javascript"
741
+ }
742
+ );
743
+ src = URL.createObjectURL(blob);
744
+ }
745
+ const mod = await import(
746
+ /* @vite-ignore */
747
+ /* webpackIgnore: true */
748
+ new URL(src, url).href
749
+ );
750
+ if (src.startsWith("blob:")) {
751
+ URL.revokeObjectURL(src);
752
+ }
753
+ if (typeof mod.mount === "function" || typeof mod.default?.mount === "function") {
754
+ if (!self.__remote_script_entrypoint_mount__) {
755
+ self.__remote_script_entrypoint_mount__ = {};
756
+ }
757
+ if (!self.__remote_script_entrypoint_mount__[url.href]) {
758
+ self.__remote_script_entrypoint_mount__[url.href] = /* @__PURE__ */ new Set();
759
+ }
760
+ self.__remote_script_entrypoint_mount__[url.href]?.add(
761
+ mod.mount || mod.default?.mount || (() => {
762
+ })
763
+ );
764
+ }
765
+ if (typeof mod.unmount === "function" || typeof mod.default?.unmount === "function") {
766
+ if (!self.__remote_script_entrypoint_unmount__) {
767
+ self.__remote_script_entrypoint_unmount__ = {};
768
+ }
769
+ if (!self.__remote_script_entrypoint_unmount__[url.href]) {
770
+ self.__remote_script_entrypoint_unmount__[url.href] = /* @__PURE__ */ new Set();
771
+ }
772
+ self.__remote_script_entrypoint_unmount__[url.href]?.add(
773
+ mod.unmount || mod.default?.unmount || (() => {
774
+ })
775
+ );
776
+ }
777
+ return {
778
+ mount: mod.mount || mod.default?.mount,
779
+ unmount: mod.unmount || mod.default?.unmount
780
+ };
781
+ } catch (e) {
782
+ console.error(
783
+ new RemoteComponentsError(
784
+ `Error loading remote component script from "${script.src || url.href}".`,
785
+ { cause: e }
786
+ )
787
+ );
788
+ return {
789
+ mount: void 0,
790
+ unmount: void 0
791
+ };
792
+ }
793
+ })
794
+ );
795
+ return mountUnmountSets.reduce(
796
+ (acc, { mount, unmount }) => {
797
+ if (typeof mount === "function") {
798
+ acc.mount.add(mount);
799
+ }
800
+ if (typeof unmount === "function") {
801
+ acc.unmount.add(unmount);
802
+ }
803
+ return acc;
804
+ },
805
+ {
806
+ mount: /* @__PURE__ */ new Set(),
807
+ unmount: /* @__PURE__ */ new Set()
808
+ }
809
+ );
810
+ }
811
+ var init_static_loader = __esm({
812
+ "src/shared/client/static-loader.ts"() {
813
+ "use strict";
814
+ init_error();
815
+ }
816
+ });
817
+
718
818
  // src/shared/client/polyfill.tsx
719
819
  import { jsx } from "react/jsx-runtime";
720
820
  function applyBundleUrlToSrc(bundle, src) {
@@ -1085,6 +1185,31 @@ var init_turbopack = __esm({
1085
1185
  }
1086
1186
  });
1087
1187
 
1188
+ // src/html/host/runtime/script.ts
1189
+ var script_exports = {};
1190
+ __export(script_exports, {
1191
+ scriptRuntime: () => scriptRuntime
1192
+ });
1193
+ function scriptRuntime() {
1194
+ const self = globalThis;
1195
+ return {
1196
+ self,
1197
+ createFromReadableStream: () => Promise.resolve(null),
1198
+ applySharedModules: () => Promise.resolve(),
1199
+ nextClientPagesLoader: () => ({
1200
+ Component: null,
1201
+ App: null
1202
+ }),
1203
+ preloadScripts: loadStaticRemoteComponent
1204
+ };
1205
+ }
1206
+ var init_script = __esm({
1207
+ "src/html/host/runtime/script.ts"() {
1208
+ "use strict";
1209
+ init_static_loader();
1210
+ }
1211
+ });
1212
+
1088
1213
  // src/html/host/index.tsx
1089
1214
  import { startTransition, useLayoutEffect } from "react";
1090
1215
  import { hydrateRoot } from "react-dom/client";
@@ -1170,6 +1295,7 @@ function createRSCStream(rscName, data) {
1170
1295
  }
1171
1296
 
1172
1297
  // src/shared/client/remote-component.ts
1298
+ init_static_loader();
1173
1299
  init_webpack_adapter();
1174
1300
  init_const();
1175
1301
  init_error();
@@ -1269,9 +1395,12 @@ async function getRuntime(type, url, bundle, shared, remoteShared) {
1269
1395
  } else if (type === "turbopack") {
1270
1396
  const { turbopackRuntime: turbopackRuntime2 } = await Promise.resolve().then(() => (init_turbopack(), turbopack_exports));
1271
1397
  return turbopackRuntime2(url, bundle, shared, remoteShared);
1398
+ } else if (type === "script") {
1399
+ const { scriptRuntime: scriptRuntime2 } = await Promise.resolve().then(() => (init_script(), script_exports));
1400
+ return scriptRuntime2();
1272
1401
  }
1273
1402
  throw new RemoteComponentsError(
1274
- `Remote Components runtime "${type}" is not supported. Supported runtimes are "webpack" and "turbopack".`
1403
+ `Remote Components runtime "${type}" is not supported. Supported runtimes are "webpack", "turbopack", and "script".`
1275
1404
  );
1276
1405
  }
1277
1406
 
@@ -1284,6 +1413,7 @@ if (typeof HTMLElement !== "undefined") {
1284
1413
  this.__next = null;
1285
1414
  this.fouc = null;
1286
1415
  this.isLoading = false;
1416
+ this.prevIsRemoteComponent = false;
1287
1417
  this.root = null;
1288
1418
  }
1289
1419
  static get observedAttributes() {
@@ -1397,23 +1527,27 @@ if (typeof HTMLElement !== "undefined") {
1397
1527
  }
1398
1528
  const parser = new DOMParser();
1399
1529
  const doc = parser.parseFromString(html, "text/html");
1400
- if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(`div[data-bundle][data-route][id^="${this.name}"]`)) {
1530
+ if (doc.querySelectorAll("div[data-bundle][data-route]").length > 1 && !doc.querySelector(
1531
+ `div[data-bundle][data-route][id^="${this.name}"]`
1532
+ ) || doc.querySelectorAll("remote-component").length > 1 && !doc.querySelector(`remote-component[name="${this.name}"]`)) {
1401
1533
  throw multipleRemoteComponentsError(
1402
1534
  url?.href ?? (this.getAttribute("src") || "unknown")
1403
1535
  );
1404
1536
  }
1405
1537
  const component = doc.querySelector(`div[data-bundle][data-route][id^="${this.name}"]`) ?? // fallback to the first element with the data-bundle and data-route attributes when not using a named remote component
1406
1538
  doc.querySelector("div[data-bundle][data-route]") ?? // fallback to Next.js Pages Router
1407
- doc.querySelector("div#__next");
1539
+ doc.querySelector("div#__next") ?? // fallback to a <remote-component> element
1540
+ doc.querySelector(`remote-component[name="${this.name}"]:not([src])`) ?? doc.querySelector("remote-component:not([src])");
1408
1541
  const nextData = JSON.parse(
1409
1542
  (doc.querySelector("#__NEXT_DATA__") ?? doc.querySelector("#__REMOTE_NEXT_DATA__"))?.textContent ?? "null"
1410
1543
  );
1544
+ const isRemoteComponent = component?.tagName.toLowerCase() === "remote-component";
1411
1545
  if (nextData && nextData.buildId === "development" && !this.reactRoot) {
1412
1546
  this.fouc = document.createElement("style");
1413
1547
  this.fouc.textContent = `:host { display: none; }`;
1414
1548
  this.root.appendChild(this.fouc);
1415
1549
  }
1416
- this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || (nextData ? "__next" : this.name);
1550
+ this.name = component?.getAttribute("id")?.replace(/_ssr$/, "") || isRemoteComponent && component.getAttribute("name") || (nextData ? "__next" : this.name);
1417
1551
  const rsc = doc.querySelector(`#${this.name}_rsc`);
1418
1552
  this.bundle = component?.getAttribute("data-bundle") || nextData?.props.__REMOTE_COMPONENT__?.bundle || this.bundle;
1419
1553
  if (url) {
@@ -1426,12 +1560,13 @@ if (typeof HTMLElement !== "undefined") {
1426
1560
  const metadata = document.createElement("script");
1427
1561
  metadata.type = "application/json";
1428
1562
  metadata.setAttribute("data-remote-component", "");
1429
- metadata.textContent = JSON.stringify({
1563
+ const metadataObj = {
1430
1564
  name: this.name,
1431
1565
  bundle: this.bundle,
1432
- route: component?.getAttribute("data-route") ?? nextData?.page ?? "/",
1433
- runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime
1434
- });
1566
+ route: component?.getAttribute("data-route") ?? nextData?.page ?? url?.pathname ?? "/",
1567
+ runtime: component?.getAttribute("data-runtime") ?? nextData?.props.__REMOTE_COMPONENT__?.runtime ?? "script"
1568
+ };
1569
+ metadata.textContent = JSON.stringify(metadataObj);
1435
1570
  if (this.previousElementSibling?.getAttribute("data-remote-component") !== null) {
1436
1571
  this.previousElementSibling?.remove();
1437
1572
  }
@@ -1446,11 +1581,38 @@ if (typeof HTMLElement !== "undefined") {
1446
1581
  remoteShared.__remote_components_missing_shared__
1447
1582
  );
1448
1583
  }
1449
- if (!component || !(rsc || nextData)) {
1584
+ if (!component || !(rsc || nextData || isRemoteComponent)) {
1450
1585
  throw new RemoteComponentsError(
1451
1586
  `Remote Component not found on ${src}.${this.name !== "__vercel_remote_component" ? ` The name for the <RemoteComponent> is "${this.name}". Check <RemoteComponent> usage.` : ""} Did you forget to wrap the content in <RemoteComponent>?`
1452
1587
  );
1453
1588
  }
1589
+ if (this.prevIsRemoteComponent) {
1590
+ if (this.prevUrl) {
1591
+ const prevUrl = this.prevUrl;
1592
+ const self2 = globalThis;
1593
+ if (self2.__remote_script_entrypoint_unmount__?.[prevUrl.href]) {
1594
+ await Promise.all(
1595
+ Array.from(
1596
+ self2.__remote_script_entrypoint_unmount__[prevUrl.href] ?? []
1597
+ ).map(async (unmount) => {
1598
+ try {
1599
+ await unmount(this.root);
1600
+ } catch (e) {
1601
+ console.error(
1602
+ new RemoteComponentsError(
1603
+ `Error while calling unmount() for Remote Component from ${prevUrl.href}.`,
1604
+ { cause: e }
1605
+ )
1606
+ );
1607
+ }
1608
+ })
1609
+ );
1610
+ }
1611
+ }
1612
+ this.root.innerHTML = "";
1613
+ }
1614
+ this.prevUrl = url ?? new URL(location.href);
1615
+ this.prevIsRemoteComponent = isRemoteComponent;
1454
1616
  const removable = Array.from(this.childNodes);
1455
1617
  const links = doc.querySelectorAll("link[href]");
1456
1618
  const remoteComponentSrc = this.getAttribute("src");
@@ -1516,7 +1678,35 @@ if (typeof HTMLElement !== "undefined") {
1516
1678
  applyOriginToNodes(doc, url ?? new URL(location.href));
1517
1679
  if (!this.reactRoot) {
1518
1680
  Array.from(component.children).forEach((el) => {
1519
- this.root?.appendChild(el);
1681
+ if (!isRemoteComponent && el.tagName.toLowerCase() === "script") {
1682
+ const newScript = document.createElement("script");
1683
+ for (const attr of el.attributes) {
1684
+ if (attr.name === "src") {
1685
+ newScript.setAttribute(
1686
+ attr.name,
1687
+ new URL(attr.value, url ?? location.origin).href
1688
+ );
1689
+ } else {
1690
+ newScript.setAttribute(attr.name, attr.value);
1691
+ }
1692
+ }
1693
+ newScript.textContent = el.textContent;
1694
+ if (remoteComponentSrc) {
1695
+ newScript.setAttribute(
1696
+ "data-remote-component-src",
1697
+ remoteComponentSrc
1698
+ );
1699
+ }
1700
+ this.root?.appendChild(newScript);
1701
+ } else {
1702
+ const newEl = el.cloneNode(true);
1703
+ for (const attr of el.attributes) {
1704
+ if (attr.name.startsWith("on")) {
1705
+ newEl.setAttribute(attr.name, attr.value);
1706
+ }
1707
+ }
1708
+ this.root?.appendChild(newEl);
1709
+ }
1520
1710
  });
1521
1711
  }
1522
1712
  for (const el of removable) {
@@ -1555,7 +1745,7 @@ if (typeof HTMLElement !== "undefined") {
1555
1745
  nextClientPagesLoader: nextClientPagesLoader2,
1556
1746
  preloadScripts
1557
1747
  } = await getRuntime(
1558
- component.getAttribute("data-runtime") ?? "webpack",
1748
+ metadataObj.runtime,
1559
1749
  url ?? new URL(location.href),
1560
1750
  this.bundle,
1561
1751
  {
@@ -1567,8 +1757,8 @@ if (typeof HTMLElement !== "undefined") {
1567
1757
  },
1568
1758
  remoteShared
1569
1759
  );
1570
- const scripts = doc.querySelectorAll(
1571
- "script[src],script[data-src]"
1760
+ const scripts = isRemoteComponent ? component.querySelectorAll("script") : doc.querySelectorAll(
1761
+ "script[src],script[data-src],script[data-remote-component-entrypoint]"
1572
1762
  );
1573
1763
  if (!url) {
1574
1764
  url = new URL(
@@ -1582,6 +1772,13 @@ if (typeof HTMLElement !== "undefined") {
1582
1772
  this.bundle ?? "default",
1583
1773
  this.name ?? "__vercel_remote_component"
1584
1774
  );
1775
+ if (isRemoteComponent) {
1776
+ Array.from(component.children).forEach((child) => {
1777
+ if (child.tagName === "SCRIPT") {
1778
+ child.remove();
1779
+ }
1780
+ });
1781
+ }
1585
1782
  const doCleanup = () => {
1586
1783
  if (this.root && remoteComponentSrc) {
1587
1784
  const selector = `[data-remote-component-src]:not([data-remote-component-src="${remoteComponentSrc}"])`;
@@ -1703,6 +1900,23 @@ if (typeof HTMLElement !== "undefined") {
1703
1900
  if (this.fouc) {
1704
1901
  this.root.removeChild(this.fouc);
1705
1902
  }
1903
+ } else if (self.__remote_script_entrypoint_mount__?.[url.href]) {
1904
+ await Promise.all(
1905
+ Array.from(
1906
+ self.__remote_script_entrypoint_mount__[url.href] ?? []
1907
+ ).map(async (mount) => {
1908
+ try {
1909
+ await mount(this.root);
1910
+ } catch (e) {
1911
+ console.error(
1912
+ new RemoteComponentsError(
1913
+ `Error while calling mount() for Remote Component from ${url.href}.`,
1914
+ { cause: e }
1915
+ )
1916
+ );
1917
+ }
1918
+ })
1919
+ );
1706
1920
  }
1707
1921
  this.isLoading = false;
1708
1922
  }