@tanstack/router-vite-plugin 1.26.21 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -272,9 +272,9 @@ async function splitFile(opts) {
272
272
  ])
273
273
  );
274
274
  } else {
275
- console.log(splitNode);
275
+ console.info(splitNode);
276
276
  throw new Error(
277
- `Unexpected splitNode type: ${splitNode.type}`
277
+ `Unexpected splitNode type ☝️: ${splitNode.type}`
278
278
  );
279
279
  }
280
280
  }
@@ -1 +1 @@
1
- {"version":3,"file":"compilers.cjs","sources":["../../src/compilers.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport * as template from '@babel/template'\nimport * as babel from '@babel/core'\nimport { splitPrefix } from './constants'\nimport { eliminateUnreferencedIdentifiers } from './eliminateUnreferencedIdentifiers'\n\ntype SplitModulesById = Record<\n string,\n { id: string; node: t.FunctionExpression }\n>\n\ninterface State {\n filename: string\n opts: {\n minify: boolean\n root: string\n }\n imported: Record<string, boolean>\n refs: Set<any>\n serverIndex: number\n splitIndex: number\n splitModulesById: SplitModulesById\n}\n\nexport type CompileFn = (compileOpts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n}) => Promise<{\n code: string\n map: any\n}>\n\nexport function makeCompile(makeOpts: { root: string }) {\n return async (opts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n }): Promise<{\n code: string\n map: any\n }> => {\n const res = await babel.transform(opts.code, {\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [\n '@babel/plugin-syntax-typescript',\n {\n isTSX: true,\n },\n ],\n ...opts.getBabelConfig().plugins,\n ],\n root: makeOpts.root,\n filename: opts.filename,\n sourceMaps: true,\n })\n\n if (res?.code) {\n return {\n code: res.code,\n map: res.map,\n }\n }\n\n return {\n code: opts.code,\n map: null,\n }\n }\n}\n\nexport async function compileFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitUrl = `${splitPrefix}:${opts.filename}?${splitPrefix}`\n\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (\n path.node.callee.name === 'createRoute' ||\n path.node.callee.name === 'createFileRoute'\n ) {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n let found = false\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === 'component') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyRouteComponent } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitComponentImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyRouteComponent($$splitComponentImporter, 'component')`,\n )() as any\n\n programPath.pushContainer('body', [\n template.smart(\n `function DummyComponent() { return null }`,\n )() as t.Statement,\n ])\n\n found = true\n } else if (prop.key.name === 'loader') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyFn } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitLoaderImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyFn($$splitLoaderImporter, 'loader')`,\n )() as any\n\n found = true\n }\n }\n }\n })\n }\n\n if (found as boolean) {\n programPath.pushContainer('body', [\n template.smart(\n `function TSR_Dummy_Component() {}`,\n )() as t.Statement,\n ])\n }\n }\n }\n }\n },\n },\n state,\n )\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n\n// Reusable function to get literal value or resolve variable to literal\nfunction resolveIdentifier(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (\n binding\n // && binding.kind === 'const'\n ) {\n const declarator = binding.path.node\n if (t.isObjectExpression(declarator.init)) {\n return declarator.init\n } else if (t.isFunctionDeclaration(declarator.init)) {\n return declarator.init\n }\n }\n return undefined\n }\n\n return node\n}\n\nfunction removeIdentifierLiteral(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (binding) {\n binding.path.remove()\n }\n }\n}\n\nconst splitNodeTypes = ['component', 'loader'] as const\ntype SplitNodeType = (typeof splitNodeTypes)[number]\n\nexport async function splitFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n // ref: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitNodesByType: Record<\n SplitNodeType,\n t.Node | undefined\n > = {\n component: undefined,\n loader: undefined,\n }\n\n // Find the node\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (path.node.callee.name === 'createFileRoute') {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n splitNodeTypes.forEach((type) => {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === type) {\n splitNodesByType[type] = prop.value\n }\n }\n })\n }\n })\n\n // Remove all of the options\n options.properties = []\n }\n }\n }\n }\n },\n },\n state,\n )\n\n splitNodeTypes.forEach((splitType) => {\n let splitNode = splitNodesByType[splitType]\n\n if (!splitNode) {\n return\n }\n\n while (t.isIdentifier(splitNode)) {\n const binding = programPath.scope.getBinding(\n splitNode.name,\n )\n splitNode = binding?.path.node\n }\n\n // Add the node to the program\n if (splitNode) {\n if (t.isFunctionDeclaration(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n t.functionExpression(\n splitNode.id || null, // Anonymize the function expression\n splitNode.params,\n splitNode.body,\n splitNode.generator,\n splitNode.async,\n ),\n ),\n ]),\n )\n } else if (\n t.isFunctionExpression(splitNode) ||\n t.isArrowFunctionExpression(splitNode)\n ) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode as any,\n ),\n ]),\n )\n } else if (t.isImportSpecifier(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode.local,\n ),\n ]),\n )\n } else {\n console.log(splitNode)\n throw new Error(\n `Unexpected splitNode type: ${splitNode.type}`,\n )\n }\n }\n\n // If the splitNode exists at the top of the program\n // then we need to remove that copy\n programPath.node.body = programPath.node.body.filter(\n (node) => {\n // console.log(node)\n return node !== splitNode\n },\n )\n\n // Export the node\n programPath.pushContainer('body', [\n t.exportNamedDeclaration(null, [\n t.exportSpecifier(\n t.identifier(splitType),\n t.identifier(splitType),\n ),\n ]),\n ])\n })\n\n // convert exports to imports from the original file\n programPath.traverse({\n ExportNamedDeclaration(path) {\n // e.g. export const x = 1 or export { x }\n // becomes\n // import { x } from '${opts.id}'\n\n if (path.node.declaration) {\n if (t.isVariableDeclaration(path.node.declaration)) {\n path.replaceWith(\n t.importDeclaration(\n path.node.declaration.declarations.map((decl) =>\n t.importSpecifier(\n t.identifier((decl.id as any).name),\n t.identifier((decl.id as any).name),\n ),\n ),\n t.stringLiteral(\n opts.filename.split(\n `?${splitPrefix}`,\n )[0] as string,\n ),\n ),\n )\n }\n }\n },\n })\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n"],"names":["babel","splitPrefix","t","template","eliminateUnreferencedIdentifiers"],"mappings":"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"}
1
+ {"version":3,"file":"compilers.cjs","sources":["../../src/compilers.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport * as template from '@babel/template'\nimport * as babel from '@babel/core'\nimport { splitPrefix } from './constants'\nimport { eliminateUnreferencedIdentifiers } from './eliminateUnreferencedIdentifiers'\n\ntype SplitModulesById = Record<\n string,\n { id: string; node: t.FunctionExpression }\n>\n\ninterface State {\n filename: string\n opts: {\n minify: boolean\n root: string\n }\n imported: Record<string, boolean>\n refs: Set<any>\n serverIndex: number\n splitIndex: number\n splitModulesById: SplitModulesById\n}\n\nexport type CompileFn = (compileOpts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n}) => Promise<{\n code: string\n map: any\n}>\n\nexport function makeCompile(makeOpts: { root: string }) {\n return async (opts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n }): Promise<{\n code: string\n map: any\n }> => {\n const res = await babel.transform(opts.code, {\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [\n '@babel/plugin-syntax-typescript',\n {\n isTSX: true,\n },\n ],\n ...opts.getBabelConfig().plugins,\n ],\n root: makeOpts.root,\n filename: opts.filename,\n sourceMaps: true,\n })\n\n if (res?.code) {\n return {\n code: res.code,\n map: res.map,\n }\n }\n\n return {\n code: opts.code,\n map: null,\n }\n }\n}\n\nexport async function compileFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitUrl = `${splitPrefix}:${opts.filename}?${splitPrefix}`\n\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (\n path.node.callee.name === 'createRoute' ||\n path.node.callee.name === 'createFileRoute'\n ) {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n let found = false\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === 'component') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyRouteComponent } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitComponentImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyRouteComponent($$splitComponentImporter, 'component')`,\n )() as any\n\n programPath.pushContainer('body', [\n template.smart(\n `function DummyComponent() { return null }`,\n )() as t.Statement,\n ])\n\n found = true\n } else if (prop.key.name === 'loader') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyFn } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitLoaderImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyFn($$splitLoaderImporter, 'loader')`,\n )() as any\n\n found = true\n }\n }\n }\n })\n }\n\n if (found as boolean) {\n programPath.pushContainer('body', [\n template.smart(\n `function TSR_Dummy_Component() {}`,\n )() as t.Statement,\n ])\n }\n }\n }\n }\n },\n },\n state,\n )\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n\n// Reusable function to get literal value or resolve variable to literal\nfunction resolveIdentifier(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (\n binding\n // && binding.kind === 'const'\n ) {\n const declarator = binding.path.node\n if (t.isObjectExpression(declarator.init)) {\n return declarator.init\n } else if (t.isFunctionDeclaration(declarator.init)) {\n return declarator.init\n }\n }\n return undefined\n }\n\n return node\n}\n\nfunction removeIdentifierLiteral(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (binding) {\n binding.path.remove()\n }\n }\n}\n\nconst splitNodeTypes = ['component', 'loader'] as const\ntype SplitNodeType = (typeof splitNodeTypes)[number]\n\nexport async function splitFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n // ref: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitNodesByType: Record<\n SplitNodeType,\n t.Node | undefined\n > = {\n component: undefined,\n loader: undefined,\n }\n\n // Find the node\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (path.node.callee.name === 'createFileRoute') {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n splitNodeTypes.forEach((type) => {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === type) {\n splitNodesByType[type] = prop.value\n }\n }\n })\n }\n })\n\n // Remove all of the options\n options.properties = []\n }\n }\n }\n }\n },\n },\n state,\n )\n\n splitNodeTypes.forEach((splitType) => {\n let splitNode = splitNodesByType[splitType]\n\n if (!splitNode) {\n return\n }\n\n while (t.isIdentifier(splitNode)) {\n const binding = programPath.scope.getBinding(\n splitNode.name,\n )\n splitNode = binding?.path.node\n }\n\n // Add the node to the program\n if (splitNode) {\n if (t.isFunctionDeclaration(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n t.functionExpression(\n splitNode.id || null, // Anonymize the function expression\n splitNode.params,\n splitNode.body,\n splitNode.generator,\n splitNode.async,\n ),\n ),\n ]),\n )\n } else if (\n t.isFunctionExpression(splitNode) ||\n t.isArrowFunctionExpression(splitNode)\n ) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode as any,\n ),\n ]),\n )\n } else if (t.isImportSpecifier(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode.local,\n ),\n ]),\n )\n } else {\n console.info(splitNode)\n throw new Error(\n `Unexpected splitNode type ☝️: ${splitNode.type}`,\n )\n }\n }\n\n // If the splitNode exists at the top of the program\n // then we need to remove that copy\n programPath.node.body = programPath.node.body.filter(\n (node) => {\n return node !== splitNode\n },\n )\n\n // Export the node\n programPath.pushContainer('body', [\n t.exportNamedDeclaration(null, [\n t.exportSpecifier(\n t.identifier(splitType),\n t.identifier(splitType),\n ),\n ]),\n ])\n })\n\n // convert exports to imports from the original file\n programPath.traverse({\n ExportNamedDeclaration(path) {\n // e.g. export const x = 1 or export { x }\n // becomes\n // import { x } from '${opts.id}'\n\n if (path.node.declaration) {\n if (t.isVariableDeclaration(path.node.declaration)) {\n path.replaceWith(\n t.importDeclaration(\n path.node.declaration.declarations.map((decl) =>\n t.importSpecifier(\n t.identifier((decl.id as any).name),\n t.identifier((decl.id as any).name),\n ),\n ),\n t.stringLiteral(\n opts.filename.split(\n `?${splitPrefix}`,\n )[0] as string,\n ),\n ),\n )\n }\n }\n },\n })\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n"],"names":["babel","splitPrefix","t","template","eliminateUnreferencedIdentifiers"],"mappings":"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"}
@@ -11,6 +11,8 @@ export declare const configSchema: z.ZodObject<{
11
11
  disableTypes: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
12
12
  addExtensions: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
13
13
  disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
14
+ routeTreeFileHeader: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
15
+ routeTreeFileFooter: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
14
16
  enableRouteGeneration: z.ZodOptional<z.ZodBoolean>;
15
17
  experimental: z.ZodOptional<z.ZodObject<{
16
18
  enableCodeSplitting: z.ZodOptional<z.ZodBoolean>;
@@ -28,6 +30,8 @@ export declare const configSchema: z.ZodObject<{
28
30
  disableTypes: boolean;
29
31
  addExtensions: boolean;
30
32
  disableLogging: boolean;
33
+ routeTreeFileHeader: string[];
34
+ routeTreeFileFooter: string[];
31
35
  routeFilePrefix?: string | undefined;
32
36
  routeFileIgnorePattern?: string | undefined;
33
37
  enableRouteGeneration?: boolean | undefined;
@@ -45,6 +49,8 @@ export declare const configSchema: z.ZodObject<{
45
49
  disableTypes?: boolean | undefined;
46
50
  addExtensions?: boolean | undefined;
47
51
  disableLogging?: boolean | undefined;
52
+ routeTreeFileHeader?: string[] | undefined;
53
+ routeTreeFileFooter?: string[] | undefined;
48
54
  enableRouteGeneration?: boolean | undefined;
49
55
  experimental?: {
50
56
  enableCodeSplitting?: boolean | undefined;
@@ -251,9 +251,9 @@ async function splitFile(opts) {
251
251
  ])
252
252
  );
253
253
  } else {
254
- console.log(splitNode);
254
+ console.info(splitNode);
255
255
  throw new Error(
256
- `Unexpected splitNode type: ${splitNode.type}`
256
+ `Unexpected splitNode type ☝️: ${splitNode.type}`
257
257
  );
258
258
  }
259
259
  }
@@ -1 +1 @@
1
- {"version":3,"file":"compilers.js","sources":["../../src/compilers.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport * as template from '@babel/template'\nimport * as babel from '@babel/core'\nimport { splitPrefix } from './constants'\nimport { eliminateUnreferencedIdentifiers } from './eliminateUnreferencedIdentifiers'\n\ntype SplitModulesById = Record<\n string,\n { id: string; node: t.FunctionExpression }\n>\n\ninterface State {\n filename: string\n opts: {\n minify: boolean\n root: string\n }\n imported: Record<string, boolean>\n refs: Set<any>\n serverIndex: number\n splitIndex: number\n splitModulesById: SplitModulesById\n}\n\nexport type CompileFn = (compileOpts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n}) => Promise<{\n code: string\n map: any\n}>\n\nexport function makeCompile(makeOpts: { root: string }) {\n return async (opts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n }): Promise<{\n code: string\n map: any\n }> => {\n const res = await babel.transform(opts.code, {\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [\n '@babel/plugin-syntax-typescript',\n {\n isTSX: true,\n },\n ],\n ...opts.getBabelConfig().plugins,\n ],\n root: makeOpts.root,\n filename: opts.filename,\n sourceMaps: true,\n })\n\n if (res?.code) {\n return {\n code: res.code,\n map: res.map,\n }\n }\n\n return {\n code: opts.code,\n map: null,\n }\n }\n}\n\nexport async function compileFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitUrl = `${splitPrefix}:${opts.filename}?${splitPrefix}`\n\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (\n path.node.callee.name === 'createRoute' ||\n path.node.callee.name === 'createFileRoute'\n ) {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n let found = false\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === 'component') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyRouteComponent } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitComponentImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyRouteComponent($$splitComponentImporter, 'component')`,\n )() as any\n\n programPath.pushContainer('body', [\n template.smart(\n `function DummyComponent() { return null }`,\n )() as t.Statement,\n ])\n\n found = true\n } else if (prop.key.name === 'loader') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyFn } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitLoaderImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyFn($$splitLoaderImporter, 'loader')`,\n )() as any\n\n found = true\n }\n }\n }\n })\n }\n\n if (found as boolean) {\n programPath.pushContainer('body', [\n template.smart(\n `function TSR_Dummy_Component() {}`,\n )() as t.Statement,\n ])\n }\n }\n }\n }\n },\n },\n state,\n )\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n\n// Reusable function to get literal value or resolve variable to literal\nfunction resolveIdentifier(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (\n binding\n // && binding.kind === 'const'\n ) {\n const declarator = binding.path.node\n if (t.isObjectExpression(declarator.init)) {\n return declarator.init\n } else if (t.isFunctionDeclaration(declarator.init)) {\n return declarator.init\n }\n }\n return undefined\n }\n\n return node\n}\n\nfunction removeIdentifierLiteral(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (binding) {\n binding.path.remove()\n }\n }\n}\n\nconst splitNodeTypes = ['component', 'loader'] as const\ntype SplitNodeType = (typeof splitNodeTypes)[number]\n\nexport async function splitFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n // ref: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitNodesByType: Record<\n SplitNodeType,\n t.Node | undefined\n > = {\n component: undefined,\n loader: undefined,\n }\n\n // Find the node\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (path.node.callee.name === 'createFileRoute') {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n splitNodeTypes.forEach((type) => {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === type) {\n splitNodesByType[type] = prop.value\n }\n }\n })\n }\n })\n\n // Remove all of the options\n options.properties = []\n }\n }\n }\n }\n },\n },\n state,\n )\n\n splitNodeTypes.forEach((splitType) => {\n let splitNode = splitNodesByType[splitType]\n\n if (!splitNode) {\n return\n }\n\n while (t.isIdentifier(splitNode)) {\n const binding = programPath.scope.getBinding(\n splitNode.name,\n )\n splitNode = binding?.path.node\n }\n\n // Add the node to the program\n if (splitNode) {\n if (t.isFunctionDeclaration(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n t.functionExpression(\n splitNode.id || null, // Anonymize the function expression\n splitNode.params,\n splitNode.body,\n splitNode.generator,\n splitNode.async,\n ),\n ),\n ]),\n )\n } else if (\n t.isFunctionExpression(splitNode) ||\n t.isArrowFunctionExpression(splitNode)\n ) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode as any,\n ),\n ]),\n )\n } else if (t.isImportSpecifier(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode.local,\n ),\n ]),\n )\n } else {\n console.log(splitNode)\n throw new Error(\n `Unexpected splitNode type: ${splitNode.type}`,\n )\n }\n }\n\n // If the splitNode exists at the top of the program\n // then we need to remove that copy\n programPath.node.body = programPath.node.body.filter(\n (node) => {\n // console.log(node)\n return node !== splitNode\n },\n )\n\n // Export the node\n programPath.pushContainer('body', [\n t.exportNamedDeclaration(null, [\n t.exportSpecifier(\n t.identifier(splitType),\n t.identifier(splitType),\n ),\n ]),\n ])\n })\n\n // convert exports to imports from the original file\n programPath.traverse({\n ExportNamedDeclaration(path) {\n // e.g. export const x = 1 or export { x }\n // becomes\n // import { x } from '${opts.id}'\n\n if (path.node.declaration) {\n if (t.isVariableDeclaration(path.node.declaration)) {\n path.replaceWith(\n t.importDeclaration(\n path.node.declaration.declarations.map((decl) =>\n t.importSpecifier(\n t.identifier((decl.id as any).name),\n t.identifier((decl.id as any).name),\n ),\n ),\n t.stringLiteral(\n opts.filename.split(\n `?${splitPrefix}`,\n )[0] as string,\n ),\n ),\n )\n }\n }\n },\n })\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compilers.js","sources":["../../src/compilers.ts"],"sourcesContent":["import * as t from '@babel/types'\nimport * as template from '@babel/template'\nimport * as babel from '@babel/core'\nimport { splitPrefix } from './constants'\nimport { eliminateUnreferencedIdentifiers } from './eliminateUnreferencedIdentifiers'\n\ntype SplitModulesById = Record<\n string,\n { id: string; node: t.FunctionExpression }\n>\n\ninterface State {\n filename: string\n opts: {\n minify: boolean\n root: string\n }\n imported: Record<string, boolean>\n refs: Set<any>\n serverIndex: number\n splitIndex: number\n splitModulesById: SplitModulesById\n}\n\nexport type CompileFn = (compileOpts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n}) => Promise<{\n code: string\n map: any\n}>\n\nexport function makeCompile(makeOpts: { root: string }) {\n return async (opts: {\n code: string\n filename: string\n getBabelConfig: () => { plugins: Array<any> }\n }): Promise<{\n code: string\n map: any\n }> => {\n const res = await babel.transform(opts.code, {\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [\n '@babel/plugin-syntax-typescript',\n {\n isTSX: true,\n },\n ],\n ...opts.getBabelConfig().plugins,\n ],\n root: makeOpts.root,\n filename: opts.filename,\n sourceMaps: true,\n })\n\n if (res?.code) {\n return {\n code: res.code,\n map: res.map,\n }\n }\n\n return {\n code: opts.code,\n map: null,\n }\n }\n}\n\nexport async function compileFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitUrl = `${splitPrefix}:${opts.filename}?${splitPrefix}`\n\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (\n path.node.callee.name === 'createRoute' ||\n path.node.callee.name === 'createFileRoute'\n ) {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n let found = false\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === 'component') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyRouteComponent } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitComponentImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyRouteComponent($$splitComponentImporter, 'component')`,\n )() as any\n\n programPath.pushContainer('body', [\n template.smart(\n `function DummyComponent() { return null }`,\n )() as t.Statement,\n ])\n\n found = true\n } else if (prop.key.name === 'loader') {\n const value = prop.value\n\n if (t.isIdentifier(value)) {\n removeIdentifierLiteral(path, value)\n }\n\n // Prepend the import statement to the program along with the importer function\n\n programPath.unshiftContainer('body', [\n template.smart(\n `import { lazyFn } from '@tanstack/react-router'`,\n )() as t.Statement,\n template.smart(\n `const $$splitLoaderImporter = () => import('${splitUrl}')`,\n )() as t.Statement,\n ])\n\n prop.value = template.expression(\n `lazyFn($$splitLoaderImporter, 'loader')`,\n )() as any\n\n found = true\n }\n }\n }\n })\n }\n\n if (found as boolean) {\n programPath.pushContainer('body', [\n template.smart(\n `function TSR_Dummy_Component() {}`,\n )() as t.Statement,\n ])\n }\n }\n }\n }\n },\n },\n state,\n )\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n\n// Reusable function to get literal value or resolve variable to literal\nfunction resolveIdentifier(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (\n binding\n // && binding.kind === 'const'\n ) {\n const declarator = binding.path.node\n if (t.isObjectExpression(declarator.init)) {\n return declarator.init\n } else if (t.isFunctionDeclaration(declarator.init)) {\n return declarator.init\n }\n }\n return undefined\n }\n\n return node\n}\n\nfunction removeIdentifierLiteral(path: any, node: any) {\n if (t.isIdentifier(node)) {\n const binding = path.scope.getBinding(node.name)\n if (binding) {\n binding.path.remove()\n }\n }\n}\n\nconst splitNodeTypes = ['component', 'loader'] as const\ntype SplitNodeType = (typeof splitNodeTypes)[number]\n\nexport async function splitFile(opts: {\n code: string\n compile: CompileFn\n filename: string\n // ref: string\n}) {\n return await opts.compile({\n code: opts.code,\n filename: opts.filename,\n getBabelConfig: () => ({\n plugins: [\n [\n {\n visitor: {\n Program: {\n enter(programPath: babel.NodePath<t.Program>, state: State) {\n const splitNodesByType: Record<\n SplitNodeType,\n t.Node | undefined\n > = {\n component: undefined,\n loader: undefined,\n }\n\n // Find the node\n programPath.traverse(\n {\n CallExpression: (path) => {\n if (path.node.callee.type === 'Identifier') {\n if (path.node.callee.name === 'createFileRoute') {\n if (\n path.parentPath.node.type === 'CallExpression'\n ) {\n const options = resolveIdentifier(\n path,\n path.parentPath.node.arguments[0],\n )\n\n if (t.isObjectExpression(options)) {\n options.properties.forEach((prop) => {\n if (t.isObjectProperty(prop)) {\n splitNodeTypes.forEach((type) => {\n if (t.isIdentifier(prop.key)) {\n if (prop.key.name === type) {\n splitNodesByType[type] = prop.value\n }\n }\n })\n }\n })\n\n // Remove all of the options\n options.properties = []\n }\n }\n }\n }\n },\n },\n state,\n )\n\n splitNodeTypes.forEach((splitType) => {\n let splitNode = splitNodesByType[splitType]\n\n if (!splitNode) {\n return\n }\n\n while (t.isIdentifier(splitNode)) {\n const binding = programPath.scope.getBinding(\n splitNode.name,\n )\n splitNode = binding?.path.node\n }\n\n // Add the node to the program\n if (splitNode) {\n if (t.isFunctionDeclaration(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n t.functionExpression(\n splitNode.id || null, // Anonymize the function expression\n splitNode.params,\n splitNode.body,\n splitNode.generator,\n splitNode.async,\n ),\n ),\n ]),\n )\n } else if (\n t.isFunctionExpression(splitNode) ||\n t.isArrowFunctionExpression(splitNode)\n ) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode as any,\n ),\n ]),\n )\n } else if (t.isImportSpecifier(splitNode)) {\n programPath.pushContainer(\n 'body',\n t.variableDeclaration('const', [\n t.variableDeclarator(\n t.identifier(splitType),\n splitNode.local,\n ),\n ]),\n )\n } else {\n console.info(splitNode)\n throw new Error(\n `Unexpected splitNode type ☝️: ${splitNode.type}`,\n )\n }\n }\n\n // If the splitNode exists at the top of the program\n // then we need to remove that copy\n programPath.node.body = programPath.node.body.filter(\n (node) => {\n return node !== splitNode\n },\n )\n\n // Export the node\n programPath.pushContainer('body', [\n t.exportNamedDeclaration(null, [\n t.exportSpecifier(\n t.identifier(splitType),\n t.identifier(splitType),\n ),\n ]),\n ])\n })\n\n // convert exports to imports from the original file\n programPath.traverse({\n ExportNamedDeclaration(path) {\n // e.g. export const x = 1 or export { x }\n // becomes\n // import { x } from '${opts.id}'\n\n if (path.node.declaration) {\n if (t.isVariableDeclaration(path.node.declaration)) {\n path.replaceWith(\n t.importDeclaration(\n path.node.declaration.declarations.map((decl) =>\n t.importSpecifier(\n t.identifier((decl.id as any).name),\n t.identifier((decl.id as any).name),\n ),\n ),\n t.stringLiteral(\n opts.filename.split(\n `?${splitPrefix}`,\n )[0] as string,\n ),\n ),\n )\n }\n }\n },\n })\n\n eliminateUnreferencedIdentifiers(programPath)\n },\n },\n },\n },\n {\n root: process.cwd(),\n minify: process.env.NODE_ENV === 'production',\n },\n ],\n ].filter(Boolean),\n }),\n })\n}\n"],"names":[],"mappings":"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"}
@@ -11,6 +11,8 @@ export declare const configSchema: z.ZodObject<{
11
11
  disableTypes: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
12
12
  addExtensions: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
13
13
  disableLogging: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
14
+ routeTreeFileHeader: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
15
+ routeTreeFileFooter: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
14
16
  enableRouteGeneration: z.ZodOptional<z.ZodBoolean>;
15
17
  experimental: z.ZodOptional<z.ZodObject<{
16
18
  enableCodeSplitting: z.ZodOptional<z.ZodBoolean>;
@@ -28,6 +30,8 @@ export declare const configSchema: z.ZodObject<{
28
30
  disableTypes: boolean;
29
31
  addExtensions: boolean;
30
32
  disableLogging: boolean;
33
+ routeTreeFileHeader: string[];
34
+ routeTreeFileFooter: string[];
31
35
  routeFilePrefix?: string | undefined;
32
36
  routeFileIgnorePattern?: string | undefined;
33
37
  enableRouteGeneration?: boolean | undefined;
@@ -45,6 +49,8 @@ export declare const configSchema: z.ZodObject<{
45
49
  disableTypes?: boolean | undefined;
46
50
  addExtensions?: boolean | undefined;
47
51
  disableLogging?: boolean | undefined;
52
+ routeTreeFileHeader?: string[] | undefined;
53
+ routeTreeFileFooter?: string[] | undefined;
48
54
  enableRouteGeneration?: boolean | undefined;
49
55
  experimental?: {
50
56
  enableCodeSplitting?: boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/router-vite-plugin",
3
- "version": "1.26.21",
3
+ "version": "1.30.0",
4
4
  "description": "",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -64,12 +64,12 @@
64
64
  "@types/babel__traverse": "^7.20.5",
65
65
  "@vitejs/plugin-react": "^4.2.1",
66
66
  "zod": "^3.22.4",
67
- "@tanstack/router-generator": "1.26.16"
67
+ "@tanstack/router-generator": "1.30.0"
68
68
  },
69
69
  "scripts": {
70
70
  "clean": "rimraf ./dist && rimraf ./coverage",
71
71
  "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit",
72
- "test:unit": "vitest",
72
+ "test:unit": "vitest --typecheck --watch=false",
73
73
  "test:eslint": "eslint --ext .ts,.tsx ./src",
74
74
  "test:types": "tsc --noEmit",
75
75
  "test:build": "publint --strict",
package/src/compilers.ts CHANGED
@@ -348,9 +348,9 @@ export async function splitFile(opts: {
348
348
  ]),
349
349
  )
350
350
  } else {
351
- console.log(splitNode)
351
+ console.info(splitNode)
352
352
  throw new Error(
353
- `Unexpected splitNode type: ${splitNode.type}`,
353
+ `Unexpected splitNode type ☝️: ${splitNode.type}`,
354
354
  )
355
355
  }
356
356
  }
@@ -359,7 +359,6 @@ export async function splitFile(opts: {
359
359
  // then we need to remove that copy
360
360
  programPath.node.body = programPath.node.body.filter(
361
361
  (node) => {
362
- // console.log(node)
363
362
  return node !== splitNode
364
363
  },
365
364
  )