export default async function runClientApp()

in packages/runtime/src/runClientApp.tsx [40:136]


export default async function runClientApp(options: RunClientAppOptions) {
  const {
    app,
    createRoutes,
    runtimeModules,
    basename,
    hydrate,
    memoryRouter,
    runtimeOptions,
    dataLoaderFetcher,
    dataLoaderDecorator,
  } = options;

  const windowContext: WindowContext = (window as any).__ICE_APP_CONTEXT__ || {};
  const assetsManifest: AssetsManifest = (window as any).__ICE_ASSETS_MANIFEST__ || {};
  let {
    appData,
    loaderData,
    routePath,
    downgrade,
    documentOnly,
    renderMode,
    serverData,
    revalidate,
  } = windowContext;
  const formattedBasename = addLeadingSlash(basename);
  const requestContext = getRequestContext(window.location);
  const appConfig = getAppConfig(app);
  const routes = createRoutes ? createRoutes({
    requestContext,
    renderMode: 'CSR',
  }) : [];
  const historyOptions = {
    memoryRouter,
    initialEntry: routePath,
    routes,
  };
  const history = createHistory(appConfig, historyOptions);
  // Set history for import it from ice.
  setHistory(deprecatedHistory(history));

  const appContext: AppContext = {
    appExport: app,
    routes,
    appConfig,
    appData,
    loaderData,
    assetsManifest,
    basename: formattedBasename,
    routePath,
    renderMode,
    requestContext,
    serverData,
    revalidate,
  };

  const runtime = new Runtime(appContext, runtimeOptions);
  runtime.setAppRouter<ClientAppRouterProps>(ClientRouter);
  // Load static module before getAppData,
  // so we can call request in in getAppData which provide by `plugin-request`.
  if (runtimeModules.statics) {
    await Promise.all(runtimeModules.statics.map(m => runtime.loadModule(m)).filter(Boolean));
  }

  if (process.env.ICE_CORE_REMOVE_DATA_LOADER !== 'true') {
    dataLoaderFetcher && setFetcher(dataLoaderFetcher);
    dataLoaderDecorator && setDecorator(dataLoaderDecorator);
  }

  if (!appData) {
    appData = await getAppData(app, requestContext);
  }

  const needHydrate = hydrate && !downgrade && !documentOnly;
  if (needHydrate) {
    runtime.setRender((container, element) => {
      const hydrateOptions: ReactDOM.HydrationOptions = {
        // @ts-ignore react-dom do not define the type of second argument of onRecoverableError.
        onRecoverableError: appConfig?.app?.onRecoverableError ||
        ((error: unknown, errorInfo: ErrorStack) => {
          reportRecoverableError(error, errorInfo, { ignoreRuntimeWarning: revalidate });
        }),
      };
      if (appConfig?.app?.onBeforeHydrate) {
        appConfig?.app?.onBeforeHydrate();
      }
      return ReactDOM.hydrateRoot(container, element, hydrateOptions);
    });
  }
  // Reset app context after app context is updated.
  runtime.setAppContext({ ...appContext, appData });
  if (runtimeModules.commons) {
    await Promise.all(runtimeModules.commons.map(m => runtime.loadModule(m)).filter(Boolean));
  }

  return render({ runtime, history, needHydrate });
}