@tanstack/router-plugin
Version:
Modern and scalable routing for React applications
1 lines • 11.3 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 { 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 { debug } from './utils'\nimport type { CodeSplitGroupings, SplitRouteIdentNodes } from './constants'\nimport type { GetRoutesByFileMapResultValue } from '@tanstack/router-generator'\nimport type { Config } from './config'\nimport type {\n UnpluginContextMeta,\n UnpluginFactory,\n TransformResult as UnpluginTransformResult,\n} from 'unplugin'\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(\n externalPlugin: BannedBeforeExternalPlugin,\n pluginFramework: string,\n ) {\n super(`We detected that the '${externalPlugin.pkg}' was passed before '@tanstack/router-plugin/${pluginFramework}'. Please make sure that '@tanstack/router-plugin' is passed before '${externalPlugin.pkg}' and try again: \ne.g.\nplugins: [\n tanstackRouter(), // 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 generatorNodeInfo: GetRoutesByFileMapResultValue,\n ): UnpluginTransformResult => {\n if (debug) console.info('Compiling Route: ', id)\n\n const fromCode = detectCodeSplitGroupingsFromRoute({\n code,\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: generatorNodeInfo.routePath,\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 runtimeEnv: isProduction ? 'prod' : 'dev',\n codeSplitGroupings: splitGroupings,\n targetFramework: userConfig.target,\n filename: id,\n id,\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 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 {\n name: 'tanstack-router:code-splitter:compile-reference-file',\n enforce: 'pre',\n\n transform: {\n filter: {\n id: {\n exclude: tsrSplit,\n // this is necessary for webpack / rspack to avoid matching .html files\n include: /\\.(m|c)?(j|t)sx?$/,\n },\n code: 'createFileRoute(',\n },\n handler(code, id) {\n const generatorFileInfo = globalThis.TSR_ROUTES_BY_ID_MAP?.get(id)\n if (generatorFileInfo && code.includes('createFileRoute(')) {\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, generatorFileInfo)\n }\n\n return null\n },\n },\n\n vite: {\n configResolved(config) {\n ROOT = config.root\n userConfig = getConfig(options, ROOT)\n },\n },\n\n rspack() {\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 (compiler.options.mode === 'production') {\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 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 id = fileURLToPath(url).replace(/\\\\/g, '/')\n return handleCompilingVirtualFile(code, id)\n },\n },\n },\n ]\n}\n"],"names":["defaultCodeSplitGroupings","debug","detectCodeSplitGroupingsFromRoute","splitGroupingsSchema","compileCodeSplitReferenceRoute","logDiff","tsrSplit","decodeIdentifier","splitRouteIdentNodes","compileCodeSplitVirtualRoute","config","getConfig","pathToFileURL","fileURLToPath"],"mappings":"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"}