UNPKG

@tanstack/router-plugin

Version:

Modern and scalable routing for React applications

239 lines (238 loc) 9.61 kB
require("../_virtual/_rolldown/runtime.cjs"); const require_config = require("./config.cjs"); const require_constants = require("./constants.cjs"); const require_path_ids = require("./code-splitter/path-ids.cjs"); const require_compilers = require("./code-splitter/compilers.cjs"); const require_utils = require("./utils.cjs"); const require_framework_plugins = require("./code-splitter/plugins/framework-plugins.cjs"); let node_url = require("node:url"); let _tanstack_router_utils = require("@tanstack/router-utils"); //#region src/core/router-code-splitter-plugin.ts /** * It is important to familiarize yourself with how the code-splitting works in this plugin. * https://github.com/TanStack/router/pull/3355 */ var PLUGIN_NAME = "unplugin:router-code-splitter"; var CODE_SPLITTER_PLUGIN_NAME = "tanstack-router:code-splitter:compile-reference-file"; /** * JSX transformation plugins grouped by framework. * These plugins must come AFTER the TanStack Router plugin in the Vite config. */ var TRANSFORMATION_PLUGINS_BY_FRAMEWORK = { react: [ { pluginNames: ["vite:react-babel", "vite:react-refresh"], pkg: "@vitejs/plugin-react", usage: "react()" }, { pluginNames: ["vite:react-swc", "vite:react-swc:resolve-runtime"], pkg: "@vitejs/plugin-react-swc", usage: "reactSwc()" }, { pluginNames: ["vite:react-oxc:config", "vite:react-oxc:refresh-runtime"], pkg: "@vitejs/plugin-react-oxc", usage: "reactOxc()" } ], solid: [{ pluginNames: ["solid"], pkg: "vite-plugin-solid", usage: "solid()" }] }; var unpluginRouterCodeSplitterFactory = (options = {}, { framework: _framework }) => { let ROOT = process.cwd(); let userConfig; function initUserConfig() { if (typeof options === "function") userConfig = options(); else userConfig = require_config.getConfig(options, ROOT); } const isProduction = process.env.NODE_ENV === "production"; const sharedBindingsMap = /* @__PURE__ */ new Map(); const getGlobalCodeSplitGroupings = () => { return userConfig.codeSplittingOptions?.defaultBehavior || require_constants.defaultCodeSplitGroupings; }; const getShouldSplitFn = () => { return userConfig.codeSplittingOptions?.splitBehavior; }; const handleCompilingReferenceFile = (code, id, generatorNodeInfo) => { if (require_utils.debug) console.info("Compiling Route: ", id); const fromCode = require_compilers.detectCodeSplitGroupingsFromRoute({ code }); if (fromCode.groupings) { const res = require_config.splitGroupingsSchema.safeParse(fromCode.groupings); if (!res.success) { const message = res.error.errors.map((e) => e.message).join(". "); throw new Error(`The groupings for the route "${id}" are invalid.\n${message}`); } } const pluginSplitBehavior = getShouldSplitFn()?.({ routeId: generatorNodeInfo.routePath }); if (pluginSplitBehavior) { const res = require_config.splitGroupingsSchema.safeParse(pluginSplitBehavior); if (!res.success) { const message = res.error.errors.map((e) => e.message).join(". "); throw new Error(`The groupings returned when using \`splitBehavior\` for the route "${id}" are invalid.\n${message}`); } } const splitGroupings = fromCode.groupings || pluginSplitBehavior || getGlobalCodeSplitGroupings(); const sharedBindings = require_compilers.computeSharedBindings({ code, codeSplitGroupings: splitGroupings }); if (sharedBindings.size > 0) sharedBindingsMap.set(id, sharedBindings); else sharedBindingsMap.delete(id); const addHmr = (userConfig.codeSplittingOptions?.addHmr ?? true) && !isProduction; const compiledReferenceRoute = require_compilers.compileCodeSplitReferenceRoute({ code, codeSplitGroupings: splitGroupings, targetFramework: userConfig.target, filename: id, id, deleteNodes: userConfig.codeSplittingOptions?.deleteNodes ? new Set(userConfig.codeSplittingOptions.deleteNodes) : void 0, addHmr, sharedBindings: sharedBindings.size > 0 ? sharedBindings : void 0, compilerPlugins: require_framework_plugins.getReferenceRouteCompilerPlugins({ targetFramework: userConfig.target, addHmr }) }); if (compiledReferenceRoute === null) { if (require_utils.debug) console.info(`No changes made to route "${id}", skipping code-splitting.`); return null; } if (require_utils.debug) { (0, _tanstack_router_utils.logDiff)(code, compiledReferenceRoute.code); console.log("Output:\n", compiledReferenceRoute.code + "\n\n"); } return compiledReferenceRoute; }; const handleCompilingVirtualFile = (code, id) => { if (require_utils.debug) console.info("Splitting Route: ", id); const [_, ...pathnameParts] = id.split("?"); const splitValue = new URLSearchParams(pathnameParts.join("?")).get(require_constants.tsrSplit); if (!splitValue) throw new Error(`The split value for the virtual route "${id}" was not found.`); const rawGrouping = require_path_ids.decodeIdentifier(splitValue); const grouping = [...new Set(rawGrouping)].filter((p) => require_constants.splitRouteIdentNodes.includes(p)); const baseId = id.split("?")[0]; const result = require_compilers.compileCodeSplitVirtualRoute({ code, filename: id, splitTargets: grouping, sharedBindings: sharedBindingsMap.get(baseId) }); if (require_utils.debug) { (0, _tanstack_router_utils.logDiff)(code, result.code); console.log("Output:\n", result.code + "\n\n"); } return result; }; const includedCode = [ "createFileRoute(", "createRootRoute(", "createRootRouteWithContext(" ]; return [ { name: "tanstack-router:code-splitter:compile-reference-file", enforce: "pre", transform: { filter: { id: { exclude: [require_constants.tsrSplit, require_constants.tsrShared], include: /\.(m|c)?(j|t)sx?$/ }, code: { include: includedCode } }, handler(code, id) { const normalizedId = require_utils.normalizePath(id); const generatorFileInfo = globalThis.TSR_ROUTES_BY_ID_MAP?.get(normalizedId); if (generatorFileInfo && includedCode.some((included) => code.includes(included))) return handleCompilingReferenceFile(code, normalizedId, generatorFileInfo); return null; } }, vite: { configResolved(config) { ROOT = config.root; initUserConfig(); const routerPluginIndex = config.plugins.findIndex((p) => p.name === CODE_SPLITTER_PLUGIN_NAME); if (routerPluginIndex === -1) return; const frameworkPlugins = TRANSFORMATION_PLUGINS_BY_FRAMEWORK[userConfig.target]; if (!frameworkPlugins) return; for (const transformPlugin of frameworkPlugins) { const transformPluginIndex = config.plugins.findIndex((p) => transformPlugin.pluginNames.includes(p.name)); if (transformPluginIndex !== -1 && transformPluginIndex < routerPluginIndex) throw new Error(`Plugin order error: '${transformPlugin.pkg}' is placed before '@tanstack/router-plugin'.\n\nThe TanStack Router plugin must come BEFORE JSX transformation plugins.\n\nPlease update your Vite config:\n\n plugins: [\n tanstackRouter(),\n ${transformPlugin.usage},\n ]\n`); } }, applyToEnvironment(environment) { if (userConfig.plugin?.vite?.environmentName) return userConfig.plugin.vite.environmentName === environment.name; return true; } }, rspack(compiler) { ROOT = process.cwd(); initUserConfig(); if (compiler.options.mode === "production") compiler.hooks.done.tap(PLUGIN_NAME, () => { console.info("✅ " + PLUGIN_NAME + ": code-splitting done!"); }); }, webpack(compiler) { ROOT = process.cwd(); initUserConfig(); if (compiler.options.mode === "production") compiler.hooks.done.tap(PLUGIN_NAME, () => { console.info("✅ " + PLUGIN_NAME + ": code-splitting done!"); }); } }, { name: "tanstack-router:code-splitter:compile-virtual-file", enforce: "pre", transform: { filter: { id: /tsr-split/ }, handler(code, id) { const url = (0, node_url.pathToFileURL)(id); url.searchParams.delete("v"); return handleCompilingVirtualFile(code, require_utils.normalizePath((0, node_url.fileURLToPath)(url))); } }, vite: { applyToEnvironment(environment) { if (userConfig.plugin?.vite?.environmentName) return userConfig.plugin.vite.environmentName === environment.name; return true; } } }, { name: "tanstack-router:code-splitter:compile-shared-file", enforce: "pre", transform: { filter: { id: /tsr-shared/ }, handler(code, id) { const url = (0, node_url.pathToFileURL)(id); url.searchParams.delete("v"); const normalizedId = require_utils.normalizePath((0, node_url.fileURLToPath)(url)); const [baseId] = normalizedId.split("?"); if (!baseId) return null; const sharedBindings = sharedBindingsMap.get(baseId); if (!sharedBindings || sharedBindings.size === 0) return null; if (require_utils.debug) console.info("Compiling Shared Module: ", id); const result = require_compilers.compileCodeSplitSharedRoute({ code, sharedBindings, filename: normalizedId }); if (require_utils.debug) { (0, _tanstack_router_utils.logDiff)(code, result.code); console.log("Output:\n", result.code + "\n\n"); } return result; } }, vite: { applyToEnvironment(environment) { if (userConfig.plugin?.vite?.environmentName) return userConfig.plugin.vite.environmentName === environment.name; return true; } } } ]; }; //#endregion exports.unpluginRouterCodeSplitterFactory = unpluginRouterCodeSplitterFactory; //# sourceMappingURL=router-code-splitter-plugin.cjs.map