@tanstack/router-plugin
Version:
Modern and scalable routing for React applications
1 lines • 12 kB
Source Map (JSON)
{"version":3,"file":"router-code-splitter-plugin.cjs","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 { isAbsolute, join, normalize } from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { logDiff } from '@tanstack/router-utils'\nimport { getConfig, splitGroupingsSchema } from './config'\nimport {\n compileCodeSplitReferenceRoute,\n compileCodeSplitVirtualRoute,\n detectCodeSplitGroupingsFromRoute,\n} from './code-splitter/compilers'\nimport {\n defaultCodeSplitGroupings,\n splitRouteIdentNodes,\n tsrSplit,\n} from './constants'\nimport { decodeIdentifier } from './code-splitter/path-ids'\nimport type { CodeSplitGroupings, SplitRouteIdentNodes } from './constants'\n\nimport type { Config } from './config'\nimport type {\n UnpluginContextMeta,\n UnpluginFactory,\n TransformResult as UnpluginTransformResult,\n} from 'unplugin'\n\nconst debug =\n process.env.TSR_VITE_DEBUG &&\n ['true', 'router-plugin'].includes(process.env.TSR_VITE_DEBUG)\n\nfunction capitalizeFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1)\n}\n\nfunction fileIsInRoutesDirectory(\n filePath: string,\n routesDirectory: string,\n): boolean {\n const routesDirectoryPath = isAbsolute(routesDirectory)\n ? routesDirectory\n : join(process.cwd(), routesDirectory)\n\n const path = normalize(filePath)\n\n return path.startsWith(routesDirectoryPath)\n}\n\ntype BannedBeforeExternalPlugin = {\n identifier: string\n pkg: string\n usage: string\n frameworks: Array<UnpluginContextMeta['framework']>\n}\n\nconst bannedBeforeExternalPlugins: Array<BannedBeforeExternalPlugin> = [\n {\n identifier: '@react-refresh',\n pkg: '@vitejs/plugin-react',\n usage: 'viteReact()',\n frameworks: ['vite'],\n },\n]\n\nclass FoundPluginInBeforeCode extends Error {\n constructor(externalPlugin: BannedBeforeExternalPlugin, framework: string) {\n super(`We detected that the '${externalPlugin.pkg}' was passed before '@tanstack/router-plugin'. Please make sure that '@tanstack/router-plugin' is passed before '${externalPlugin.pkg}' and try again: \ne.g.\nplugins: [\n TanStackRouter${capitalizeFirst(framework)}(), // Place this before ${externalPlugin.usage}\n ${externalPlugin.usage},\n]\n`)\n }\n}\n\nconst PLUGIN_NAME = 'unplugin:router-code-splitter'\n\nexport const unpluginRouterCodeSplitterFactory: UnpluginFactory<\n Partial<Config> | undefined\n> = (options = {}, { framework }) => {\n let ROOT: string = process.cwd()\n let userConfig = options as Config\n\n const isProduction = process.env.NODE_ENV === 'production'\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 ): UnpluginTransformResult => {\n if (debug) console.info('Compiling Route: ', id)\n\n const fromCode = detectCodeSplitGroupingsFromRoute({\n code,\n root: ROOT,\n filename: id,\n })\n\n if (fromCode.groupings) {\n const res = splitGroupingsSchema.safeParse(fromCode.groupings)\n if (!res.success) {\n const message = res.error.errors.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: fromCode.routeId,\n }) as CodeSplitGroupings | undefined\n\n if (pluginSplitBehavior) {\n const res = splitGroupingsSchema.safeParse(pluginSplitBehavior)\n if (!res.success) {\n const message = res.error.errors.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 const compiledReferenceRoute = compileCodeSplitReferenceRoute({\n code,\n root: ROOT,\n filename: id,\n runtimeEnv: isProduction ? 'prod' : 'dev',\n codeSplitGroupings: splitGroupings,\n targetFramework: userConfig.target,\n })\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 result = compileCodeSplitVirtualRoute({\n code,\n root: ROOT,\n filename: id,\n splitTargets: grouping,\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 name: 'router-code-splitter-plugin',\n enforce: 'pre',\n\n transform(code, id) {\n if (!userConfig.autoCodeSplitting) {\n return null\n }\n\n const url = pathToFileURL(id)\n url.searchParams.delete('v')\n id = fileURLToPath(url).replace(/\\\\/g, '/')\n\n if (id.includes(tsrSplit)) {\n return handleCompilingVirtualFile(code, id)\n } else if (\n fileIsInRoutesDirectory(id, userConfig.routesDirectory) &&\n (code.includes('createRoute(') || code.includes('createFileRoute('))\n ) {\n for (const externalPlugin of bannedBeforeExternalPlugins) {\n if (!externalPlugin.frameworks.includes(framework)) {\n continue\n }\n\n if (code.includes(externalPlugin.identifier)) {\n throw new FoundPluginInBeforeCode(externalPlugin, framework)\n }\n }\n\n return handleCompilingReferenceFile(code, id)\n }\n\n return null\n },\n\n transformInclude(id) {\n if (!userConfig.autoCodeSplitting) {\n return undefined\n }\n\n if (\n fileIsInRoutesDirectory(id, userConfig.routesDirectory) ||\n id.includes(tsrSplit)\n ) {\n return true\n }\n return false\n },\n\n vite: {\n configResolved(config) {\n ROOT = config.root\n\n userConfig = getConfig(options, ROOT)\n },\n },\n\n rspack(_compiler) {\n ROOT = process.cwd()\n userConfig = getConfig(options, ROOT)\n },\n\n webpack(compiler) {\n ROOT = process.cwd()\n userConfig = getConfig(options, ROOT)\n\n if (\n userConfig.autoCodeSplitting &&\n compiler.options.mode === 'production'\n ) {\n compiler.hooks.done.tap(PLUGIN_NAME, () => {\n console.info('✅ ' + PLUGIN_NAME + ': code-splitting done!')\n setTimeout(() => {\n process.exit(0)\n })\n })\n }\n },\n }\n}\n"],"names":["isAbsolute","join","normalize","defaultCodeSplitGroupings","detectCodeSplitGroupingsFromRoute","splitGroupingsSchema","compileCodeSplitReferenceRoute","logDiff","tsrSplit","decodeIdentifier","splitRouteIdentNodes","compileCodeSplitVirtualRoute","pathToFileURL","fileURLToPath","config","getConfig"],"mappings":"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"}