{"version":3,"file":"router-code-splitter-plugin.cjs","names":[],"sources":["../../../src/core/router-code-splitter-plugin.ts"],"sourcesContent":["/**\n * It is important to familiarize yourself with how the code-splitting works in this plugin.\n * https://github.com/TanStack/router/pull/3355\n */\n\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { decodeIdentifier, logDiff } from '@tanstack/router-utils'\nimport { getConfig, splitGroupingsSchema } from './config'\nimport {\n  compileCodeSplitReferenceRoute,\n  compileCodeSplitSharedRoute,\n  compileCodeSplitVirtualRoute,\n  computeSharedBindings,\n  detectCodeSplitGroupingsFromRoute,\n} from './code-splitter/compilers'\nimport { getReferenceRouteCompilerPlugins } from './code-splitter/plugins/framework-plugins'\nimport {\n  defaultCodeSplitGroupings,\n  splitRouteIdentNodes,\n  tsrShared,\n  tsrSplit,\n} from './constants'\nimport { debug, normalizePath, routeFactoryCallCodeFilter } from './utils'\nimport { createRouterPluginContext } from './router-plugin-context'\nimport type { CodeSplitGroupings, SplitRouteIdentNodes } from './constants'\nimport type { GetRoutesByFileMapResultValue } from '@tanstack/router-generator'\nimport type { Config } from './config'\nimport type { RouterPluginContext } from './router-plugin-context'\nimport type {\n  UnpluginFactory,\n  TransformResult as UnpluginTransformResult,\n} from 'unplugin'\n\nconst CODE_SPLITTER_PLUGIN_NAME =\n  'tanstack-router:code-splitter:compile-reference-file'\n\ntype TransformationPluginInfo = {\n  pluginNames: Array<string>\n  pkg: string\n  usage: string\n}\n\n/**\n * JSX transformation plugins grouped by framework.\n * These plugins must come AFTER the TanStack Router plugin in the Vite config.\n */\nconst TRANSFORMATION_PLUGINS_BY_FRAMEWORK: Record<\n  string,\n  Array<TransformationPluginInfo>\n> = {\n  react: [\n    {\n      // Babel-based React plugin\n      pluginNames: ['vite:react-babel', 'vite:react-refresh'],\n      pkg: '@vitejs/plugin-react',\n      usage: 'react()',\n    },\n    {\n      // SWC-based React plugin\n      pluginNames: ['vite:react-swc', 'vite:react-swc:resolve-runtime'],\n      pkg: '@vitejs/plugin-react-swc',\n      usage: 'reactSwc()',\n    },\n    {\n      // OXC-based React plugin (deprecated but should still be handled)\n      pluginNames: ['vite:react-oxc:config', 'vite:react-oxc:refresh-runtime'],\n      pkg: '@vitejs/plugin-react-oxc',\n      usage: 'reactOxc()',\n    },\n  ],\n  solid: [\n    {\n      pluginNames: ['solid'],\n      pkg: 'vite-plugin-solid',\n      usage: 'solid()',\n    },\n  ],\n}\n\nexport function createRouterCodeSplitterPlugin(\n  options: Partial<Config | (() => Config)> | undefined = {},\n  routerPluginContext: RouterPluginContext,\n): ReturnType<UnpluginFactory<Partial<Config | (() => Config)> | undefined>> {\n  let ROOT: string = process.cwd()\n  let userConfig: Config\n\n  function initUserConfig() {\n    if (typeof options === 'function') {\n      userConfig = options()\n    } else {\n      userConfig = getConfig(options, ROOT)\n    }\n  }\n  const isProduction = process.env.NODE_ENV === 'production'\n  // Map from normalized route file path → set of shared binding names.\n  // Populated by the reference compiler, consumed by virtual and shared compilers.\n  const sharedBindingsMap = new Map<string, Set<string>>()\n\n  const getGlobalCodeSplitGroupings = () => {\n    return (\n      userConfig.codeSplittingOptions?.defaultBehavior ||\n      defaultCodeSplitGroupings\n    )\n  }\n  const getShouldSplitFn = () => {\n    return userConfig.codeSplittingOptions?.splitBehavior\n  }\n\n  const handleCompilingReferenceFile = (\n    code: string,\n    id: string,\n    generatorNodeInfo: GetRoutesByFileMapResultValue,\n  ): UnpluginTransformResult => {\n    if (debug) console.info('Compiling Route: ', id)\n\n    const fromCode = detectCodeSplitGroupingsFromRoute({\n      code,\n      filename: id,\n    })\n\n    if (fromCode.groupings !== undefined) {\n      const res = splitGroupingsSchema.safeParse(fromCode.groupings)\n      if (!res.success) {\n        const message = res.error.issues.map((e) => e.message).join('. ')\n        throw new Error(\n          `The groupings for the route \"${id}\" are invalid.\\n${message}`,\n        )\n      }\n    }\n\n    const userShouldSplitFn = getShouldSplitFn()\n\n    const pluginSplitBehavior = userShouldSplitFn?.({\n      routeId: generatorNodeInfo.routeId,\n    }) as CodeSplitGroupings | undefined\n\n    if (pluginSplitBehavior) {\n      const res = splitGroupingsSchema.safeParse(pluginSplitBehavior)\n      if (!res.success) {\n        const message = res.error.issues.map((e) => e.message).join('. ')\n        throw new Error(\n          `The groupings returned when using \\`splitBehavior\\` for the route \"${id}\" are invalid.\\n${message}`,\n        )\n      }\n    }\n\n    const splitGroupings: CodeSplitGroupings =\n      fromCode.groupings ?? pluginSplitBehavior ?? getGlobalCodeSplitGroupings()\n\n    // Compute shared bindings before compiling the reference route\n    const sharedBindings = computeSharedBindings({\n      code,\n      filename: id,\n      codeSplitGroupings: splitGroupings,\n    })\n    if (sharedBindings.size > 0) {\n      sharedBindingsMap.set(id, sharedBindings)\n    } else {\n      sharedBindingsMap.delete(id)\n    }\n\n    const addHmr =\n      (userConfig.codeSplittingOptions?.addHmr ?? true) && !isProduction\n    const hmrStyle = userConfig.plugin?.hmr?.style ?? 'vite'\n\n    const compiledReferenceRoute = compileCodeSplitReferenceRoute({\n      code,\n      codeSplitGroupings: splitGroupings,\n      targetFramework: userConfig.target,\n      filename: id,\n      id,\n      deleteNodes: userConfig.codeSplittingOptions?.deleteNodes\n        ? new Set(userConfig.codeSplittingOptions.deleteNodes)\n        : undefined,\n      addHmr,\n      hmrStyle,\n      hmrRouteId: generatorNodeInfo.routeId,\n      sharedBindings: sharedBindings.size > 0 ? sharedBindings : undefined,\n      compilerPlugins: [\n        ...(getReferenceRouteCompilerPlugins({\n          targetFramework: userConfig.target,\n          addHmr,\n          hmrStyle,\n        }) ?? []),\n        ...(userConfig.codeSplittingOptions?.compilerPlugins ?? []),\n      ],\n    })\n\n    if (compiledReferenceRoute === null) {\n      if (debug) {\n        console.info(\n          `No changes made to route \"${id}\", skipping code-splitting.`,\n        )\n      }\n      return null\n    }\n    if (debug) {\n      logDiff(code, compiledReferenceRoute.code)\n      console.log('Output:\\n', compiledReferenceRoute.code + '\\n\\n')\n    }\n\n    return compiledReferenceRoute\n  }\n\n  const handleCompilingVirtualFile = (\n    code: string,\n    id: string,\n  ): UnpluginTransformResult => {\n    if (debug) console.info('Splitting Route: ', id)\n\n    const [_, ...pathnameParts] = id.split('?')\n\n    const searchParams = new URLSearchParams(pathnameParts.join('?'))\n    const splitValue = searchParams.get(tsrSplit)\n\n    if (!splitValue) {\n      throw new Error(\n        `The split value for the virtual route \"${id}\" was not found.`,\n      )\n    }\n\n    const rawGrouping = decodeIdentifier(splitValue)\n    const grouping = [...new Set(rawGrouping)].filter((p) =>\n      splitRouteIdentNodes.includes(p as any),\n    ) as Array<SplitRouteIdentNodes>\n\n    const baseId = id.split('?')[0]!\n    const resolvedSharedBindings = sharedBindingsMap.get(baseId)\n\n    const result = compileCodeSplitVirtualRoute({\n      code,\n      filename: id,\n      splitTargets: grouping,\n      sharedBindings: resolvedSharedBindings,\n    })\n\n    if (debug) {\n      logDiff(code, result.code)\n      console.log('Output:\\n', result.code + '\\n\\n')\n    }\n\n    return result\n  }\n\n  return [\n    {\n      name: 'tanstack-router:code-splitter:compile-reference-file',\n      enforce: 'pre',\n\n      transform: {\n        filter: {\n          id: {\n            exclude: [tsrSplit, tsrShared],\n            // this is necessary for webpack / rspack to avoid matching .html files\n            include: /\\.(m|c)?(j|t)sx?$/,\n          },\n          code: {\n            include: routeFactoryCallCodeFilter,\n          },\n        },\n        handler(code, id) {\n          const normalizedId = normalizePath(id)\n          const generatorFileInfo =\n            routerPluginContext.routesByFile.get(normalizedId)\n          if (generatorFileInfo) {\n            return handleCompilingReferenceFile(\n              code,\n              normalizedId,\n              generatorFileInfo,\n            )\n          }\n\n          return null\n        },\n      },\n\n      vite: {\n        configResolved(config) {\n          ROOT = config.root\n          initUserConfig()\n\n          // Validate plugin order - router must come before JSX transformation plugins\n          const routerPluginIndex = config.plugins.findIndex(\n            (p) => p.name === CODE_SPLITTER_PLUGIN_NAME,\n          )\n\n          if (routerPluginIndex === -1) return\n\n          const frameworkPlugins =\n            TRANSFORMATION_PLUGINS_BY_FRAMEWORK[userConfig.target]\n          if (!frameworkPlugins) return\n\n          for (const transformPlugin of frameworkPlugins) {\n            const transformPluginIndex = config.plugins.findIndex((p) =>\n              transformPlugin.pluginNames.includes(p.name),\n            )\n\n            if (\n              transformPluginIndex !== -1 &&\n              transformPluginIndex < routerPluginIndex\n            ) {\n              throw new Error(\n                `Plugin order error: '${transformPlugin.pkg}' is placed before '@tanstack/router-plugin'.\\n\\n` +\n                  `The TanStack Router plugin must come BEFORE JSX transformation plugins.\\n\\n` +\n                  `Please update your Vite config:\\n\\n` +\n                  `  plugins: [\\n` +\n                  `    tanstackRouter(),\\n` +\n                  `    ${transformPlugin.usage},\\n` +\n                  `  ]\\n`,\n              )\n            }\n          }\n        },\n        applyToEnvironment(environment) {\n          if (userConfig.plugin?.vite?.environmentName) {\n            return userConfig.plugin.vite.environmentName === environment.name\n          }\n          return true\n        },\n      },\n\n      rspack() {\n        ROOT = process.cwd()\n        initUserConfig()\n      },\n\n      webpack() {\n        ROOT = process.cwd()\n        initUserConfig()\n      },\n    },\n    {\n      name: 'tanstack-router:code-splitter:compile-virtual-file',\n      enforce: 'pre',\n\n      transform: {\n        filter: {\n          id: /tsr-split/,\n        },\n        handler(code, id) {\n          const url = pathToFileURL(id)\n          url.searchParams.delete('v')\n          const normalizedId = normalizePath(fileURLToPath(url))\n          return handleCompilingVirtualFile(code, normalizedId)\n        },\n      },\n\n      vite: {\n        applyToEnvironment(environment) {\n          if (userConfig.plugin?.vite?.environmentName) {\n            return userConfig.plugin.vite.environmentName === environment.name\n          }\n          return true\n        },\n      },\n    },\n    {\n      name: 'tanstack-router:code-splitter:compile-shared-file',\n      enforce: 'pre',\n\n      transform: {\n        filter: {\n          id: /tsr-shared/,\n        },\n        handler(code, id) {\n          const url = pathToFileURL(id)\n          url.searchParams.delete('v')\n          const normalizedId = normalizePath(fileURLToPath(url))\n          const [baseId] = normalizedId.split('?')\n\n          if (!baseId) return null\n\n          const sharedBindings = sharedBindingsMap.get(baseId)\n          if (!sharedBindings || sharedBindings.size === 0) return null\n\n          if (debug) console.info('Compiling Shared Module: ', id)\n\n          const result = compileCodeSplitSharedRoute({\n            code,\n            sharedBindings,\n            filename: normalizedId,\n          })\n\n          if (debug) {\n            logDiff(code, result.code)\n            console.log('Output:\\n', result.code + '\\n\\n')\n          }\n\n          return result\n        },\n      },\n\n      vite: {\n        applyToEnvironment(environment) {\n          if (userConfig.plugin?.vite?.environmentName) {\n            return userConfig.plugin.vite.environmentName === environment.name\n          }\n          return true\n        },\n      },\n    },\n  ]\n}\n\nexport const unpluginRouterCodeSplitterFactory: UnpluginFactory<\n  Partial<Config | (() => Config)> | undefined\n> = (options = {}) => {\n  return createRouterCodeSplitterPlugin(options, createRouterPluginContext())\n}\n"],"mappings":"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"}