Repository: remix-run/react-router
File: packages/react-router-dev/vite/plugin.ts (TypeScript)

Code before:
const BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";

export type EnvironmentName =
  | "client"
  | SsrEnvironmentName
  | CssDevHelperEnvironmentName;

const SSR_BUNDLE_PREFIX = "ssrBundle_";
type SsrBundleEnvironmentName = `${typeof SSR_BUNDLE_PREFIX}${string}`;
type SsrEnvironmentName = "ssr" | SsrBundleEnvironmentName;

function isSsrBundleEnvironmentName(
  name: string
): name is SsrBundleEnvironmentName {
  return name.startsWith(SSR_BUNDLE_PREFIX);
}

// We use a separate environment for loading the critical CSS during
// development. This is because "ssrLoadModule" isn't available if the "ssr"
// environment has been defined by another plugin (e.g.
// vite-plugin-cloudflare) as a custom Vite.DevEnvironment rather than a
// Vite.RunnableDevEnvironment:
// https://vite.dev/guide/api-environment-frameworks.html#runtime-agnostic-ssr
const CSS_DEV_HELPER_ENVIRONMENT_NAME =
  "__react_router_css_dev_helper__" as const;
type CssDevHelperEnvironmentName = typeof CSS_DEV_HELPER_ENVIRONMENT_NAME;

type EnvironmentOptions = Pick<Vite.EnvironmentOptions, "build" | "resolve">;

type EnvironmentOptionsResolver = (options: {
  viteUserConfig: Vite.UserConfig;
}) => EnvironmentOptions;

type EnvironmentOptionsResolvers = Partial<
  Record<EnvironmentName, EnvironmentOptionsResolver>
>;

export type EnvironmentBuildContext = {
  name: EnvironmentName;
  resolveOptions: EnvironmentOptionsResolver;
};

function getServerEnvironmentEntries<T>(
  ctx: ReactRouterPluginContext,
  record: Record<string, T>
): [SsrEnvironmentName, T][] {
  return Object.entries(record).filter(([name]) =>
    ctx.buildManifest?.serverBundles
      ? isSsrBundleEnvironmentName(name)
      : name === "ssr"
  ) as [SsrEnvironmentName, T][];

Review comment (suggestion):
Now that we're loading the CSS from the client environment, we don't need to introduce a custom `Vite.RunnableDevEnvironment` anymore. This was only introduced because we were originally importing the CSS from the SSR environment, but when using `vite-plugin-cloudflare`, the SSR environment was a custom `Vite.DevEnvironment` that couldn't be imported from. With our new approach in this PR, this distinction doesn't matter.

Code after:
/** This is used to manage a build optimization to remove unused route exports
from the client build output. This is important in cases where custom route
exports are only ever used on the server. Without this optimization we can't
tree-shake any unused custom exports because routes are entry points. */
const BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";

export type EnvironmentName = "client" | SsrEnvironmentName;

const SSR_BUNDLE_PREFIX = "ssrBundle_";
type SsrBundleEnvironmentName = `${typeof SSR_BUNDLE_PREFIX}${string}`;
type SsrEnvironmentName = "ssr" | SsrBundleEnvironmentName;

function isSsrBundleEnvironmentName(
  name: string
): name is SsrBundleEnvironmentName {
  return name.startsWith(SSR_BUNDLE_PREFIX);
}

type EnvironmentOptions = Pick<Vite.EnvironmentOptions, "build" | "resolve">;

type EnvironmentOptionsResolver = (options: {
  viteUserConfig: Vite.UserConfig;
}) => EnvironmentOptions;

type EnvironmentOptionsResolvers = Partial<
  Record<EnvironmentName, EnvironmentOptionsResolver>
>;

export type EnvironmentBuildContext = {
  name: EnvironmentName;
  resolveOptions: EnvironmentOptionsResolver;
};

function getServerEnvironmentEntries<T>(
  ctx: ReactRouterPluginContext,
  record: Record<string, T>
): [SsrEnvironmentName, T][] {
  return Object.entries(record).filter(([name]) =>
    ctx.buildManifest?.serverBundles
      ? isSsrBundleEnvironmentName(name)
      : name === "ssr"
  ) as [SsrEnvironmentName, T][];
}

export function getServerEnvironmentKeys(
  ctx: ReactRouterPluginContext,
  record: Record<string, unknown>
): SsrEnvironmentName[] {
  return getServerEnvironmentEntries(ctx, record).map(([key]) => key);
}