@vercel/microfrontends
Version:
Defines configuration and utilities for microfrontends development
3 lines • 6.18 kB
JavaScript
"use client";
import X from"next/link.js";import{forwardRef as $,useContext as q,useMemo as G}from"react";import{useEffect as k,useMemo as M,useState as P}from"react";import{pathToRegexp as R}from"path-to-regexp";var m=new Map,S=t=>{let e=m.get(t);if(e)return e;let r=R(t);return m.set(t,r),r},f=class{constructor(e,r){this.pathCache={};this.hasFlaggedPaths=e.hasFlaggedPaths??!1;for(let i of Object.values(e.applications))if(i.routing){i.routing.some(n=>n.flag)&&(this.hasFlaggedPaths=!0);let o=[],a=[];for(let n of i.routing)if(n.flag){if(r?.removeFlaggedPaths)continue;n.group&&delete n.group,o.push(n)}else a.push(...n.paths);a.length>0&&o.push({paths:a}),i.routing=o}this.serialized=e,this.hasFlaggedPaths&&(this.serialized.hasFlaggedPaths=this.hasFlaggedPaths),this.applications=e.applications}static fromEnv(e){if(!e)throw new Error("Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`? Is the local proxy running and this application is being accessed via the proxy port? See https://vercel.com/docs/microfrontends/local-development#setting-up-microfrontends-proxy");return new f(JSON.parse(e))}isEqual(e){return this===e||JSON.stringify(this.applications)===JSON.stringify(e.applications)}getApplicationNameForPath(e){if(!e.startsWith("/"))throw new Error("Path must start with a /");if(this.pathCache[e])return this.pathCache[e];let r=new URL(e,"https://example.com").pathname;for(let[o,a]of Object.entries(this.applications))if(a.routing){for(let n of a.routing)for(let s of n.paths)if(S(s).test(r))return this.pathCache[e]=o,o}let i=Object.entries(this.applications).find(([,o])=>o.default);return i?(this.pathCache[e]=i[0],i[0]):null}serialize(){return this.serialized}};var E=new Map,y=new Map,L=t=>{let e=E.get(t||"");if(e)return e;let r=f.fromEnv(t);return E.set(t||"",r),r},p=null,d=null;async function O(){try{let t=await fetch("/.well-known/vercel/microfrontends/client-config");if(t.status!==200)return null;let e=await t.json(),r=new f(e.config);return d=r,r}catch{return null}}function h(t){let[e,r]=P(()=>d??L(t)),i=M(()=>{if(process.env.NODE_ENV==="test"&&process.env.MFE_FORCE_CLIENT_CONFIG_FROM_SERVER!=="1"||d)return!1;let n=y.get(t||"");if(n!==void 0)return n;let l=L(t).hasFlaggedPaths;return y.set(t||"",l),!!l},[t]),[o,a]=P(i);return k(()=>{i&&(p||(p=O()),p.then(n=>{n&&r(s=>s.isEqual(n)?s:n)}).finally(()=>{a(!1)}))},[i]),{clientConfig:e,isLoading:o}}import F from"next/script.js";import{useEffect as v,useRef as w,useState as H}from"react";import{jsx as Z}from"react/jsx-runtime";var g="data-prefetch",c={anyZone:"[data-zone]",external:'[data-zone="null"]',sameZone:'[data-zone="same"]',prefetch:`[${g}]`},x={and:[{href_matches:"/*"},{selector_matches:c.anyZone},{not:{selector_matches:c.sameZone}},{not:{selector_matches:c.external}}]},T={and:[{href_matches:"/*"},{selector_matches:c.anyZone},{not:{selector_matches:c.sameZone}},{not:{selector_matches:c.external}},{selector_matches:c.prefetch}]};function _(t){if(!t)return!0;if("checkVisibility"in t)return t.checkVisibility({opacityProperty:!0});let e=t,r=window.getComputedStyle(e);return r.display==="none"||r.visibility==="hidden"||r.opacity==="0"?!1:_(e.parentElement)}function ae({prerenderEagerness:t="conservative"}){let{isLoading:e}=h(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG),[r,i]=H([]),o=w(A());if(v(()=>{if(e)return;let n=new IntersectionObserver(s=>{s.forEach(l=>{l.isIntersecting&&!l.target.hasAttribute(g)&&_(l.target)&&l.target.setAttribute(g,"true")})},{root:null,rootMargin:"0px",threshold:.1});return r.forEach(s=>n.observe(s)),()=>{n.disconnect()}},[e,r]),v(()=>{if(e)return;let n=new MutationObserver(s=>{s.some(u=>u.type==="childList"&&u.addedNodes.length>0||u.type==="attributes"&&u.attributeName==="href")&&i(Array.from(document.querySelectorAll(`a${c.anyZone}:not(${c.prefetch}):not(${c.sameZone}):not(${c.external})`)))});return n.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["href"]}),()=>{n.disconnect()}},[e]),e)return null;let a={prefetch:[{eagerness:"moderate",where:x},{eagerness:"immediate",where:T}],...o.current?{prerender:[{eagerness:t,where:x}]}:{}};return Z(F,{dangerouslySetInnerHTML:{__html:JSON.stringify(a)},id:"prefetch-zones-links",type:"speculationrules"})}function A(){if(typeof navigator>"u")return!0;let t=navigator.userAgent.match(/Chrome\/(\d+)/);return t?Number(t[1])!==147:!0}import{createContext as I,startTransition as z,useCallback as D,useMemo as J,useRef as B,useState as V}from"react";import{Fragment as U,jsx as b,jsxs as W}from"react/jsx-runtime";var C=I({prefetchHref:()=>{}});function ue({children:t}){let[e,r]=V(new Set),i=B(typeof navigator<"u"&&(navigator.userAgent.includes("Firefox")||navigator.userAgent.includes("Safari")&&!navigator.userAgent.includes("Chrome"))),o=D(n=>{z(()=>{r(s=>s.has(n)?s:new Set(s).add(n))})},[]),a=J(()=>({prefetchHref:o}),[o]);return i.current?W(C.Provider,{value:a,children:[t,[...e].map(n=>b("link",{as:"fetch",href:n,rel:"preload"},n))]}):b(U,{children:t})}import{jsx as N}from"react/jsx-runtime";var j=process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION_HASH;function K(t){let{clientConfig:e,isLoading:r}=h(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG),{isRelativePath:i,zoneOfHref:o}=G(()=>{let n=typeof t=="string"&&t.startsWith("/");return{isRelativePath:n,zoneOfHref:n?e.getApplicationNameForPath(t):null}},[e,t]);return typeof t=="string"&&!t.length?{zoneOfHref:null,isDifferentZone:!1,isLoading:!1}:{zoneOfHref:o,isDifferentZone:!i||(o?j!==o:!1),isLoading:r}}var Q=$(({children:t,...e},r)=>{let{prefetchHref:i}=q(C),{zoneOfHref:o,isDifferentZone:a,isLoading:n}=K(e.href);function s(){e.href&&i(e.href)}if(a&&o!==null){let{prefetch:l,...u}=e;return N("a",{...u,"data-zone":o,onFocus:e.prefetch!==!1?s:void 0,onMouseOver:e.prefetch!==!1?s:void 0,children:t})}return N(X,{...e,"data-zone":o?"same":"null",prefetch:e.prefetch??(n?!1:void 0),ref:r,children:t})});Q.displayName="MicrofrontendsLink";export{Q as Link,ae as PrefetchCrossZoneLinks,C as PrefetchCrossZoneLinksContext,ue as PrefetchCrossZoneLinksProvider,K as useZoneForHref};
//# sourceMappingURL=client.js.map