From 22ba755b2a7d5e65c2ea14f9a64e4e0b315786a3 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Wed, 11 Dec 2024 23:55:26 -0700 Subject: [PATCH] fix: improve babel parsing/generation reliability * fix: attempt fix DCE * fix: clean up babel parsing and generation, upgrade deps, adding debug * fix: remove unnecessary test --- packages/router-plugin/package.json | 14 +++--- .../src/core/code-splitter/ast.ts | 39 +++-------------- .../src/core/code-splitter/compilers.ts | 43 +++++++++++++------ .../src/core/router-code-splitter-plugin.ts | 12 +++++- packages/start-vite-plugin/package.json | 12 +++--- packages/start-vite-plugin/src/ast.ts | 40 ++++------------- packages/start-vite-plugin/src/compilers.ts | 12 ------ packages/start-vite-plugin/src/index.ts | 12 +++++- 8 files changed, 80 insertions(+), 104 deletions(-) diff --git a/packages/router-plugin/package.json b/packages/router-plugin/package.json index b015a3bcd1..c03abee478 100644 --- a/packages/router-plugin/package.json +++ b/packages/router-plugin/package.json @@ -103,14 +103,8 @@ "node": ">=12" }, "dependencies": { - "@babel/core": "^7.26.0", - "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.25.9", - "@babel/traverse": "^7.26.4", - "@babel/types": "^7.26.3", "@tanstack/router-generator": "workspace:^", "@tanstack/virtual-file-routes": "workspace:^", "@types/babel__core": "^7.20.5", @@ -120,7 +114,13 @@ "babel-dead-code-elimination": "^1.0.6", "chokidar": "^3.6.0", "unplugin": "^1.16.0", - "zod": "^3.23.8" + "zod": "^3.23.8", + "@babel/generator": "^7.26.3", + "@babel/core": "^7.26.0", + "@babel/parser": "^7.26.3", + "@babel/plugin-syntax-typescript": "^7.25.9", + "@babel/traverse": "^7.26.4", + "@babel/types": "^7.26.3" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", diff --git a/packages/router-plugin/src/core/code-splitter/ast.ts b/packages/router-plugin/src/core/code-splitter/ast.ts index 89db33ebe3..7cb14cb239 100644 --- a/packages/router-plugin/src/core/code-splitter/ast.ts +++ b/packages/router-plugin/src/core/code-splitter/ast.ts @@ -1,20 +1,4 @@ -import * as babel from '@babel/core' -import '@babel/parser' -// @ts-expect-error -import _babelPluginJsx from '@babel/plugin-syntax-jsx' -// @ts-expect-error -import _babelPluginTypeScript from '@babel/plugin-syntax-typescript' - -let babelPluginJsx = _babelPluginJsx -let babelPluginTypeScript = _babelPluginTypeScript - -if (babelPluginJsx.default) { - babelPluginJsx = babelPluginJsx.default -} - -if (babelPluginTypeScript.default) { - babelPluginTypeScript = babelPluginTypeScript.default -} +import { parse } from '@babel/parser' export type ParseAstOptions = { code: string @@ -23,21 +7,12 @@ export type ParseAstOptions = { } export function parseAst(opts: ParseAstOptions) { - const babelPlugins: Array = [ - babelPluginJsx, - [ - babelPluginTypeScript, - { - isTSX: true, - }, - ], - ] - - return babel.parse(opts.code, { - plugins: babelPlugins, - root: opts.root, - filename: opts.filename, - sourceMaps: true, + return parse(opts.code, { + plugins: ['jsx', 'typescript'], sourceType: 'module', + ...{ + root: opts.root, + filename: opts.filename, + }, }) } diff --git a/packages/router-plugin/src/core/code-splitter/compilers.ts b/packages/router-plugin/src/core/code-splitter/compilers.ts index a320a8114e..bdc59e48c1 100644 --- a/packages/router-plugin/src/core/code-splitter/compilers.ts +++ b/packages/router-plugin/src/core/code-splitter/compilers.ts @@ -8,6 +8,8 @@ import { splitPrefix } from '../constants' import { parseAst } from './ast' import type { ParseAstOptions } from './ast' +const debug = process.env.TSR_VITE_DEBUG + // Babel is a CJS package and uses `default` as named binding (`exports.default =`). // https://github.com/babel/babel/issues/15269. let generate = (_generate as any)['default'] as typeof _generate @@ -38,12 +40,6 @@ interface State { export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) { const ast = parseAst(opts) - if (!ast) { - throw new Error( - `Failed to compile ast for compileCodeSplitReferenceRoute() for the file: ${opts.filename}`, - ) - } - babel.traverse(ast, { Program: { enter(programPath, programState) { @@ -255,8 +251,22 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) { }, }) + if (debug) console.info('') + if (debug) console.info('Dead Code Elimination Input 1:') + if (debug) console.info(generate(ast, { sourceMaps: true }).code) + if (debug) console.info('') + if (debug) console.info('') + if (debug) console.info('') + deadCodeElimination(ast) + if (debug) console.info('') + if (debug) console.info('Dead Code Elimination Output 1:') + if (debug) console.info(generate(ast, { sourceMaps: true }).code) + if (debug) console.info('') + if (debug) console.info('') + if (debug) console.info('') + return generate(ast, { sourceMaps: true, }) @@ -268,12 +278,6 @@ type SplitNodeType = (typeof splitNodeTypes)[number] export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) { const ast = parseAst(opts) - if (!ast) { - throw new Error( - `Failed to compile ast for compileCodeSplitVirtualRoute() for the file: ${opts.filename}`, - ) - } - const knownExportedIdents = new Set() babel.traverse(ast, { @@ -497,8 +501,23 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) { }, }) + if (debug) console.info('') + if (debug) console.info('Dead Code Elimination Input 2:') + console.log(JSON.stringify(ast, null, 2)) + if (debug) console.info(generate(ast, { sourceMaps: true }).code) + if (debug) console.info('') + if (debug) console.info('') + if (debug) console.info('') + deadCodeElimination(ast) + if (debug) console.info('') + if (debug) console.info('Dead Code Elimination Output 2:') + if (debug) console.info(generate(ast, { sourceMaps: true }).code) + if (debug) console.info('') + if (debug) console.info('') + if (debug) console.info('') + // if there are exported identifiers, then we need to add a warning // to the file to let the user know that the exported identifiers // will not in the split file but in the original file, therefore diff --git a/packages/router-plugin/src/core/router-code-splitter-plugin.ts b/packages/router-plugin/src/core/router-code-splitter-plugin.ts index c9de306416..1437cb2e7c 100644 --- a/packages/router-plugin/src/core/router-code-splitter-plugin.ts +++ b/packages/router-plugin/src/core/router-code-splitter-plugin.ts @@ -70,6 +70,14 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory< const handleSplittingFile = (code: string, id: string) => { if (debug) console.info('Splitting route: ', id) + if (debug) console.info('') + if (debug) console.info('Split Route Input: ', id) + if (debug) console.info('') + if (debug) console.info(code) + if (debug) console.info('') + if (debug) console.info('') + if (debug) console.info('') + const compiledVirtualRoute = compileCodeSplitVirtualRoute({ code, root: ROOT, @@ -77,7 +85,7 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory< }) if (debug) console.info('') - if (debug) console.info('Split Output') + if (debug) console.info('Split Route Output: ', id) if (debug) console.info('') if (debug) console.info(compiledVirtualRoute.code) if (debug) console.info('') @@ -97,7 +105,7 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory< }) if (debug) console.info('') - if (debug) console.info('Compiled Output') + if (debug) console.info('Handling createRoute output: ', id) if (debug) console.info('') if (debug) console.info(compiledReferenceRoute.code) if (debug) console.info('') diff --git a/packages/start-vite-plugin/package.json b/packages/start-vite-plugin/package.json index d8514f8dc1..4195a289cf 100644 --- a/packages/start-vite-plugin/package.json +++ b/packages/start-vite-plugin/package.json @@ -64,21 +64,21 @@ "node": ">=12" }, "dependencies": { - "@babel/core": "^7.26.0", "@babel/code-frame": "7.26.2", "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.25.9", - "@babel/traverse": "^7.26.4", - "@babel/types": "^7.26.3", "@types/babel__core": "^7.20.5", "@types/babel__generator": "^7.6.8", "@types/babel__code-frame": "^7.0.6", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6", "tiny-invariant": "^1.3.3", - "babel-dead-code-elimination": "^1.0.6" + "babel-dead-code-elimination": "^1.0.6", + "@babel/core": "^7.26.0", + "@babel/parser": "^7.26.3", + "@babel/plugin-syntax-typescript": "^7.25.9", + "@babel/traverse": "^7.26.4", + "@babel/types": "^7.26.3" } } diff --git a/packages/start-vite-plugin/src/ast.ts b/packages/start-vite-plugin/src/ast.ts index 6062993cfd..4f1cb2f04e 100644 --- a/packages/start-vite-plugin/src/ast.ts +++ b/packages/start-vite-plugin/src/ast.ts @@ -1,20 +1,4 @@ -import * as babel from '@babel/core' -import '@babel/parser' -// @ts-expect-error -import _babelPluginJsx from '@babel/plugin-syntax-jsx' -// @ts-expect-error -import _babelPluginTypeScript from '@babel/plugin-syntax-typescript' - -let babelPluginJsx = _babelPluginJsx -let babelPluginTypeScript = _babelPluginTypeScript - -if (babelPluginJsx.default) { - babelPluginJsx = babelPluginJsx.default -} - -if (babelPluginTypeScript.default) { - babelPluginTypeScript = babelPluginTypeScript.default -} +import { parse } from '@babel/parser' export type ParseAstOptions = { code: string @@ -24,21 +8,13 @@ export type ParseAstOptions = { } export function parseAst(opts: ParseAstOptions) { - const babelPlugins: Array = [ - babelPluginJsx, - [ - babelPluginTypeScript, - { - isTSX: true, - }, - ], - ] - - return babel.parse(opts.code, { - plugins: babelPlugins, - root: opts.root, - filename: opts.filename, - sourceMaps: true, + return parse(opts.code, { + plugins: ['jsx', 'typescript'], sourceType: 'module', + ...{ + root: opts.root, + filename: opts.filename, + env: opts.env, + }, }) } diff --git a/packages/start-vite-plugin/src/compilers.ts b/packages/start-vite-plugin/src/compilers.ts index a5d8c49b11..f5e6dfd3c9 100644 --- a/packages/start-vite-plugin/src/compilers.ts +++ b/packages/start-vite-plugin/src/compilers.ts @@ -18,13 +18,7 @@ if (!generate) { export function compileEliminateDeadCode(opts: ParseAstOptions) { const ast = parseAst(opts) - if (!ast) { - throw new Error( - `Failed to compile ast for compileEliminateDeadCode() for the file: ${opts.filename}`, - ) - } deadCodeElimination(ast) - return generate(ast, { sourceMaps: true, }) @@ -52,12 +46,6 @@ type IdentifierConfig = { export function compileStartOutput(opts: ParseAstOptions) { const ast = parseAst(opts) - if (!ast) { - throw new Error( - `Failed to compile ast for compileStartOutput() for the file: ${opts.filename}`, - ) - } - babel.traverse(ast, { Program: { enter(programPath) { diff --git a/packages/start-vite-plugin/src/index.ts b/packages/start-vite-plugin/src/index.ts index 20b377d249..bd40710f2a 100644 --- a/packages/start-vite-plugin/src/index.ts +++ b/packages/start-vite-plugin/src/index.ts @@ -99,6 +99,16 @@ export function TanStackStartViteDeadCodeElimination( id = fileURLToPath(url).replace(/\\/g, '/') if (transformFuncs.some((fn) => code.includes(fn))) { + if (debug) console.info('Handling dead code elimination: ', id) + + if (debug) console.info('') + if (debug) console.info('Dead Code Elimination Input:') + if (debug) console.info('') + if (debug) console.info(code) + if (debug) console.info('') + if (debug) console.info('') + if (debug) console.info('') + const compiled = compileEliminateDeadCode({ code, root: ROOT, @@ -107,7 +117,7 @@ export function TanStackStartViteDeadCodeElimination( }) if (debug) console.info('') - if (debug) console.info('Output after dead code elimination') + if (debug) console.info('Dead Code Elimination Output:') if (debug) console.info('') if (debug) console.info(compiled.code) if (debug) console.info('')