{"version":3,"file":"preload.cjs","names":["matchRemote","getRemoteEntry"],"sources":["../../src/utils/preload.ts"],"sourcesContent":["import { createLink, createScript, safeToString } from '@module-federation/sdk';\nimport {\n  PreloadAssets,\n  PreloadAssetResult,\n  PreloadConfig,\n  PreloadOptions,\n  PreloadRemoteArgs,\n  Remote,\n  RemoteInfo,\n  ResourceLoadContext,\n  ResourceLoadType,\n  depsPreloadArg,\n} from '../type';\nimport { matchRemote } from './manifest';\nimport { assert } from './logger';\nimport { ModuleFederation } from '../core';\nimport { getRemoteEntry } from './load';\n\nexport function defaultPreloadArgs(\n  preloadConfig: PreloadRemoteArgs | depsPreloadArg,\n): PreloadConfig {\n  return {\n    resourceCategory: 'sync',\n    share: true,\n    depsRemote: true,\n    ...preloadConfig,\n  } as PreloadConfig;\n}\n\nexport function formatPreloadArgs(\n  remotes: Array<Remote>,\n  preloadArgs: Array<PreloadRemoteArgs>,\n): PreloadOptions {\n  return preloadArgs.map((args) => {\n    const remoteInfo = matchRemote(remotes, args.nameOrAlias);\n    assert(\n      remoteInfo,\n      `Unable to preload ${args.nameOrAlias} as it is not included in ${\n        !remoteInfo &&\n        safeToString({\n          remoteInfo,\n          remotes,\n        })\n      }`,\n    );\n    return {\n      remote: remoteInfo,\n      preloadConfig: defaultPreloadArgs(args),\n    };\n  });\n}\n\nexport function normalizePreloadExposes(exposes?: string[]): string[] {\n  if (!exposes) {\n    return [];\n  }\n\n  return exposes.map((expose) => {\n    if (expose === '.') {\n      return expose;\n    }\n    if (expose.startsWith('./')) {\n      return expose.replace('./', '');\n    }\n    return expose;\n  });\n}\n\nfunction isTimeoutError(error: unknown): boolean {\n  if (!(error instanceof Error)) {\n    return false;\n  }\n  return error.message.includes('timed out') || error.name.includes('Timeout');\n}\n\nfunction createAssetResult(\n  context: ResourceLoadContext,\n  url: string,\n  status: PreloadAssetResult['status'],\n  error?: unknown,\n): PreloadAssetResult {\n  return {\n    url,\n    status,\n    resourceType: context.resourceType,\n    initiator: context.initiator,\n    id: context.id,\n    error,\n  };\n}\n\nasync function waitForRemoteEntryPreload(\n  host: ModuleFederation,\n  remoteInfo: RemoteInfo,\n  entryRemoteInfo: RemoteInfo,\n  context: ResourceLoadContext,\n): Promise<PreloadAssetResult> {\n  const cachedRemote = host.moduleCache.get(entryRemoteInfo.name);\n  const url = entryRemoteInfo.entry;\n  if (cachedRemote?.remoteEntryExports) {\n    return createAssetResult(context, url, 'cached');\n  }\n\n  try {\n    const remoteEntryExports = await getRemoteEntry({\n      origin: host,\n      remoteInfo: entryRemoteInfo,\n      remoteEntryExports: cachedRemote?.remoteEntryExports,\n      resourceContext: {\n        ...context,\n        url,\n      },\n    });\n    if (!remoteEntryExports) {\n      throw new Error(`Failed to load remoteEntry \"${url}\".`);\n    }\n    return createAssetResult(context, url, 'success');\n  } catch (error) {\n    return createAssetResult(\n      context,\n      url,\n      isTimeoutError(error) ? 'timeout' : 'error',\n      error,\n    );\n  }\n}\n\nfunction waitForLinkPreload({\n  host,\n  remoteInfo,\n  url,\n  attrs,\n  context,\n  needDeleteLink,\n}: {\n  host: ModuleFederation;\n  remoteInfo: RemoteInfo;\n  url: string;\n  attrs: Record<string, string>;\n  context: ResourceLoadContext;\n  needDeleteLink?: boolean;\n}): Promise<PreloadAssetResult> {\n  return new Promise((resolve) => {\n    const { link, needAttach } = createLink({\n      url,\n      cb: () => {\n        resolve(\n          createAssetResult(context, url, needAttach ? 'success' : 'cached'),\n        );\n      },\n      onErrorCallback: (error) => {\n        resolve(\n          createAssetResult(\n            context,\n            url,\n            isTimeoutError(error) ? 'timeout' : 'error',\n            error,\n          ),\n        );\n      },\n      attrs,\n      createLinkHook: (hookUrl, hookAttrs) => {\n        const res = host.loaderHook.lifecycle.createLink.emit({\n          url: hookUrl,\n          attrs: hookAttrs,\n          remoteInfo,\n          resourceContext: {\n            ...context,\n            url: hookUrl,\n          },\n        });\n        if (res instanceof HTMLLinkElement) {\n          return res;\n        }\n        return res;\n      },\n      needDeleteLink,\n    });\n\n    needAttach && document.head.appendChild(link);\n  });\n}\n\nfunction waitForScriptPreload({\n  host,\n  remoteInfo,\n  url,\n  attrs,\n  context,\n}: {\n  host: ModuleFederation;\n  remoteInfo: RemoteInfo;\n  url: string;\n  attrs: Record<string, string>;\n  context: ResourceLoadContext;\n}): Promise<PreloadAssetResult> {\n  return new Promise((resolve) => {\n    const { script, needAttach } = createScript({\n      url,\n      cb: () => {\n        resolve(\n          createAssetResult(context, url, needAttach ? 'success' : 'cached'),\n        );\n      },\n      onErrorCallback: (error) => {\n        resolve(\n          createAssetResult(\n            context,\n            url,\n            isTimeoutError(error) ? 'timeout' : 'error',\n            error,\n          ),\n        );\n      },\n      attrs,\n      createScriptHook: (hookUrl: string, hookAttrs: any) => {\n        const res = host.loaderHook.lifecycle.createScript.emit({\n          url: hookUrl,\n          attrs: hookAttrs,\n          remoteInfo,\n          resourceContext: {\n            ...context,\n            url: hookUrl,\n          },\n        });\n        if (res instanceof HTMLScriptElement) {\n          return res;\n        }\n        return res;\n      },\n      needDeleteScript: true,\n    });\n\n    needAttach && document.head.appendChild(script);\n  });\n}\n\nfunction createResourceContext(\n  baseContext: Omit<ResourceLoadContext, 'resourceType'>,\n  resourceType: ResourceLoadType,\n): ResourceLoadContext {\n  return {\n    ...baseContext,\n    resourceType,\n  };\n}\n\nexport function preloadAssets(\n  remoteInfo: RemoteInfo,\n  host: ModuleFederation,\n  assets: PreloadAssets,\n  // It is used to distinguish preload from load remote parallel loading\n  useLinkPreload = true,\n  baseContext: Omit<ResourceLoadContext, 'resourceType'> = {\n    initiator: 'preloadRemote',\n    id: remoteInfo.name,\n  },\n): Promise<PreloadAssetResult[]> {\n  const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;\n  const results: Array<Promise<PreloadAssetResult>> = [];\n\n  if (host.options.inBrowser) {\n    entryAssets.forEach((asset) => {\n      const { moduleInfo: entryRemoteInfo } = asset;\n      results.push(\n        waitForRemoteEntryPreload(\n          host,\n          remoteInfo,\n          entryRemoteInfo,\n          createResourceContext(baseContext, 'remoteEntry'),\n        ),\n      );\n    });\n\n    if (useLinkPreload) {\n      const defaultAttrs = {\n        rel: 'preload',\n        as: 'style',\n      };\n      cssAssets.forEach((cssUrl) => {\n        results.push(\n          waitForLinkPreload({\n            host,\n            remoteInfo,\n            url: cssUrl,\n            attrs: defaultAttrs,\n            context: createResourceContext(baseContext, 'css'),\n          }),\n        );\n      });\n    } else {\n      const defaultAttrs = {\n        rel: 'stylesheet',\n        type: 'text/css',\n      };\n      cssAssets.forEach((cssUrl) => {\n        results.push(\n          waitForLinkPreload({\n            host,\n            remoteInfo,\n            url: cssUrl,\n            attrs: defaultAttrs,\n            needDeleteLink: false,\n            context: createResourceContext(baseContext, 'css'),\n          }),\n        );\n      });\n    }\n\n    if (useLinkPreload) {\n      const defaultAttrs = {\n        rel: 'preload',\n        as: 'script',\n      };\n      jsAssetsWithoutEntry.forEach((jsUrl) => {\n        results.push(\n          waitForLinkPreload({\n            host,\n            remoteInfo,\n            url: jsUrl,\n            attrs: defaultAttrs,\n            context: createResourceContext(baseContext, 'js'),\n          }),\n        );\n      });\n    } else {\n      const defaultAttrs = {\n        fetchpriority: 'high',\n        type: remoteInfo?.type === 'module' ? 'module' : 'text/javascript',\n      };\n      jsAssetsWithoutEntry.forEach((jsUrl) => {\n        results.push(\n          waitForScriptPreload({\n            host,\n            remoteInfo,\n            url: jsUrl,\n            attrs: defaultAttrs,\n            context: createResourceContext(baseContext, 'js'),\n          }),\n        );\n      });\n    }\n  }\n\n  return Promise.all(results);\n}\n"],"mappings":"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"}