Repository: remix-run/react-router
File: packages/react-router/lib/dom/ssr/single-fetch.tsx (TypeScript)

Code before:
  manifest: AssetsManifest,
  ssr: boolean,
  basename: string | undefined,
  getRouter: () => DataRouter
): DataStrategyFunction {
  let dataStrategy = getSingleFetchDataStrategyImpl(
    manifest,
    ssr,
    basename,
    getRouter
  );
  return async (args) => args.unstable_runMiddleware(dataStrategy);
}

export function getSingleFetchDataStrategyImpl(
  manifest: AssetsManifest,
  ssr: boolean,
  basename: string | undefined,
  getRouter: () => DataRouter
): DataStrategyFunction {
  return async (args) => {
    let { request, matches, fetcherKey } = args;

    // Actions are simple and behave the same for navigations and fetchers
    if (request.method !== "GET") {
      return singleFetchActionStrategy(args, basename);
    }

    let foundRevalidatingServerLoader = matches.some(
      (m) =>
        m.unstable_shouldCallHandler() &&
        manifest.routes[m.route.id]?.hasLoader &&
        !manifest.routes[m.route.id]?.hasClientLoader
    );
    if (!ssr && !foundRevalidatingServerLoader) {
      // If this is SPA mode, there won't be any loaders below root and we'll
      // disable single fetch.  We have to keep the `dataStrategy` defined for
      // SPA mode because we may load a SPA fallback page but then navigate into
      // a pre-rendered path and need to fetch the pre-rendered `.data` file.
      //
      // If this is `ssr:false` with a `prerender` config, we need to keep single
      // fetch enabled because we can prerender the `.data` files at build time
      // and load them from a static file server/CDN at runtime.
      //
      // However, with the SPA Fallback logic, we can have SPA routes operating
      // alongside pre-rendered routes.  If any pre-rendered routes have a
      // `loader` then the default behavior would be to make the single fetch
      // `.data` request on navigation to get the updated root/parent route
      // `loader` data.
      //
      // We need to detect these scenarios because if it's a non-pre-rendered

Review comment (suggestion):
This goes back to effectively the original non-middleware implementation because we wrap middleware around the whole thing above

Code after:
  manifest: AssetsManifest,
  ssr: boolean,
  basename: string | undefined,
  getRouter: () => DataRouter
): DataStrategyFunction {
  let dataStrategy = getSingleFetchDataStrategyImpl(
    manifest,
    ssr,
    basename,
    getRouter
  );
  return async (args) => args.unstable_runClientMiddleware(dataStrategy);
}

export function getSingleFetchDataStrategyImpl(
  manifest: AssetsManifest,
  ssr: boolean,
  basename: string | undefined,
  getRouter: () => DataRouter
): DataStrategyFunction {
  return async (args) => {
    let { request, matches, fetcherKey } = args;

    // Actions are simple and behave the same for navigations and fetchers
    if (request.method !== "GET") {
      return singleFetchActionStrategy(args, basename);
    }

    let foundRevalidatingServerLoader = matches.some(
      (m) =>
        m.unstable_shouldCallHandler() &&
        manifest.routes[m.route.id]?.hasLoader &&
        !manifest.routes[m.route.id]?.hasClientLoader
    );
    if (!ssr && !foundRevalidatingServerLoader) {
      // If this is SPA mode, there won't be any loaders below root and we'll
      // disable single fetch.  We have to keep the `dataStrategy` defined for
      // SPA mode because we may load a SPA fallback page but then navigate into
      // a pre-rendered path and need to fetch the pre-rendered `.data` file.
      //
      // If this is `ssr:false` with a `prerender` config, we need to keep single
      // fetch enabled because we can prerender the `.data` files at build time
      // and load them from a static file server/CDN at runtime.
      //
      // However, with the SPA Fallback logic, we can have SPA routes operating
      // alongside pre-rendered routes.  If any pre-rendered routes have a
      // `loader` then the default behavior would be to make the single fetch
      // `.data` request on navigation to get the updated root/parent route
      // `loader` data.
      //
      // We need to detect these scenarios because if it's a non-pre-rendered