UNPKG

@vercel/microfrontends

Version:

Defines configuration and utilities for microfrontends development

3 lines 5.79 kB
"use client"; import{forwardRef as $,useContext as K,useMemo as q}from"react";import G from"next/link.js";import{useState as E,useEffect as w,useMemo as S}from"react";import{pathToRegexp as b}from"path-to-regexp";var m=new Map,k=t=>{let e=m.get(t);if(e)return e;let r=b(t);return m.set(t,r),r},l=class{constructor(e,r){this.pathCache={};if(this.serialized=e,r?.removeFlaggedPaths)for(let o of Object.values(e.applications))o.routing&&(o.routing=o.routing.filter(n=>!n.flag));this.applications=e.applications}static fromEnv(e,r){if(!e)throw new Error("Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?");return new l(JSON.parse(e),r)}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[n,a]of Object.entries(this.applications))if(a.routing){for(let i of a.routing)for(let s of i.paths)if(k(s).test(r))return this.pathCache[e]=n,n}let o=Object.entries(this.applications).find(([,n])=>n.default);return o?(this.pathCache[e]=o[0],o[0]):null}serialize(){return this.serialized}};var P=new Map,y=new Map,F=t=>JSON.stringify({removeFlaggedPaths:t?.removeFlaggedPaths||!1}),L=(t,e)=>{let r=F(e),o=P.get(t||"");if(!o)o=new Map,P.set(t||"",o);else{let a=o.get(r);if(a)return a}let n=l.fromEnv(t,e);return o.set(r,n),n},d=null,g=null;async function T(){try{let t=await fetch("/.well-known/vercel/microfrontends/client-config");if(t.status!==200)return null;let e=await t.json(),r=new l(e.config);return g=r,r}catch{return null}}function p(t,{removeFlaggedPathsFromDefault:e}={}){let[r,o]=E(()=>g??L(t,{removeFlaggedPaths:e})),n=S(()=>{if(process.env.NODE_ENV==="test"&&process.env.MFE_FORCE_CLIENT_CONFIG_FROM_SERVER!=="1"||g)return!1;let s=y.get(t||"");if(s!==void 0)return s;let f=L(t),u=Object.values(f.applications).some(N=>N.routing?.some(R=>R.flag));return y.set(t||"",u),!!u},[t]),[a,i]=E(n);return w(()=>{n&&(d||(d=T()),d.then(s=>{s&&o(f=>f.isEqual(s)?f:s)}).finally(()=>{i(!1)}))},[t,r.applications,n]),{clientConfig:r,isLoading:a}}import{createContext as A,useCallback as H,useRef as Z,useMemo as I,useState as D,startTransition as z}from"react";import{Fragment as J,jsx as v,jsxs as B}from"react/jsx-runtime";var h=A({prefetchHref:()=>{}});function ae({children:t}){let[e,r]=D(new Set),o=Z(typeof navigator<"u"&&(navigator.userAgent.includes("Firefox")||navigator.userAgent.includes("Safari")&&!navigator.userAgent.includes("Chrome"))),n=H(i=>{z(()=>{r(s=>s.has(i)?s:new Set(s).add(i))})},[]),a=I(()=>({prefetchHref:n}),[n]);return o.current?B(h.Provider,{value:a,children:[t,[...e].map(i=>v("link",{as:"fetch",href:i,rel:"preload"},i))]}):v(J,{children:t})}import{useEffect as x,useState as V}from"react";import U from"next/script.js";import{jsx as W}from"react/jsx-runtime";var C="data-prefetch",c={anyZone:"[data-zone]",external:'[data-zone="null"]',sameZone:'[data-zone="same"]',prefetch:`[${C}]`},M={and:[{href_matches:"/*"},{selector_matches:c.anyZone},{not:{selector_matches:c.sameZone}},{not:{selector_matches:c.external}}]},X={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 de(){let{isLoading:t}=p(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG),[e,r]=V([]);return x(()=>{if(t)return;let n=new IntersectionObserver(a=>{a.forEach(i=>{i.isIntersecting&&!i.target.hasAttribute(C)&&_(i.target)&&i.target.setAttribute(C,"true")})},{root:null,rootMargin:"0px",threshold:.1});return e.forEach(a=>n.observe(a)),()=>{n.disconnect()}},[t,e]),x(()=>{if(t)return;let n=new MutationObserver(a=>{a.some(s=>s.type==="childList"&&s.addedNodes.length>0||s.type==="attributes"&&s.attributeName==="href")&&r(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()}},[t]),t?null:W(U,{dangerouslySetInnerHTML:{__html:JSON.stringify({prefetch:[{eagerness:"moderate",where:M},{eagerness:"immediate",where:X}],prerender:[{eagerness:"conservative",where:M}]})},id:"prefetch-zones-links",type:"speculationrules"})}import{jsx as O}from"react/jsx-runtime";var j=process.env.NEXT_PUBLIC_MFE_CURRENT_APPLICATION;function Q(t){let{clientConfig:e,isLoading:r}=p(process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,{removeFlaggedPathsFromDefault:!0}),{isRelativePath:o,zoneOfHref:n}=q(()=>{let i=typeof t=="string"&&t.startsWith("/");return{isRelativePath:i,zoneOfHref:i?e.getApplicationNameForPath(t):null}},[e,t]);return typeof t=="string"&&!t.length?{zoneOfHref:null,isDifferentZone:!1,isLoading:!1}:{zoneOfHref:n,isDifferentZone:!o||(n?j!==n:!1),isLoading:r}}var Y=$(({children:t,...e},r)=>{let{prefetchHref:o}=K(h),{zoneOfHref:n,isDifferentZone:a,isLoading:i}=Q(e.href);function s(){e.href&&o(e.href)}if(a&&n!==null){let{prefetch:f,...u}=e;return O("a",{...u,"data-zone":n,onFocus:e.prefetch!==!1?s:void 0,onMouseOver:e.prefetch!==!1?s:void 0,children:t})}return O(G,{...e,"data-zone":n?"same":"null",prefetch:e.prefetch??(i?!1:void 0),ref:r,children:t})});Y.displayName="MicrofrontendsLink";export{Y as Link,de as PrefetchCrossZoneLinks,h as PrefetchCrossZoneLinksContext,ae as PrefetchCrossZoneLinksProvider,Q as useZoneForHref}; //# sourceMappingURL=client.js.map