@tanstack/router-plugin 1.166.10 → 1.166.12

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.
Files changed (80) hide show
  1. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  2. package/dist/cjs/core/code-splitter/compilers.cjs +866 -1324
  3. package/dist/cjs/core/code-splitter/compilers.cjs.map +1 -1
  4. package/dist/cjs/core/code-splitter/framework-options.cjs +39 -41
  5. package/dist/cjs/core/code-splitter/framework-options.cjs.map +1 -1
  6. package/dist/cjs/core/code-splitter/path-ids.cjs +26 -31
  7. package/dist/cjs/core/code-splitter/path-ids.cjs.map +1 -1
  8. package/dist/cjs/core/code-splitter/plugins/framework-plugins.cjs +11 -14
  9. package/dist/cjs/core/code-splitter/plugins/framework-plugins.cjs.map +1 -1
  10. package/dist/cjs/core/code-splitter/plugins/react-refresh-route-components.cjs +31 -65
  11. package/dist/cjs/core/code-splitter/plugins/react-refresh-route-components.cjs.map +1 -1
  12. package/dist/cjs/core/config.cjs +36 -46
  13. package/dist/cjs/core/config.cjs.map +1 -1
  14. package/dist/cjs/core/constants.cjs +16 -15
  15. package/dist/cjs/core/constants.cjs.map +1 -1
  16. package/dist/cjs/core/route-autoimport-plugin.cjs +81 -115
  17. package/dist/cjs/core/route-autoimport-plugin.cjs.map +1 -1
  18. package/dist/cjs/core/route-hmr-statement.cjs +34 -56
  19. package/dist/cjs/core/route-hmr-statement.cjs.map +1 -1
  20. package/dist/cjs/core/router-code-splitter-plugin.cjs +236 -306
  21. package/dist/cjs/core/router-code-splitter-plugin.cjs.map +1 -1
  22. package/dist/cjs/core/router-composed-plugin.cjs +28 -34
  23. package/dist/cjs/core/router-composed-plugin.cjs.map +1 -1
  24. package/dist/cjs/core/router-generator-plugin.cjs +101 -133
  25. package/dist/cjs/core/router-generator-plugin.cjs.map +1 -1
  26. package/dist/cjs/core/router-hmr-plugin.cjs +81 -81
  27. package/dist/cjs/core/router-hmr-plugin.cjs.map +1 -1
  28. package/dist/cjs/core/utils.cjs +23 -30
  29. package/dist/cjs/core/utils.cjs.map +1 -1
  30. package/dist/cjs/esbuild.cjs +47 -18
  31. package/dist/cjs/esbuild.cjs.map +1 -1
  32. package/dist/cjs/index.cjs +11 -13
  33. package/dist/cjs/rspack.cjs +58 -19
  34. package/dist/cjs/rspack.cjs.map +1 -1
  35. package/dist/cjs/vite.cjs +52 -20
  36. package/dist/cjs/vite.cjs.map +1 -1
  37. package/dist/cjs/webpack.cjs +46 -19
  38. package/dist/cjs/webpack.cjs.map +1 -1
  39. package/dist/esm/core/code-splitter/compilers.js +859 -1307
  40. package/dist/esm/core/code-splitter/compilers.js.map +1 -1
  41. package/dist/esm/core/code-splitter/framework-options.js +40 -42
  42. package/dist/esm/core/code-splitter/framework-options.js.map +1 -1
  43. package/dist/esm/core/code-splitter/path-ids.js +27 -33
  44. package/dist/esm/core/code-splitter/path-ids.js.map +1 -1
  45. package/dist/esm/core/code-splitter/plugins/framework-plugins.js +11 -14
  46. package/dist/esm/core/code-splitter/plugins/framework-plugins.js.map +1 -1
  47. package/dist/esm/core/code-splitter/plugins/react-refresh-route-components.js +29 -48
  48. package/dist/esm/core/code-splitter/plugins/react-refresh-route-components.js.map +1 -1
  49. package/dist/esm/core/config.js +35 -48
  50. package/dist/esm/core/config.js.map +1 -1
  51. package/dist/esm/core/constants.js +17 -19
  52. package/dist/esm/core/constants.js.map +1 -1
  53. package/dist/esm/core/route-autoimport-plugin.js +78 -98
  54. package/dist/esm/core/route-autoimport-plugin.js.map +1 -1
  55. package/dist/esm/core/route-hmr-statement.js +32 -39
  56. package/dist/esm/core/route-hmr-statement.js.map +1 -1
  57. package/dist/esm/core/router-code-splitter-plugin.js +234 -305
  58. package/dist/esm/core/router-code-splitter-plugin.js.map +1 -1
  59. package/dist/esm/core/router-composed-plugin.js +25 -32
  60. package/dist/esm/core/router-composed-plugin.js.map +1 -1
  61. package/dist/esm/core/router-generator-plugin.js +100 -111
  62. package/dist/esm/core/router-generator-plugin.js.map +1 -1
  63. package/dist/esm/core/router-hmr-plugin.js +79 -80
  64. package/dist/esm/core/router-hmr-plugin.js.map +1 -1
  65. package/dist/esm/core/utils.js +21 -15
  66. package/dist/esm/core/utils.js.map +1 -1
  67. package/dist/esm/esbuild.js +37 -18
  68. package/dist/esm/esbuild.js.map +1 -1
  69. package/dist/esm/index.js +2 -11
  70. package/dist/esm/rspack.js +49 -20
  71. package/dist/esm/rspack.js.map +1 -1
  72. package/dist/esm/vite.js +42 -21
  73. package/dist/esm/vite.js.map +1 -1
  74. package/dist/esm/webpack.js +37 -20
  75. package/dist/esm/webpack.js.map +1 -1
  76. package/package.json +6 -6
  77. package/src/core/code-splitter/compilers.ts +1 -1
  78. package/src/core/route-autoimport-plugin.ts +1 -1
  79. package/dist/cjs/index.cjs.map +0 -1
  80. package/dist/esm/index.js.map +0 -1
@@ -1,1364 +1,916 @@
1
- import * as t from "@babel/types";
2
- import babel from "@babel/core";
3
- import * as template from "@babel/template";
4
- import { parseAst, findReferencedIdentifiers, deadCodeElimination, generateFromAst } from "@tanstack/router-utils";
5
1
  import { tsrShared, tsrSplit } from "../constants.js";
6
2
  import { routeHmrStatement } from "../route-hmr-statement.js";
7
3
  import { createIdentifier } from "./path-ids.js";
8
4
  import { getFrameworkOptions } from "./framework-options.js";
9
- const SPLIT_NODES_CONFIG = /* @__PURE__ */ new Map([
10
- [
11
- "loader",
12
- {
13
- routeIdent: "loader",
14
- localImporterIdent: "$$splitLoaderImporter",
15
- // const $$splitLoaderImporter = () => import('...')
16
- splitStrategy: "lazyFn",
17
- localExporterIdent: "SplitLoader",
18
- // const SplitLoader = ...
19
- exporterIdent: "loader"
20
- // export { SplitLoader as loader }
21
- }
22
- ],
23
- [
24
- "component",
25
- {
26
- routeIdent: "component",
27
- localImporterIdent: "$$splitComponentImporter",
28
- // const $$splitComponentImporter = () => import('...')
29
- splitStrategy: "lazyRouteComponent",
30
- localExporterIdent: "SplitComponent",
31
- // const SplitComponent = ...
32
- exporterIdent: "component"
33
- // export { SplitComponent as component }
34
- }
35
- ],
36
- [
37
- "pendingComponent",
38
- {
39
- routeIdent: "pendingComponent",
40
- localImporterIdent: "$$splitPendingComponentImporter",
41
- // const $$splitPendingComponentImporter = () => import('...')
42
- splitStrategy: "lazyRouteComponent",
43
- localExporterIdent: "SplitPendingComponent",
44
- // const SplitPendingComponent = ...
45
- exporterIdent: "pendingComponent"
46
- // export { SplitPendingComponent as pendingComponent }
47
- }
48
- ],
49
- [
50
- "errorComponent",
51
- {
52
- routeIdent: "errorComponent",
53
- localImporterIdent: "$$splitErrorComponentImporter",
54
- // const $$splitErrorComponentImporter = () => import('...')
55
- splitStrategy: "lazyRouteComponent",
56
- localExporterIdent: "SplitErrorComponent",
57
- // const SplitErrorComponent = ...
58
- exporterIdent: "errorComponent"
59
- // export { SplitErrorComponent as errorComponent }
60
- }
61
- ],
62
- [
63
- "notFoundComponent",
64
- {
65
- routeIdent: "notFoundComponent",
66
- localImporterIdent: "$$splitNotFoundComponentImporter",
67
- // const $$splitNotFoundComponentImporter = () => import('...')
68
- splitStrategy: "lazyRouteComponent",
69
- localExporterIdent: "SplitNotFoundComponent",
70
- // const SplitNotFoundComponent = ...
71
- exporterIdent: "notFoundComponent"
72
- // export { SplitNotFoundComponent as notFoundComponent }
73
- }
74
- ]
5
+ import { deadCodeElimination, findReferencedIdentifiers, generateFromAst, parseAst } from "@tanstack/router-utils";
6
+ import * as t from "@babel/types";
7
+ import * as babel from "@babel/core";
8
+ import * as template from "@babel/template";
9
+ //#region src/core/code-splitter/compilers.ts
10
+ var SPLIT_NODES_CONFIG = new Map([
11
+ ["loader", {
12
+ routeIdent: "loader",
13
+ localImporterIdent: "$$splitLoaderImporter",
14
+ splitStrategy: "lazyFn",
15
+ localExporterIdent: "SplitLoader",
16
+ exporterIdent: "loader"
17
+ }],
18
+ ["component", {
19
+ routeIdent: "component",
20
+ localImporterIdent: "$$splitComponentImporter",
21
+ splitStrategy: "lazyRouteComponent",
22
+ localExporterIdent: "SplitComponent",
23
+ exporterIdent: "component"
24
+ }],
25
+ ["pendingComponent", {
26
+ routeIdent: "pendingComponent",
27
+ localImporterIdent: "$$splitPendingComponentImporter",
28
+ splitStrategy: "lazyRouteComponent",
29
+ localExporterIdent: "SplitPendingComponent",
30
+ exporterIdent: "pendingComponent"
31
+ }],
32
+ ["errorComponent", {
33
+ routeIdent: "errorComponent",
34
+ localImporterIdent: "$$splitErrorComponentImporter",
35
+ splitStrategy: "lazyRouteComponent",
36
+ localExporterIdent: "SplitErrorComponent",
37
+ exporterIdent: "errorComponent"
38
+ }],
39
+ ["notFoundComponent", {
40
+ routeIdent: "notFoundComponent",
41
+ localImporterIdent: "$$splitNotFoundComponentImporter",
42
+ splitStrategy: "lazyRouteComponent",
43
+ localExporterIdent: "SplitNotFoundComponent",
44
+ exporterIdent: "notFoundComponent"
45
+ }]
75
46
  ]);
76
- const KNOWN_SPLIT_ROUTE_IDENTS = [...SPLIT_NODES_CONFIG.keys()];
47
+ var KNOWN_SPLIT_ROUTE_IDENTS = [...SPLIT_NODES_CONFIG.keys()];
77
48
  function addSplitSearchParamToFilename(filename, grouping) {
78
- const [bareFilename] = filename.split("?");
79
- const params = new URLSearchParams();
80
- params.append(tsrSplit, createIdentifier(grouping));
81
- const result = `${bareFilename}?${params.toString()}`;
82
- return result;
49
+ const [bareFilename] = filename.split("?");
50
+ const params = new URLSearchParams();
51
+ params.append(tsrSplit, createIdentifier(grouping));
52
+ return `${bareFilename}?${params.toString()}`;
83
53
  }
84
54
  function removeSplitSearchParamFromFilename(filename) {
85
- const [bareFilename] = filename.split("?");
86
- return bareFilename;
55
+ const [bareFilename] = filename.split("?");
56
+ return bareFilename;
87
57
  }
88
58
  function addSharedSearchParamToFilename(filename) {
89
- const [bareFilename] = filename.split("?");
90
- return `${bareFilename}?${tsrShared}=1`;
59
+ const [bareFilename] = filename.split("?");
60
+ return `${bareFilename}?${tsrShared}=1`;
91
61
  }
92
- const splittableCreateRouteFns = ["createFileRoute"];
93
- const unsplittableCreateRouteFns = [
94
- "createRootRoute",
95
- "createRootRouteWithContext"
96
- ];
97
- const allCreateRouteFns = [
98
- ...splittableCreateRouteFns,
99
- ...unsplittableCreateRouteFns
100
- ];
62
+ var splittableCreateRouteFns = ["createFileRoute"];
63
+ var unsplittableCreateRouteFns = ["createRootRoute", "createRootRouteWithContext"];
64
+ var allCreateRouteFns = [...splittableCreateRouteFns, ...unsplittableCreateRouteFns];
65
+ /**
66
+ * Recursively walk an AST node and collect referenced identifier-like names.
67
+ * Much cheaper than babel.traverse — no path/scope overhead.
68
+ *
69
+ * Notes:
70
+ * - Uses @babel/types `isReferenced` to avoid collecting non-references like
71
+ * object keys, member expression properties, or binding identifiers.
72
+ * - Also handles JSX identifiers for component references.
73
+ */
101
74
  function collectIdentifiersFromNode(node) {
102
- const ids = /* @__PURE__ */ new Set();
103
- (function walk(n, parent, grandparent, parentKey) {
104
- if (!n) return;
105
- if (t.isIdentifier(n)) {
106
- if (!parent || t.isReferenced(n, parent, grandparent)) {
107
- ids.add(n.name);
108
- }
109
- return;
110
- }
111
- if (t.isJSXIdentifier(n)) {
112
- if (parent && t.isJSXAttribute(parent) && parentKey === "name") {
113
- return;
114
- }
115
- if (parent && t.isJSXMemberExpression(parent) && parentKey === "property") {
116
- return;
117
- }
118
- const first = n.name[0];
119
- if (first && first === first.toLowerCase()) {
120
- return;
121
- }
122
- ids.add(n.name);
123
- return;
124
- }
125
- for (const key of t.VISITOR_KEYS[n.type] || []) {
126
- const child = n[key];
127
- if (Array.isArray(child)) {
128
- for (const c of child) {
129
- if (c && typeof c.type === "string") {
130
- walk(c, n, parent, key);
131
- }
132
- }
133
- } else if (child && typeof child.type === "string") {
134
- walk(child, n, parent, key);
135
- }
136
- }
137
- })(node);
138
- return ids;
75
+ const ids = /* @__PURE__ */ new Set();
76
+ (function walk(n, parent, grandparent, parentKey) {
77
+ if (!n) return;
78
+ if (t.isIdentifier(n)) {
79
+ if (!parent || t.isReferenced(n, parent, grandparent)) ids.add(n.name);
80
+ return;
81
+ }
82
+ if (t.isJSXIdentifier(n)) {
83
+ if (parent && t.isJSXAttribute(parent) && parentKey === "name") return;
84
+ if (parent && t.isJSXMemberExpression(parent) && parentKey === "property") return;
85
+ const first = n.name[0];
86
+ if (first && first === first.toLowerCase()) return;
87
+ ids.add(n.name);
88
+ return;
89
+ }
90
+ for (const key of t.VISITOR_KEYS[n.type] || []) {
91
+ const child = n[key];
92
+ if (Array.isArray(child)) {
93
+ for (const c of child) if (c && typeof c.type === "string") walk(c, n, parent, key);
94
+ } else if (child && typeof child.type === "string") walk(child, n, parent, key);
95
+ }
96
+ })(node);
97
+ return ids;
139
98
  }
99
+ /**
100
+ * Build a map from binding name → declaration AST node for all
101
+ * locally-declared module-level bindings. Built once, O(1) lookup.
102
+ */
140
103
  function buildDeclarationMap(ast) {
141
- const map = /* @__PURE__ */ new Map();
142
- for (const stmt of ast.program.body) {
143
- const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
144
- if (t.isVariableDeclaration(decl)) {
145
- for (const declarator of decl.declarations) {
146
- for (const name of collectIdentifiersFromPattern(declarator.id)) {
147
- map.set(name, declarator);
148
- }
149
- }
150
- } else if (t.isFunctionDeclaration(decl) && decl.id) {
151
- map.set(decl.id.name, decl);
152
- } else if (t.isClassDeclaration(decl) && decl.id) {
153
- map.set(decl.id.name, decl);
154
- }
155
- }
156
- return map;
104
+ const map = /* @__PURE__ */ new Map();
105
+ for (const stmt of ast.program.body) {
106
+ const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
107
+ if (t.isVariableDeclaration(decl)) for (const declarator of decl.declarations) for (const name of collectIdentifiersFromPattern(declarator.id)) map.set(name, declarator);
108
+ else if (t.isFunctionDeclaration(decl) && decl.id) map.set(decl.id.name, decl);
109
+ else if (t.isClassDeclaration(decl) && decl.id) map.set(decl.id.name, decl);
110
+ }
111
+ return map;
157
112
  }
113
+ /**
114
+ * Build a dependency graph: for each local binding, the set of other local
115
+ * bindings its declaration references. Built once via simple node walking.
116
+ */
158
117
  function buildDependencyGraph(declMap, localBindings) {
159
- const graph = /* @__PURE__ */ new Map();
160
- for (const [name, declNode] of declMap) {
161
- if (!localBindings.has(name)) continue;
162
- const allIds = collectIdentifiersFromNode(declNode);
163
- const deps = /* @__PURE__ */ new Set();
164
- for (const id of allIds) {
165
- if (id !== name && localBindings.has(id)) deps.add(id);
166
- }
167
- graph.set(name, deps);
168
- }
169
- return graph;
118
+ const graph = /* @__PURE__ */ new Map();
119
+ for (const [name, declNode] of declMap) {
120
+ if (!localBindings.has(name)) continue;
121
+ const allIds = collectIdentifiersFromNode(declNode);
122
+ const deps = /* @__PURE__ */ new Set();
123
+ for (const id of allIds) if (id !== name && localBindings.has(id)) deps.add(id);
124
+ graph.set(name, deps);
125
+ }
126
+ return graph;
170
127
  }
128
+ /**
129
+ * Computes module-level bindings that are shared between split and non-split
130
+ * route properties. These bindings need to be extracted into a shared virtual
131
+ * module to avoid double-initialization.
132
+ *
133
+ * A binding is "shared" if it is referenced by at least one split property
134
+ * AND at least one non-split property. Only locally-declared module-level
135
+ * bindings are candidates (not imports — bundlers dedupe those).
136
+ */
171
137
  function computeSharedBindings(opts) {
172
- const ast = parseAst(opts);
173
- const localModuleLevelBindings = /* @__PURE__ */ new Set();
174
- for (const node of ast.program.body) {
175
- collectLocalBindingsFromStatement(node, localModuleLevelBindings);
176
- }
177
- localModuleLevelBindings.delete("Route");
178
- if (localModuleLevelBindings.size === 0) {
179
- return /* @__PURE__ */ new Set();
180
- }
181
- function findIndexForSplitNode(str) {
182
- return opts.codeSplitGroupings.findIndex(
183
- (group) => group.includes(str)
184
- );
185
- }
186
- let routeOptions;
187
- babel.traverse(ast, {
188
- CallExpression(path) {
189
- if (!t.isIdentifier(path.node.callee)) return;
190
- if (!splittableCreateRouteFns.includes(path.node.callee.name)) return;
191
- if (t.isCallExpression(path.parentPath.node)) {
192
- const opts2 = resolveIdentifier(path, path.parentPath.node.arguments[0]);
193
- if (t.isObjectExpression(opts2)) routeOptions = opts2;
194
- } else if (t.isVariableDeclarator(path.parentPath.node)) {
195
- const caller = resolveIdentifier(path, path.parentPath.node.init);
196
- if (t.isCallExpression(caller)) {
197
- const opts2 = resolveIdentifier(path, caller.arguments[0]);
198
- if (t.isObjectExpression(opts2)) routeOptions = opts2;
199
- }
200
- }
201
- }
202
- });
203
- if (!routeOptions) return /* @__PURE__ */ new Set();
204
- const splitGroupsPresent = /* @__PURE__ */ new Set();
205
- let hasNonSplit = false;
206
- for (const prop of routeOptions.properties) {
207
- if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
208
- if (prop.key.name === "codeSplitGroupings") continue;
209
- if (t.isIdentifier(prop.value) && prop.value.name === "undefined") continue;
210
- const groupIndex = findIndexForSplitNode(prop.key.name);
211
- if (groupIndex === -1) {
212
- hasNonSplit = true;
213
- } else {
214
- splitGroupsPresent.add(groupIndex);
215
- }
216
- }
217
- if (!hasNonSplit && splitGroupsPresent.size < 2) return /* @__PURE__ */ new Set();
218
- const declMap = buildDeclarationMap(ast);
219
- const depGraph = buildDependencyGraph(declMap, localModuleLevelBindings);
220
- const allLocalBindings = new Set(localModuleLevelBindings);
221
- allLocalBindings.add("Route");
222
- const fullDepGraph = buildDependencyGraph(declMap, allLocalBindings);
223
- const refsByGroup = /* @__PURE__ */ new Map();
224
- for (const prop of routeOptions.properties) {
225
- if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
226
- const key = prop.key.name;
227
- if (key === "codeSplitGroupings") continue;
228
- const groupIndex = findIndexForSplitNode(key);
229
- const directRefs = collectModuleLevelRefsFromNode(
230
- prop.value,
231
- localModuleLevelBindings
232
- );
233
- const allRefs = new Set(directRefs);
234
- expandTransitively(allRefs, depGraph);
235
- for (const ref of allRefs) {
236
- let groups = refsByGroup.get(ref);
237
- if (!groups) {
238
- groups = /* @__PURE__ */ new Set();
239
- refsByGroup.set(ref, groups);
240
- }
241
- groups.add(groupIndex);
242
- }
243
- }
244
- const shared = /* @__PURE__ */ new Set();
245
- for (const [name, groups] of refsByGroup) {
246
- if (groups.size >= 2) shared.add(name);
247
- }
248
- expandSharedDestructuredDeclarators(ast, refsByGroup, shared);
249
- if (shared.size === 0) return shared;
250
- expandDestructuredDeclarations(ast, shared);
251
- removeBindingsDependingOnRoute(shared, fullDepGraph);
252
- return shared;
138
+ const ast = parseAst(opts);
139
+ const localModuleLevelBindings = /* @__PURE__ */ new Set();
140
+ for (const node of ast.program.body) collectLocalBindingsFromStatement(node, localModuleLevelBindings);
141
+ localModuleLevelBindings.delete("Route");
142
+ if (localModuleLevelBindings.size === 0) return /* @__PURE__ */ new Set();
143
+ function findIndexForSplitNode(str) {
144
+ return opts.codeSplitGroupings.findIndex((group) => group.includes(str));
145
+ }
146
+ let routeOptions;
147
+ babel.traverse(ast, { CallExpression(path) {
148
+ if (!t.isIdentifier(path.node.callee)) return;
149
+ if (!splittableCreateRouteFns.includes(path.node.callee.name)) return;
150
+ if (t.isCallExpression(path.parentPath.node)) {
151
+ const opts = resolveIdentifier(path, path.parentPath.node.arguments[0]);
152
+ if (t.isObjectExpression(opts)) routeOptions = opts;
153
+ } else if (t.isVariableDeclarator(path.parentPath.node)) {
154
+ const caller = resolveIdentifier(path, path.parentPath.node.init);
155
+ if (t.isCallExpression(caller)) {
156
+ const opts = resolveIdentifier(path, caller.arguments[0]);
157
+ if (t.isObjectExpression(opts)) routeOptions = opts;
158
+ }
159
+ }
160
+ } });
161
+ if (!routeOptions) return /* @__PURE__ */ new Set();
162
+ const splitGroupsPresent = /* @__PURE__ */ new Set();
163
+ let hasNonSplit = false;
164
+ for (const prop of routeOptions.properties) {
165
+ if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
166
+ if (prop.key.name === "codeSplitGroupings") continue;
167
+ if (t.isIdentifier(prop.value) && prop.value.name === "undefined") continue;
168
+ const groupIndex = findIndexForSplitNode(prop.key.name);
169
+ if (groupIndex === -1) hasNonSplit = true;
170
+ else splitGroupsPresent.add(groupIndex);
171
+ }
172
+ if (!hasNonSplit && splitGroupsPresent.size < 2) return /* @__PURE__ */ new Set();
173
+ const declMap = buildDeclarationMap(ast);
174
+ const depGraph = buildDependencyGraph(declMap, localModuleLevelBindings);
175
+ const allLocalBindings = new Set(localModuleLevelBindings);
176
+ allLocalBindings.add("Route");
177
+ const fullDepGraph = buildDependencyGraph(declMap, allLocalBindings);
178
+ const refsByGroup = /* @__PURE__ */ new Map();
179
+ for (const prop of routeOptions.properties) {
180
+ if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
181
+ const key = prop.key.name;
182
+ if (key === "codeSplitGroupings") continue;
183
+ const groupIndex = findIndexForSplitNode(key);
184
+ const directRefs = collectModuleLevelRefsFromNode(prop.value, localModuleLevelBindings);
185
+ const allRefs = new Set(directRefs);
186
+ expandTransitively(allRefs, depGraph);
187
+ for (const ref of allRefs) {
188
+ let groups = refsByGroup.get(ref);
189
+ if (!groups) {
190
+ groups = /* @__PURE__ */ new Set();
191
+ refsByGroup.set(ref, groups);
192
+ }
193
+ groups.add(groupIndex);
194
+ }
195
+ }
196
+ const shared = /* @__PURE__ */ new Set();
197
+ for (const [name, groups] of refsByGroup) if (groups.size >= 2) shared.add(name);
198
+ expandSharedDestructuredDeclarators(ast, refsByGroup, shared);
199
+ if (shared.size === 0) return shared;
200
+ expandDestructuredDeclarations(ast, shared);
201
+ removeBindingsDependingOnRoute(shared, fullDepGraph);
202
+ return shared;
253
203
  }
204
+ /**
205
+ * If bindings from the same destructured declarator are referenced by
206
+ * different groups, mark all bindings from that declarator as shared.
207
+ */
254
208
  function expandSharedDestructuredDeclarators(ast, refsByGroup, shared) {
255
- for (const stmt of ast.program.body) {
256
- const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
257
- if (!t.isVariableDeclaration(decl)) continue;
258
- for (const declarator of decl.declarations) {
259
- if (!t.isObjectPattern(declarator.id) && !t.isArrayPattern(declarator.id))
260
- continue;
261
- const names = collectIdentifiersFromPattern(declarator.id);
262
- const usedGroups = /* @__PURE__ */ new Set();
263
- for (const name of names) {
264
- const groups = refsByGroup.get(name);
265
- if (!groups) continue;
266
- for (const g of groups) usedGroups.add(g);
267
- }
268
- if (usedGroups.size >= 2) {
269
- for (const name of names) {
270
- shared.add(name);
271
- }
272
- }
273
- }
274
- }
209
+ for (const stmt of ast.program.body) {
210
+ const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
211
+ if (!t.isVariableDeclaration(decl)) continue;
212
+ for (const declarator of decl.declarations) {
213
+ if (!t.isObjectPattern(declarator.id) && !t.isArrayPattern(declarator.id)) continue;
214
+ const names = collectIdentifiersFromPattern(declarator.id);
215
+ const usedGroups = /* @__PURE__ */ new Set();
216
+ for (const name of names) {
217
+ const groups = refsByGroup.get(name);
218
+ if (!groups) continue;
219
+ for (const g of groups) usedGroups.add(g);
220
+ }
221
+ if (usedGroups.size >= 2) for (const name of names) shared.add(name);
222
+ }
223
+ }
275
224
  }
225
+ /**
226
+ * Collect locally-declared module-level binding names from a statement.
227
+ * Pure node inspection, no traversal.
228
+ */
276
229
  function collectLocalBindingsFromStatement(node, bindings) {
277
- const decl = t.isExportNamedDeclaration(node) && node.declaration ? node.declaration : node;
278
- if (t.isVariableDeclaration(decl)) {
279
- for (const declarator of decl.declarations) {
280
- for (const name of collectIdentifiersFromPattern(declarator.id)) {
281
- bindings.add(name);
282
- }
283
- }
284
- } else if (t.isFunctionDeclaration(decl) && decl.id) {
285
- bindings.add(decl.id.name);
286
- } else if (t.isClassDeclaration(decl) && decl.id) {
287
- bindings.add(decl.id.name);
288
- }
230
+ const decl = t.isExportNamedDeclaration(node) && node.declaration ? node.declaration : node;
231
+ if (t.isVariableDeclaration(decl)) for (const declarator of decl.declarations) for (const name of collectIdentifiersFromPattern(declarator.id)) bindings.add(name);
232
+ else if (t.isFunctionDeclaration(decl) && decl.id) bindings.add(decl.id.name);
233
+ else if (t.isClassDeclaration(decl) && decl.id) bindings.add(decl.id.name);
289
234
  }
235
+ /**
236
+ * Collect direct module-level binding names referenced from a given AST node.
237
+ * Uses a simple recursive walk instead of babel.traverse.
238
+ */
290
239
  function collectModuleLevelRefsFromNode(node, localModuleLevelBindings) {
291
- const allIds = collectIdentifiersFromNode(node);
292
- const refs = /* @__PURE__ */ new Set();
293
- for (const name of allIds) {
294
- if (localModuleLevelBindings.has(name)) refs.add(name);
295
- }
296
- return refs;
240
+ const allIds = collectIdentifiersFromNode(node);
241
+ const refs = /* @__PURE__ */ new Set();
242
+ for (const name of allIds) if (localModuleLevelBindings.has(name)) refs.add(name);
243
+ return refs;
297
244
  }
245
+ /**
246
+ * Expand the shared set transitively using a prebuilt dependency graph.
247
+ * No AST traversals — pure graph BFS.
248
+ */
298
249
  function expandTransitively(shared, depGraph) {
299
- const queue = [...shared];
300
- const visited = /* @__PURE__ */ new Set();
301
- while (queue.length > 0) {
302
- const name = queue.pop();
303
- if (visited.has(name)) continue;
304
- visited.add(name);
305
- const deps = depGraph.get(name);
306
- if (!deps) continue;
307
- for (const dep of deps) {
308
- if (!shared.has(dep)) {
309
- shared.add(dep);
310
- queue.push(dep);
311
- }
312
- }
313
- }
250
+ const queue = [...shared];
251
+ const visited = /* @__PURE__ */ new Set();
252
+ while (queue.length > 0) {
253
+ const name = queue.pop();
254
+ if (visited.has(name)) continue;
255
+ visited.add(name);
256
+ const deps = depGraph.get(name);
257
+ if (!deps) continue;
258
+ for (const dep of deps) if (!shared.has(dep)) {
259
+ shared.add(dep);
260
+ queue.push(dep);
261
+ }
262
+ }
314
263
  }
264
+ /**
265
+ * Remove any bindings from `shared` that transitively depend on `Route`.
266
+ * The Route singleton must remain in the reference file; if a shared binding
267
+ * references it (directly or transitively), extracting that binding would
268
+ * duplicate Route in the shared module.
269
+ *
270
+ * Uses `depGraph` which must include `Route` as a node so the dependency
271
+ * chain is visible.
272
+ */
315
273
  function removeBindingsDependingOnRoute(shared, depGraph) {
316
- const reverseGraph = /* @__PURE__ */ new Map();
317
- for (const [name, deps] of depGraph) {
318
- for (const dep of deps) {
319
- let parents = reverseGraph.get(dep);
320
- if (!parents) {
321
- parents = /* @__PURE__ */ new Set();
322
- reverseGraph.set(dep, parents);
323
- }
324
- parents.add(name);
325
- }
326
- }
327
- const visited = /* @__PURE__ */ new Set();
328
- const queue = ["Route"];
329
- while (queue.length > 0) {
330
- const cur = queue.pop();
331
- if (visited.has(cur)) continue;
332
- visited.add(cur);
333
- const parents = reverseGraph.get(cur);
334
- if (!parents) continue;
335
- for (const parent of parents) {
336
- if (!visited.has(parent)) queue.push(parent);
337
- }
338
- }
339
- for (const name of [...shared]) {
340
- if (visited.has(name)) {
341
- shared.delete(name);
342
- }
343
- }
274
+ const reverseGraph = /* @__PURE__ */ new Map();
275
+ for (const [name, deps] of depGraph) for (const dep of deps) {
276
+ let parents = reverseGraph.get(dep);
277
+ if (!parents) {
278
+ parents = /* @__PURE__ */ new Set();
279
+ reverseGraph.set(dep, parents);
280
+ }
281
+ parents.add(name);
282
+ }
283
+ const visited = /* @__PURE__ */ new Set();
284
+ const queue = ["Route"];
285
+ while (queue.length > 0) {
286
+ const cur = queue.pop();
287
+ if (visited.has(cur)) continue;
288
+ visited.add(cur);
289
+ const parents = reverseGraph.get(cur);
290
+ if (!parents) continue;
291
+ for (const parent of parents) if (!visited.has(parent)) queue.push(parent);
292
+ }
293
+ for (const name of [...shared]) if (visited.has(name)) shared.delete(name);
344
294
  }
295
+ /**
296
+ * If any binding from a destructured declaration is shared,
297
+ * ensure all bindings from that same declaration are also shared.
298
+ * Pure node inspection of program.body, no traversal.
299
+ */
345
300
  function expandDestructuredDeclarations(ast, shared) {
346
- for (const stmt of ast.program.body) {
347
- const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
348
- if (!t.isVariableDeclaration(decl)) continue;
349
- for (const declarator of decl.declarations) {
350
- if (!t.isObjectPattern(declarator.id) && !t.isArrayPattern(declarator.id))
351
- continue;
352
- const names = collectIdentifiersFromPattern(declarator.id);
353
- const hasShared = names.some((n) => shared.has(n));
354
- if (hasShared) {
355
- for (const n of names) {
356
- shared.add(n);
357
- }
358
- }
359
- }
360
- }
301
+ for (const stmt of ast.program.body) {
302
+ const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
303
+ if (!t.isVariableDeclaration(decl)) continue;
304
+ for (const declarator of decl.declarations) {
305
+ if (!t.isObjectPattern(declarator.id) && !t.isArrayPattern(declarator.id)) continue;
306
+ const names = collectIdentifiersFromPattern(declarator.id);
307
+ if (names.some((n) => shared.has(n))) for (const n of names) shared.add(n);
308
+ }
309
+ }
361
310
  }
311
+ /**
312
+ * Find which shared bindings are user-exported in the original source.
313
+ * These need to be re-exported from the shared module.
314
+ */
362
315
  function findExportedSharedBindings(ast, sharedBindings) {
363
- const exported = /* @__PURE__ */ new Set();
364
- for (const stmt of ast.program.body) {
365
- if (!t.isExportNamedDeclaration(stmt) || !stmt.declaration) continue;
366
- if (t.isVariableDeclaration(stmt.declaration)) {
367
- for (const decl of stmt.declaration.declarations) {
368
- for (const name of collectIdentifiersFromPattern(decl.id)) {
369
- if (sharedBindings.has(name)) exported.add(name);
370
- }
371
- }
372
- } else if (t.isFunctionDeclaration(stmt.declaration) && stmt.declaration.id) {
373
- if (sharedBindings.has(stmt.declaration.id.name))
374
- exported.add(stmt.declaration.id.name);
375
- } else if (t.isClassDeclaration(stmt.declaration) && stmt.declaration.id) {
376
- if (sharedBindings.has(stmt.declaration.id.name))
377
- exported.add(stmt.declaration.id.name);
378
- }
379
- }
380
- return exported;
316
+ const exported = /* @__PURE__ */ new Set();
317
+ for (const stmt of ast.program.body) {
318
+ if (!t.isExportNamedDeclaration(stmt) || !stmt.declaration) continue;
319
+ if (t.isVariableDeclaration(stmt.declaration)) {
320
+ for (const decl of stmt.declaration.declarations) for (const name of collectIdentifiersFromPattern(decl.id)) if (sharedBindings.has(name)) exported.add(name);
321
+ } else if (t.isFunctionDeclaration(stmt.declaration) && stmt.declaration.id) {
322
+ if (sharedBindings.has(stmt.declaration.id.name)) exported.add(stmt.declaration.id.name);
323
+ } else if (t.isClassDeclaration(stmt.declaration) && stmt.declaration.id) {
324
+ if (sharedBindings.has(stmt.declaration.id.name)) exported.add(stmt.declaration.id.name);
325
+ }
326
+ }
327
+ return exported;
381
328
  }
329
+ /**
330
+ * Remove declarations of shared bindings from the AST.
331
+ * Handles both plain and exported declarations, including destructured patterns.
332
+ * Removes the entire statement if all bindings in it are shared.
333
+ */
382
334
  function removeSharedDeclarations(ast, sharedBindings) {
383
- ast.program.body = ast.program.body.filter((stmt) => {
384
- const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
385
- if (t.isVariableDeclaration(decl)) {
386
- decl.declarations = decl.declarations.filter((declarator) => {
387
- const names = collectIdentifiersFromPattern(declarator.id);
388
- return !names.every((n) => sharedBindings.has(n));
389
- });
390
- if (decl.declarations.length === 0) return false;
391
- } else if (t.isFunctionDeclaration(decl) && decl.id) {
392
- if (sharedBindings.has(decl.id.name)) return false;
393
- } else if (t.isClassDeclaration(decl) && decl.id) {
394
- if (sharedBindings.has(decl.id.name)) return false;
395
- }
396
- return true;
397
- });
335
+ ast.program.body = ast.program.body.filter((stmt) => {
336
+ const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
337
+ if (t.isVariableDeclaration(decl)) {
338
+ decl.declarations = decl.declarations.filter((declarator) => {
339
+ return !collectIdentifiersFromPattern(declarator.id).every((n) => sharedBindings.has(n));
340
+ });
341
+ if (decl.declarations.length === 0) return false;
342
+ } else if (t.isFunctionDeclaration(decl) && decl.id) {
343
+ if (sharedBindings.has(decl.id.name)) return false;
344
+ } else if (t.isClassDeclaration(decl) && decl.id) {
345
+ if (sharedBindings.has(decl.id.name)) return false;
346
+ }
347
+ return true;
348
+ });
398
349
  }
399
350
  function compileCodeSplitReferenceRoute(opts) {
400
- const ast = parseAst(opts);
401
- const refIdents = findReferencedIdentifiers(ast);
402
- const knownExportedIdents = /* @__PURE__ */ new Set();
403
- function findIndexForSplitNode(str) {
404
- return opts.codeSplitGroupings.findIndex(
405
- (group) => group.includes(str)
406
- );
407
- }
408
- const frameworkOptions = getFrameworkOptions(opts.targetFramework);
409
- const PACKAGE = frameworkOptions.package;
410
- const LAZY_ROUTE_COMPONENT_IDENT = frameworkOptions.idents.lazyRouteComponent;
411
- const LAZY_FN_IDENT = frameworkOptions.idents.lazyFn;
412
- let createRouteFn;
413
- let modified = false;
414
- let hmrAdded = false;
415
- let sharedExportedNames;
416
- babel.traverse(ast, {
417
- Program: {
418
- enter(programPath) {
419
- const removableImportPaths = /* @__PURE__ */ new Set([]);
420
- programPath.traverse({
421
- CallExpression: (path) => {
422
- if (!t.isIdentifier(path.node.callee)) {
423
- return;
424
- }
425
- if (!allCreateRouteFns.includes(path.node.callee.name)) {
426
- return;
427
- }
428
- createRouteFn = path.node.callee.name;
429
- function babelHandleReference(routeOptions) {
430
- const hasImportedOrDefinedIdentifier = (name) => {
431
- return programPath.scope.hasBinding(name);
432
- };
433
- if (t.isObjectExpression(routeOptions)) {
434
- if (opts.deleteNodes && opts.deleteNodes.size > 0) {
435
- routeOptions.properties = routeOptions.properties.filter(
436
- (prop) => {
437
- if (t.isObjectProperty(prop)) {
438
- if (t.isIdentifier(prop.key)) {
439
- if (opts.deleteNodes.has(prop.key.name)) {
440
- modified = true;
441
- return false;
442
- }
443
- }
444
- }
445
- return true;
446
- }
447
- );
448
- }
449
- if (!splittableCreateRouteFns.includes(createRouteFn)) {
450
- const insertionPath = path.getStatementParent() ?? path;
451
- opts.compilerPlugins?.forEach((plugin) => {
452
- const pluginResult = plugin.onUnsplittableRoute?.({
453
- programPath,
454
- callExpressionPath: path,
455
- insertionPath,
456
- routeOptions,
457
- createRouteFn,
458
- opts
459
- });
460
- if (pluginResult?.modified) {
461
- modified = true;
462
- }
463
- });
464
- if (opts.addHmr && !hmrAdded) {
465
- programPath.pushContainer("body", routeHmrStatement);
466
- modified = true;
467
- hmrAdded = true;
468
- }
469
- return programPath.stop();
470
- }
471
- routeOptions.properties.forEach((prop) => {
472
- if (t.isObjectProperty(prop)) {
473
- if (t.isIdentifier(prop.key)) {
474
- const key = prop.key.name;
475
- const codeSplitGroupingByKey = findIndexForSplitNode(key);
476
- if (codeSplitGroupingByKey === -1) {
477
- return;
478
- }
479
- const codeSplitGroup = [
480
- ...new Set(
481
- opts.codeSplitGroupings[codeSplitGroupingByKey]
482
- )
483
- ];
484
- const isNodeConfigAvailable = SPLIT_NODES_CONFIG.has(
485
- key
486
- );
487
- if (!isNodeConfigAvailable) {
488
- return;
489
- }
490
- if (t.isBooleanLiteral(prop.value) || t.isNullLiteral(prop.value) || t.isIdentifier(prop.value) && prop.value.name === "undefined") {
491
- return;
492
- }
493
- const splitNodeMeta = SPLIT_NODES_CONFIG.get(key);
494
- const splitUrl = addSplitSearchParamToFilename(
495
- opts.filename,
496
- codeSplitGroup
497
- );
498
- if (splitNodeMeta.splitStrategy === "lazyRouteComponent") {
499
- const value = prop.value;
500
- let shouldSplit = true;
501
- if (t.isIdentifier(value)) {
502
- const existingImportPath = getImportSpecifierAndPathFromLocalName(
503
- programPath,
504
- value.name
505
- ).path;
506
- if (existingImportPath) {
507
- removableImportPaths.add(existingImportPath);
508
- }
509
- const isExported = hasExport(ast, value);
510
- if (isExported) {
511
- knownExportedIdents.add(value.name);
512
- }
513
- shouldSplit = !isExported;
514
- if (shouldSplit) {
515
- removeIdentifierLiteral(path, value);
516
- }
517
- }
518
- if (!shouldSplit) {
519
- return;
520
- }
521
- modified = true;
522
- if (!hasImportedOrDefinedIdentifier(
523
- LAZY_ROUTE_COMPONENT_IDENT
524
- )) {
525
- programPath.unshiftContainer("body", [
526
- template.statement(
527
- `import { ${LAZY_ROUTE_COMPONENT_IDENT} } from '${PACKAGE}'`
528
- )()
529
- ]);
530
- }
531
- if (!hasImportedOrDefinedIdentifier(
532
- splitNodeMeta.localImporterIdent
533
- )) {
534
- programPath.unshiftContainer("body", [
535
- template.statement(
536
- `const ${splitNodeMeta.localImporterIdent} = () => import('${splitUrl}')`
537
- )()
538
- ]);
539
- }
540
- prop.value = template.expression(
541
- `${LAZY_ROUTE_COMPONENT_IDENT}(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`
542
- )();
543
- if (opts.addHmr && !hmrAdded) {
544
- programPath.pushContainer("body", routeHmrStatement);
545
- modified = true;
546
- hmrAdded = true;
547
- }
548
- } else {
549
- const value = prop.value;
550
- let shouldSplit = true;
551
- if (t.isIdentifier(value)) {
552
- const existingImportPath = getImportSpecifierAndPathFromLocalName(
553
- programPath,
554
- value.name
555
- ).path;
556
- if (existingImportPath) {
557
- removableImportPaths.add(existingImportPath);
558
- }
559
- const isExported = hasExport(ast, value);
560
- if (isExported) {
561
- knownExportedIdents.add(value.name);
562
- }
563
- shouldSplit = !isExported;
564
- if (shouldSplit) {
565
- removeIdentifierLiteral(path, value);
566
- }
567
- }
568
- if (!shouldSplit) {
569
- return;
570
- }
571
- modified = true;
572
- if (!hasImportedOrDefinedIdentifier(LAZY_FN_IDENT)) {
573
- programPath.unshiftContainer(
574
- "body",
575
- template.smart(
576
- `import { ${LAZY_FN_IDENT} } from '${PACKAGE}'`
577
- )()
578
- );
579
- }
580
- if (!hasImportedOrDefinedIdentifier(
581
- splitNodeMeta.localImporterIdent
582
- )) {
583
- programPath.unshiftContainer("body", [
584
- template.statement(
585
- `const ${splitNodeMeta.localImporterIdent} = () => import('${splitUrl}')`
586
- )()
587
- ]);
588
- }
589
- prop.value = template.expression(
590
- `${LAZY_FN_IDENT}(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`
591
- )();
592
- }
593
- }
594
- }
595
- programPath.scope.crawl();
596
- });
597
- }
598
- }
599
- if (t.isCallExpression(path.parentPath.node)) {
600
- const options = resolveIdentifier(
601
- path,
602
- path.parentPath.node.arguments[0]
603
- );
604
- babelHandleReference(options);
605
- } else if (t.isVariableDeclarator(path.parentPath.node)) {
606
- const caller = resolveIdentifier(path, path.parentPath.node.init);
607
- if (t.isCallExpression(caller)) {
608
- const options = resolveIdentifier(path, caller.arguments[0]);
609
- babelHandleReference(options);
610
- }
611
- }
612
- }
613
- });
614
- if (removableImportPaths.size > 0) {
615
- modified = true;
616
- programPath.traverse({
617
- ImportDeclaration(path) {
618
- if (path.node.specifiers.length > 0) return;
619
- if (removableImportPaths.has(path.node.source.value)) {
620
- path.remove();
621
- }
622
- }
623
- });
624
- }
625
- if (opts.sharedBindings && opts.sharedBindings.size > 0) {
626
- sharedExportedNames = findExportedSharedBindings(
627
- ast,
628
- opts.sharedBindings
629
- );
630
- removeSharedDeclarations(ast, opts.sharedBindings);
631
- const sharedModuleUrl = addSharedSearchParamToFilename(opts.filename);
632
- const sharedImportSpecifiers = [...opts.sharedBindings].map(
633
- (name) => t.importSpecifier(t.identifier(name), t.identifier(name))
634
- );
635
- const [sharedImportPath] = programPath.unshiftContainer(
636
- "body",
637
- t.importDeclaration(
638
- sharedImportSpecifiers,
639
- t.stringLiteral(sharedModuleUrl)
640
- )
641
- );
642
- sharedImportPath.traverse({
643
- Identifier(identPath) {
644
- if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") {
645
- refIdents.add(identPath);
646
- }
647
- }
648
- });
649
- if (sharedExportedNames.size > 0) {
650
- const reExportSpecifiers = [...sharedExportedNames].map(
651
- (name) => t.exportSpecifier(t.identifier(name), t.identifier(name))
652
- );
653
- programPath.pushContainer(
654
- "body",
655
- t.exportNamedDeclaration(
656
- null,
657
- reExportSpecifiers,
658
- t.stringLiteral(sharedModuleUrl)
659
- )
660
- );
661
- }
662
- }
663
- }
664
- }
665
- });
666
- if (!modified) {
667
- return null;
668
- }
669
- deadCodeElimination(ast, refIdents);
670
- if (knownExportedIdents.size > 0) {
671
- const warningMessage = createNotExportableMessage(
672
- opts.filename,
673
- knownExportedIdents
674
- );
675
- console.warn(warningMessage);
676
- if (process.env.NODE_ENV !== "production") {
677
- const warningTemplate = template.statement(
678
- `console.warn(${JSON.stringify(warningMessage)})`
679
- )();
680
- ast.program.body.unshift(warningTemplate);
681
- }
682
- }
683
- const result = generateFromAst(ast, {
684
- sourceMaps: true,
685
- sourceFileName: opts.filename,
686
- filename: opts.filename
687
- });
688
- if (result.map) {
689
- result.map.sourcesContent = [opts.code];
690
- }
691
- return result;
351
+ const ast = parseAst(opts);
352
+ const refIdents = findReferencedIdentifiers(ast);
353
+ const knownExportedIdents = /* @__PURE__ */ new Set();
354
+ function findIndexForSplitNode(str) {
355
+ return opts.codeSplitGroupings.findIndex((group) => group.includes(str));
356
+ }
357
+ const frameworkOptions = getFrameworkOptions(opts.targetFramework);
358
+ const PACKAGE = frameworkOptions.package;
359
+ const LAZY_ROUTE_COMPONENT_IDENT = frameworkOptions.idents.lazyRouteComponent;
360
+ const LAZY_FN_IDENT = frameworkOptions.idents.lazyFn;
361
+ let createRouteFn;
362
+ let modified = false;
363
+ let hmrAdded = false;
364
+ let sharedExportedNames;
365
+ babel.traverse(ast, { Program: { enter(programPath) {
366
+ /**
367
+ * If the component for the route is being imported from
368
+ * another file, this is to track the path to that file
369
+ * the path itself doesn't matter, we just need to keep
370
+ * track of it so that we can remove it from the imports
371
+ * list if it's not being used like:
372
+ *
373
+ * `import '../shared/imported'`
374
+ */
375
+ const removableImportPaths = /* @__PURE__ */ new Set([]);
376
+ programPath.traverse({ CallExpression: (path) => {
377
+ if (!t.isIdentifier(path.node.callee)) return;
378
+ if (!allCreateRouteFns.includes(path.node.callee.name)) return;
379
+ createRouteFn = path.node.callee.name;
380
+ function babelHandleReference(routeOptions) {
381
+ const hasImportedOrDefinedIdentifier = (name) => {
382
+ return programPath.scope.hasBinding(name);
383
+ };
384
+ if (t.isObjectExpression(routeOptions)) {
385
+ if (opts.deleteNodes && opts.deleteNodes.size > 0) routeOptions.properties = routeOptions.properties.filter((prop) => {
386
+ if (t.isObjectProperty(prop)) {
387
+ if (t.isIdentifier(prop.key)) {
388
+ if (opts.deleteNodes.has(prop.key.name)) {
389
+ modified = true;
390
+ return false;
391
+ }
392
+ }
393
+ }
394
+ return true;
395
+ });
396
+ if (!splittableCreateRouteFns.includes(createRouteFn)) {
397
+ const insertionPath = path.getStatementParent() ?? path;
398
+ opts.compilerPlugins?.forEach((plugin) => {
399
+ if ((plugin.onUnsplittableRoute?.({
400
+ programPath,
401
+ callExpressionPath: path,
402
+ insertionPath,
403
+ routeOptions,
404
+ createRouteFn,
405
+ opts
406
+ }))?.modified) modified = true;
407
+ });
408
+ if (opts.addHmr && !hmrAdded) {
409
+ programPath.pushContainer("body", routeHmrStatement);
410
+ modified = true;
411
+ hmrAdded = true;
412
+ }
413
+ return programPath.stop();
414
+ }
415
+ routeOptions.properties.forEach((prop) => {
416
+ if (t.isObjectProperty(prop)) {
417
+ if (t.isIdentifier(prop.key)) {
418
+ const key = prop.key.name;
419
+ const codeSplitGroupingByKey = findIndexForSplitNode(key);
420
+ if (codeSplitGroupingByKey === -1) return;
421
+ const codeSplitGroup = [...new Set(opts.codeSplitGroupings[codeSplitGroupingByKey])];
422
+ if (!SPLIT_NODES_CONFIG.has(key)) return;
423
+ if (t.isBooleanLiteral(prop.value) || t.isNullLiteral(prop.value) || t.isIdentifier(prop.value) && prop.value.name === "undefined") return;
424
+ const splitNodeMeta = SPLIT_NODES_CONFIG.get(key);
425
+ const splitUrl = addSplitSearchParamToFilename(opts.filename, codeSplitGroup);
426
+ if (splitNodeMeta.splitStrategy === "lazyRouteComponent") {
427
+ const value = prop.value;
428
+ let shouldSplit = true;
429
+ if (t.isIdentifier(value)) {
430
+ const existingImportPath = getImportSpecifierAndPathFromLocalName(programPath, value.name).path;
431
+ if (existingImportPath) removableImportPaths.add(existingImportPath);
432
+ const isExported = hasExport(ast, value);
433
+ if (isExported) knownExportedIdents.add(value.name);
434
+ shouldSplit = !isExported;
435
+ if (shouldSplit) removeIdentifierLiteral(path, value);
436
+ }
437
+ if (!shouldSplit) return;
438
+ modified = true;
439
+ if (!hasImportedOrDefinedIdentifier(LAZY_ROUTE_COMPONENT_IDENT)) programPath.unshiftContainer("body", [template.statement(`import { ${LAZY_ROUTE_COMPONENT_IDENT} } from '${PACKAGE}'`)()]);
440
+ if (!hasImportedOrDefinedIdentifier(splitNodeMeta.localImporterIdent)) programPath.unshiftContainer("body", [template.statement(`const ${splitNodeMeta.localImporterIdent} = () => import('${splitUrl}')`)()]);
441
+ prop.value = template.expression(`${LAZY_ROUTE_COMPONENT_IDENT}(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`)();
442
+ if (opts.addHmr && !hmrAdded) {
443
+ programPath.pushContainer("body", routeHmrStatement);
444
+ modified = true;
445
+ hmrAdded = true;
446
+ }
447
+ } else {
448
+ const value = prop.value;
449
+ let shouldSplit = true;
450
+ if (t.isIdentifier(value)) {
451
+ const existingImportPath = getImportSpecifierAndPathFromLocalName(programPath, value.name).path;
452
+ if (existingImportPath) removableImportPaths.add(existingImportPath);
453
+ const isExported = hasExport(ast, value);
454
+ if (isExported) knownExportedIdents.add(value.name);
455
+ shouldSplit = !isExported;
456
+ if (shouldSplit) removeIdentifierLiteral(path, value);
457
+ }
458
+ if (!shouldSplit) return;
459
+ modified = true;
460
+ if (!hasImportedOrDefinedIdentifier(LAZY_FN_IDENT)) programPath.unshiftContainer("body", template.smart(`import { ${LAZY_FN_IDENT} } from '${PACKAGE}'`)());
461
+ if (!hasImportedOrDefinedIdentifier(splitNodeMeta.localImporterIdent)) programPath.unshiftContainer("body", [template.statement(`const ${splitNodeMeta.localImporterIdent} = () => import('${splitUrl}')`)()]);
462
+ prop.value = template.expression(`${LAZY_FN_IDENT}(${splitNodeMeta.localImporterIdent}, '${splitNodeMeta.exporterIdent}')`)();
463
+ }
464
+ }
465
+ }
466
+ programPath.scope.crawl();
467
+ });
468
+ }
469
+ }
470
+ if (t.isCallExpression(path.parentPath.node)) babelHandleReference(resolveIdentifier(path, path.parentPath.node.arguments[0]));
471
+ else if (t.isVariableDeclarator(path.parentPath.node)) {
472
+ const caller = resolveIdentifier(path, path.parentPath.node.init);
473
+ if (t.isCallExpression(caller)) babelHandleReference(resolveIdentifier(path, caller.arguments[0]));
474
+ }
475
+ } });
476
+ /**
477
+ * If the component for the route is being imported,
478
+ * and it's not being used, remove the import statement
479
+ * from the program, by checking that the import has no
480
+ * specifiers
481
+ */
482
+ if (removableImportPaths.size > 0) {
483
+ modified = true;
484
+ programPath.traverse({ ImportDeclaration(path) {
485
+ if (path.node.specifiers.length > 0) return;
486
+ if (removableImportPaths.has(path.node.source.value)) path.remove();
487
+ } });
488
+ }
489
+ if (opts.sharedBindings && opts.sharedBindings.size > 0) {
490
+ sharedExportedNames = findExportedSharedBindings(ast, opts.sharedBindings);
491
+ removeSharedDeclarations(ast, opts.sharedBindings);
492
+ const sharedModuleUrl = addSharedSearchParamToFilename(opts.filename);
493
+ const sharedImportSpecifiers = [...opts.sharedBindings].map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
494
+ const [sharedImportPath] = programPath.unshiftContainer("body", t.importDeclaration(sharedImportSpecifiers, t.stringLiteral(sharedModuleUrl)));
495
+ sharedImportPath.traverse({ Identifier(identPath) {
496
+ if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") refIdents.add(identPath);
497
+ } });
498
+ if (sharedExportedNames.size > 0) {
499
+ const reExportSpecifiers = [...sharedExportedNames].map((name) => t.exportSpecifier(t.identifier(name), t.identifier(name)));
500
+ programPath.pushContainer("body", t.exportNamedDeclaration(null, reExportSpecifiers, t.stringLiteral(sharedModuleUrl)));
501
+ }
502
+ }
503
+ } } });
504
+ if (!modified) return null;
505
+ deadCodeElimination(ast, refIdents);
506
+ if (knownExportedIdents.size > 0) {
507
+ const warningMessage = createNotExportableMessage(opts.filename, knownExportedIdents);
508
+ console.warn(warningMessage);
509
+ if (process.env.NODE_ENV !== "production") {
510
+ const warningTemplate = template.statement(`console.warn(${JSON.stringify(warningMessage)})`)();
511
+ ast.program.body.unshift(warningTemplate);
512
+ }
513
+ }
514
+ const result = generateFromAst(ast, {
515
+ sourceMaps: true,
516
+ sourceFileName: opts.filename,
517
+ filename: opts.filename
518
+ });
519
+ if (result.map) result.map.sourcesContent = [opts.code];
520
+ return result;
692
521
  }
693
522
  function compileCodeSplitVirtualRoute(opts) {
694
- const ast = parseAst(opts);
695
- const refIdents = findReferencedIdentifiers(ast);
696
- if (opts.sharedBindings && opts.sharedBindings.size > 0) {
697
- removeSharedDeclarations(ast, opts.sharedBindings);
698
- }
699
- const intendedSplitNodes = new Set(opts.splitTargets);
700
- const knownExportedIdents = /* @__PURE__ */ new Set();
701
- babel.traverse(ast, {
702
- Program: {
703
- enter(programPath) {
704
- const trackedNodesToSplitByType = {
705
- component: void 0,
706
- loader: void 0,
707
- pendingComponent: void 0,
708
- errorComponent: void 0,
709
- notFoundComponent: void 0
710
- };
711
- programPath.traverse({
712
- CallExpression: (path) => {
713
- if (!t.isIdentifier(path.node.callee)) {
714
- return;
715
- }
716
- if (!splittableCreateRouteFns.includes(path.node.callee.name)) {
717
- return;
718
- }
719
- function babelHandleVirtual(options) {
720
- if (t.isObjectExpression(options)) {
721
- options.properties.forEach((prop) => {
722
- if (t.isObjectProperty(prop)) {
723
- KNOWN_SPLIT_ROUTE_IDENTS.forEach((splitType) => {
724
- if (!t.isIdentifier(prop.key) || prop.key.name !== splitType) {
725
- return;
726
- }
727
- const value = prop.value;
728
- if (t.isIdentifier(value) && value.name === "undefined") {
729
- return;
730
- }
731
- let isExported = false;
732
- if (t.isIdentifier(value)) {
733
- isExported = hasExport(ast, value);
734
- if (isExported) {
735
- knownExportedIdents.add(value.name);
736
- }
737
- }
738
- if (isExported && t.isIdentifier(value)) {
739
- removeExports(ast, value);
740
- } else {
741
- const meta = SPLIT_NODES_CONFIG.get(splitType);
742
- trackedNodesToSplitByType[splitType] = {
743
- node: prop.value,
744
- meta
745
- };
746
- }
747
- });
748
- }
749
- });
750
- options.properties = [];
751
- }
752
- }
753
- if (t.isCallExpression(path.parentPath.node)) {
754
- const options = resolveIdentifier(
755
- path,
756
- path.parentPath.node.arguments[0]
757
- );
758
- babelHandleVirtual(options);
759
- } else if (t.isVariableDeclarator(path.parentPath.node)) {
760
- const caller = resolveIdentifier(path, path.parentPath.node.init);
761
- if (t.isCallExpression(caller)) {
762
- const options = resolveIdentifier(path, caller.arguments[0]);
763
- babelHandleVirtual(options);
764
- }
765
- }
766
- }
767
- });
768
- intendedSplitNodes.forEach((SPLIT_TYPE) => {
769
- const splitKey = trackedNodesToSplitByType[SPLIT_TYPE];
770
- if (!splitKey) {
771
- return;
772
- }
773
- let splitNode = splitKey.node;
774
- const splitMeta = { ...splitKey.meta, shouldRemoveNode: true };
775
- let originalIdentName;
776
- if (t.isIdentifier(splitNode)) {
777
- originalIdentName = splitNode.name;
778
- }
779
- while (t.isIdentifier(splitNode)) {
780
- const binding = programPath.scope.getBinding(splitNode.name);
781
- splitNode = binding?.path.node;
782
- }
783
- if (splitNode) {
784
- if (t.isFunctionDeclaration(splitNode)) {
785
- if (!splitNode.id) {
786
- throw new Error(
787
- `Function declaration for "${SPLIT_TYPE}" must have an identifier.`
788
- );
789
- }
790
- splitMeta.shouldRemoveNode = false;
791
- splitMeta.localExporterIdent = splitNode.id.name;
792
- } else if (t.isFunctionExpression(splitNode) || t.isArrowFunctionExpression(splitNode)) {
793
- programPath.pushContainer(
794
- "body",
795
- t.variableDeclaration("const", [
796
- t.variableDeclarator(
797
- t.identifier(splitMeta.localExporterIdent),
798
- splitNode
799
- )
800
- ])
801
- );
802
- } else if (t.isImportSpecifier(splitNode) || t.isImportDefaultSpecifier(splitNode)) {
803
- programPath.pushContainer(
804
- "body",
805
- t.variableDeclaration("const", [
806
- t.variableDeclarator(
807
- t.identifier(splitMeta.localExporterIdent),
808
- splitNode.local
809
- )
810
- ])
811
- );
812
- } else if (t.isVariableDeclarator(splitNode)) {
813
- if (t.isIdentifier(splitNode.id)) {
814
- splitMeta.localExporterIdent = splitNode.id.name;
815
- splitMeta.shouldRemoveNode = false;
816
- } else if (t.isObjectPattern(splitNode.id)) {
817
- if (originalIdentName) {
818
- splitMeta.localExporterIdent = originalIdentName;
819
- }
820
- splitMeta.shouldRemoveNode = false;
821
- } else {
822
- throw new Error(
823
- `Unexpected splitNode type ☝️: ${splitNode.type}`
824
- );
825
- }
826
- } else if (t.isCallExpression(splitNode)) {
827
- const outputSplitNodeCode = generateFromAst(splitNode).code;
828
- const splitNodeAst = babel.parse(outputSplitNodeCode);
829
- if (!splitNodeAst) {
830
- throw new Error(
831
- `Failed to parse the generated code for "${SPLIT_TYPE}" in the node type "${splitNode.type}"`
832
- );
833
- }
834
- const statement = splitNodeAst.program.body[0];
835
- if (!statement) {
836
- throw new Error(
837
- `Failed to parse the generated code for "${SPLIT_TYPE}" in the node type "${splitNode.type}" as no statement was found in the program body`
838
- );
839
- }
840
- if (t.isExpressionStatement(statement)) {
841
- const expression = statement.expression;
842
- programPath.pushContainer(
843
- "body",
844
- t.variableDeclaration("const", [
845
- t.variableDeclarator(
846
- t.identifier(splitMeta.localExporterIdent),
847
- expression
848
- )
849
- ])
850
- );
851
- } else {
852
- throw new Error(
853
- `Unexpected expression type encounter for "${SPLIT_TYPE}" in the node type "${splitNode.type}"`
854
- );
855
- }
856
- } else if (t.isConditionalExpression(splitNode)) {
857
- programPath.pushContainer(
858
- "body",
859
- t.variableDeclaration("const", [
860
- t.variableDeclarator(
861
- t.identifier(splitMeta.localExporterIdent),
862
- splitNode
863
- )
864
- ])
865
- );
866
- } else if (t.isTSAsExpression(splitNode)) {
867
- splitNode = splitNode.expression;
868
- programPath.pushContainer(
869
- "body",
870
- t.variableDeclaration("const", [
871
- t.variableDeclarator(
872
- t.identifier(splitMeta.localExporterIdent),
873
- splitNode
874
- )
875
- ])
876
- );
877
- } else if (t.isBooleanLiteral(splitNode)) {
878
- return;
879
- } else if (t.isNullLiteral(splitNode)) {
880
- return;
881
- } else {
882
- console.info("Unexpected splitNode type:", splitNode);
883
- throw new Error(`Unexpected splitNode type ☝️: ${splitNode.type}`);
884
- }
885
- }
886
- if (splitMeta.shouldRemoveNode) {
887
- programPath.node.body = programPath.node.body.filter((node) => {
888
- return node !== splitNode;
889
- });
890
- }
891
- programPath.pushContainer("body", [
892
- t.exportNamedDeclaration(null, [
893
- t.exportSpecifier(
894
- t.identifier(splitMeta.localExporterIdent),
895
- // local variable name
896
- t.identifier(splitMeta.exporterIdent)
897
- // as what name it should be exported as
898
- )
899
- ])
900
- ]);
901
- });
902
- programPath.traverse({
903
- ExportNamedDeclaration(path) {
904
- if (path.node.declaration) {
905
- if (t.isVariableDeclaration(path.node.declaration)) {
906
- const specifiers = path.node.declaration.declarations.flatMap(
907
- (decl) => {
908
- if (t.isIdentifier(decl.id)) {
909
- return [
910
- t.importSpecifier(
911
- t.identifier(decl.id.name),
912
- t.identifier(decl.id.name)
913
- )
914
- ];
915
- }
916
- if (t.isObjectPattern(decl.id)) {
917
- return collectIdentifiersFromPattern(decl.id).map(
918
- (name) => t.importSpecifier(
919
- t.identifier(name),
920
- t.identifier(name)
921
- )
922
- );
923
- }
924
- if (t.isArrayPattern(decl.id)) {
925
- return collectIdentifiersFromPattern(decl.id).map(
926
- (name) => t.importSpecifier(
927
- t.identifier(name),
928
- t.identifier(name)
929
- )
930
- );
931
- }
932
- return [];
933
- }
934
- );
935
- if (specifiers.length === 0) {
936
- path.remove();
937
- return;
938
- }
939
- const importDecl = t.importDeclaration(
940
- specifiers,
941
- t.stringLiteral(
942
- removeSplitSearchParamFromFilename(opts.filename)
943
- )
944
- );
945
- path.replaceWith(importDecl);
946
- path.traverse({
947
- Identifier(identPath) {
948
- if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") {
949
- refIdents.add(identPath);
950
- }
951
- }
952
- });
953
- }
954
- }
955
- }
956
- });
957
- if (opts.sharedBindings && opts.sharedBindings.size > 0) {
958
- const sharedImportSpecifiers = [...opts.sharedBindings].map(
959
- (name) => t.importSpecifier(t.identifier(name), t.identifier(name))
960
- );
961
- const sharedModuleUrl = addSharedSearchParamToFilename(
962
- removeSplitSearchParamFromFilename(opts.filename)
963
- );
964
- const [sharedImportPath] = programPath.unshiftContainer(
965
- "body",
966
- t.importDeclaration(
967
- sharedImportSpecifiers,
968
- t.stringLiteral(sharedModuleUrl)
969
- )
970
- );
971
- sharedImportPath.traverse({
972
- Identifier(identPath) {
973
- if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") {
974
- refIdents.add(identPath);
975
- }
976
- }
977
- });
978
- }
979
- }
980
- }
981
- });
982
- deadCodeElimination(ast, refIdents);
983
- {
984
- const locallyBound = /* @__PURE__ */ new Set();
985
- for (const stmt of ast.program.body) {
986
- collectLocalBindingsFromStatement(stmt, locallyBound);
987
- }
988
- ast.program.body = ast.program.body.filter((stmt) => {
989
- if (!t.isExpressionStatement(stmt)) return true;
990
- const refs = collectIdentifiersFromNode(stmt);
991
- return [...refs].some((name) => locallyBound.has(name));
992
- });
993
- }
994
- if (ast.program.body.length === 0) {
995
- ast.program.directives = [];
996
- }
997
- const result = generateFromAst(ast, {
998
- sourceMaps: true,
999
- sourceFileName: opts.filename,
1000
- filename: opts.filename
1001
- });
1002
- if (result.map) {
1003
- result.map.sourcesContent = [opts.code];
1004
- }
1005
- return result;
523
+ const ast = parseAst(opts);
524
+ const refIdents = findReferencedIdentifiers(ast);
525
+ if (opts.sharedBindings && opts.sharedBindings.size > 0) removeSharedDeclarations(ast, opts.sharedBindings);
526
+ const intendedSplitNodes = new Set(opts.splitTargets);
527
+ const knownExportedIdents = /* @__PURE__ */ new Set();
528
+ babel.traverse(ast, { Program: { enter(programPath) {
529
+ const trackedNodesToSplitByType = {
530
+ component: void 0,
531
+ loader: void 0,
532
+ pendingComponent: void 0,
533
+ errorComponent: void 0,
534
+ notFoundComponent: void 0
535
+ };
536
+ programPath.traverse({ CallExpression: (path) => {
537
+ if (!t.isIdentifier(path.node.callee)) return;
538
+ if (!splittableCreateRouteFns.includes(path.node.callee.name)) return;
539
+ function babelHandleVirtual(options) {
540
+ if (t.isObjectExpression(options)) {
541
+ options.properties.forEach((prop) => {
542
+ if (t.isObjectProperty(prop)) KNOWN_SPLIT_ROUTE_IDENTS.forEach((splitType) => {
543
+ if (!t.isIdentifier(prop.key) || prop.key.name !== splitType) return;
544
+ const value = prop.value;
545
+ if (t.isIdentifier(value) && value.name === "undefined") return;
546
+ let isExported = false;
547
+ if (t.isIdentifier(value)) {
548
+ isExported = hasExport(ast, value);
549
+ if (isExported) knownExportedIdents.add(value.name);
550
+ }
551
+ if (isExported && t.isIdentifier(value)) removeExports(ast, value);
552
+ else {
553
+ const meta = SPLIT_NODES_CONFIG.get(splitType);
554
+ trackedNodesToSplitByType[splitType] = {
555
+ node: prop.value,
556
+ meta
557
+ };
558
+ }
559
+ });
560
+ });
561
+ options.properties = [];
562
+ }
563
+ }
564
+ if (t.isCallExpression(path.parentPath.node)) babelHandleVirtual(resolveIdentifier(path, path.parentPath.node.arguments[0]));
565
+ else if (t.isVariableDeclarator(path.parentPath.node)) {
566
+ const caller = resolveIdentifier(path, path.parentPath.node.init);
567
+ if (t.isCallExpression(caller)) babelHandleVirtual(resolveIdentifier(path, caller.arguments[0]));
568
+ }
569
+ } });
570
+ intendedSplitNodes.forEach((SPLIT_TYPE) => {
571
+ const splitKey = trackedNodesToSplitByType[SPLIT_TYPE];
572
+ if (!splitKey) return;
573
+ let splitNode = splitKey.node;
574
+ const splitMeta = {
575
+ ...splitKey.meta,
576
+ shouldRemoveNode: true
577
+ };
578
+ let originalIdentName;
579
+ if (t.isIdentifier(splitNode)) originalIdentName = splitNode.name;
580
+ while (t.isIdentifier(splitNode)) splitNode = programPath.scope.getBinding(splitNode.name)?.path.node;
581
+ if (splitNode) if (t.isFunctionDeclaration(splitNode)) {
582
+ if (!splitNode.id) throw new Error(`Function declaration for "${SPLIT_TYPE}" must have an identifier.`);
583
+ splitMeta.shouldRemoveNode = false;
584
+ splitMeta.localExporterIdent = splitNode.id.name;
585
+ } else if (t.isFunctionExpression(splitNode) || t.isArrowFunctionExpression(splitNode)) programPath.pushContainer("body", t.variableDeclaration("const", [t.variableDeclarator(t.identifier(splitMeta.localExporterIdent), splitNode)]));
586
+ else if (t.isImportSpecifier(splitNode) || t.isImportDefaultSpecifier(splitNode)) programPath.pushContainer("body", t.variableDeclaration("const", [t.variableDeclarator(t.identifier(splitMeta.localExporterIdent), splitNode.local)]));
587
+ else if (t.isVariableDeclarator(splitNode)) if (t.isIdentifier(splitNode.id)) {
588
+ splitMeta.localExporterIdent = splitNode.id.name;
589
+ splitMeta.shouldRemoveNode = false;
590
+ } else if (t.isObjectPattern(splitNode.id)) {
591
+ if (originalIdentName) splitMeta.localExporterIdent = originalIdentName;
592
+ splitMeta.shouldRemoveNode = false;
593
+ } else throw new Error(`Unexpected splitNode type ☝️: ${splitNode.type}`);
594
+ else if (t.isCallExpression(splitNode)) {
595
+ const outputSplitNodeCode = generateFromAst(splitNode).code;
596
+ const splitNodeAst = babel.parse(outputSplitNodeCode);
597
+ if (!splitNodeAst) throw new Error(`Failed to parse the generated code for "${SPLIT_TYPE}" in the node type "${splitNode.type}"`);
598
+ const statement = splitNodeAst.program.body[0];
599
+ if (!statement) throw new Error(`Failed to parse the generated code for "${SPLIT_TYPE}" in the node type "${splitNode.type}" as no statement was found in the program body`);
600
+ if (t.isExpressionStatement(statement)) {
601
+ const expression = statement.expression;
602
+ programPath.pushContainer("body", t.variableDeclaration("const", [t.variableDeclarator(t.identifier(splitMeta.localExporterIdent), expression)]));
603
+ } else throw new Error(`Unexpected expression type encounter for "${SPLIT_TYPE}" in the node type "${splitNode.type}"`);
604
+ } else if (t.isConditionalExpression(splitNode)) programPath.pushContainer("body", t.variableDeclaration("const", [t.variableDeclarator(t.identifier(splitMeta.localExporterIdent), splitNode)]));
605
+ else if (t.isTSAsExpression(splitNode)) {
606
+ splitNode = splitNode.expression;
607
+ programPath.pushContainer("body", t.variableDeclaration("const", [t.variableDeclarator(t.identifier(splitMeta.localExporterIdent), splitNode)]));
608
+ } else if (t.isBooleanLiteral(splitNode)) return;
609
+ else if (t.isNullLiteral(splitNode)) return;
610
+ else {
611
+ console.info("Unexpected splitNode type:", splitNode);
612
+ throw new Error(`Unexpected splitNode type ☝️: ${splitNode.type}`);
613
+ }
614
+ if (splitMeta.shouldRemoveNode) programPath.node.body = programPath.node.body.filter((node) => {
615
+ return node !== splitNode;
616
+ });
617
+ programPath.pushContainer("body", [t.exportNamedDeclaration(null, [t.exportSpecifier(t.identifier(splitMeta.localExporterIdent), t.identifier(splitMeta.exporterIdent))])]);
618
+ });
619
+ programPath.traverse({ ExportNamedDeclaration(path) {
620
+ if (path.node.declaration) {
621
+ if (t.isVariableDeclaration(path.node.declaration)) {
622
+ const specifiers = path.node.declaration.declarations.flatMap((decl) => {
623
+ if (t.isIdentifier(decl.id)) return [t.importSpecifier(t.identifier(decl.id.name), t.identifier(decl.id.name))];
624
+ if (t.isObjectPattern(decl.id)) return collectIdentifiersFromPattern(decl.id).map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
625
+ if (t.isArrayPattern(decl.id)) return collectIdentifiersFromPattern(decl.id).map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
626
+ return [];
627
+ });
628
+ if (specifiers.length === 0) {
629
+ path.remove();
630
+ return;
631
+ }
632
+ const importDecl = t.importDeclaration(specifiers, t.stringLiteral(removeSplitSearchParamFromFilename(opts.filename)));
633
+ path.replaceWith(importDecl);
634
+ path.traverse({ Identifier(identPath) {
635
+ if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") refIdents.add(identPath);
636
+ } });
637
+ }
638
+ }
639
+ } });
640
+ if (opts.sharedBindings && opts.sharedBindings.size > 0) {
641
+ const sharedImportSpecifiers = [...opts.sharedBindings].map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
642
+ const sharedModuleUrl = addSharedSearchParamToFilename(removeSplitSearchParamFromFilename(opts.filename));
643
+ const [sharedImportPath] = programPath.unshiftContainer("body", t.importDeclaration(sharedImportSpecifiers, t.stringLiteral(sharedModuleUrl)));
644
+ sharedImportPath.traverse({ Identifier(identPath) {
645
+ if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") refIdents.add(identPath);
646
+ } });
647
+ }
648
+ } } });
649
+ deadCodeElimination(ast, refIdents);
650
+ {
651
+ const locallyBound = /* @__PURE__ */ new Set();
652
+ for (const stmt of ast.program.body) collectLocalBindingsFromStatement(stmt, locallyBound);
653
+ ast.program.body = ast.program.body.filter((stmt) => {
654
+ if (!t.isExpressionStatement(stmt)) return true;
655
+ return [...collectIdentifiersFromNode(stmt)].some((name) => locallyBound.has(name));
656
+ });
657
+ }
658
+ if (ast.program.body.length === 0) ast.program.directives = [];
659
+ const result = generateFromAst(ast, {
660
+ sourceMaps: true,
661
+ sourceFileName: opts.filename,
662
+ filename: opts.filename
663
+ });
664
+ if (result.map) result.map.sourcesContent = [opts.code];
665
+ return result;
1006
666
  }
667
+ /**
668
+ * Compile the shared virtual module (`?tsr-shared=1`).
669
+ * Keeps only shared binding declarations, their transitive dependencies,
670
+ * and imports they need. Exports all shared bindings.
671
+ */
1007
672
  function compileCodeSplitSharedRoute(opts) {
1008
- const ast = parseAst(opts);
1009
- const refIdents = findReferencedIdentifiers(ast);
1010
- const localBindings = /* @__PURE__ */ new Set();
1011
- for (const node of ast.program.body) {
1012
- collectLocalBindingsFromStatement(node, localBindings);
1013
- }
1014
- localBindings.delete("Route");
1015
- const declMap = buildDeclarationMap(ast);
1016
- const depGraph = buildDependencyGraph(declMap, localBindings);
1017
- const keepBindings = new Set(opts.sharedBindings);
1018
- keepBindings.delete("Route");
1019
- expandTransitively(keepBindings, depGraph);
1020
- ast.program.body = ast.program.body.filter((stmt) => {
1021
- if (t.isImportDeclaration(stmt)) return true;
1022
- const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
1023
- if (t.isVariableDeclaration(decl)) {
1024
- decl.declarations = decl.declarations.filter((declarator) => {
1025
- const names = collectIdentifiersFromPattern(declarator.id);
1026
- return names.some((n) => keepBindings.has(n));
1027
- });
1028
- if (decl.declarations.length === 0) return false;
1029
- if (t.isExportNamedDeclaration(stmt) && stmt.declaration) {
1030
- return true;
1031
- }
1032
- return true;
1033
- } else if (t.isFunctionDeclaration(decl) && decl.id) {
1034
- return keepBindings.has(decl.id.name);
1035
- } else if (t.isClassDeclaration(decl) && decl.id) {
1036
- return keepBindings.has(decl.id.name);
1037
- }
1038
- return false;
1039
- });
1040
- ast.program.body = ast.program.body.map((stmt) => {
1041
- if (t.isExportNamedDeclaration(stmt) && stmt.declaration) {
1042
- return stmt.declaration;
1043
- }
1044
- return stmt;
1045
- });
1046
- const exportNames = [...opts.sharedBindings].sort(
1047
- (a, b) => a.localeCompare(b)
1048
- );
1049
- const exportSpecifiers = exportNames.map(
1050
- (name) => t.exportSpecifier(t.identifier(name), t.identifier(name))
1051
- );
1052
- if (exportSpecifiers.length > 0) {
1053
- const exportDecl = t.exportNamedDeclaration(null, exportSpecifiers);
1054
- ast.program.body.push(exportDecl);
1055
- babel.traverse(ast, {
1056
- Program(programPath) {
1057
- const bodyPaths = programPath.get("body");
1058
- const last = bodyPaths[bodyPaths.length - 1];
1059
- if (last && last.isExportNamedDeclaration()) {
1060
- last.traverse({
1061
- Identifier(identPath) {
1062
- if (identPath.parentPath.isExportSpecifier() && identPath.key === "local") {
1063
- refIdents.add(identPath);
1064
- }
1065
- }
1066
- });
1067
- }
1068
- programPath.stop();
1069
- }
1070
- });
1071
- }
1072
- deadCodeElimination(ast, refIdents);
1073
- if (ast.program.body.length === 0) {
1074
- ast.program.directives = [];
1075
- }
1076
- const result = generateFromAst(ast, {
1077
- sourceMaps: true,
1078
- sourceFileName: opts.filename,
1079
- filename: opts.filename
1080
- });
1081
- if (result.map) {
1082
- result.map.sourcesContent = [opts.code];
1083
- }
1084
- return result;
673
+ const ast = parseAst(opts);
674
+ const refIdents = findReferencedIdentifiers(ast);
675
+ const localBindings = /* @__PURE__ */ new Set();
676
+ for (const node of ast.program.body) collectLocalBindingsFromStatement(node, localBindings);
677
+ localBindings.delete("Route");
678
+ const depGraph = buildDependencyGraph(buildDeclarationMap(ast), localBindings);
679
+ const keepBindings = new Set(opts.sharedBindings);
680
+ keepBindings.delete("Route");
681
+ expandTransitively(keepBindings, depGraph);
682
+ ast.program.body = ast.program.body.filter((stmt) => {
683
+ if (t.isImportDeclaration(stmt)) return true;
684
+ const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
685
+ if (t.isVariableDeclaration(decl)) {
686
+ decl.declarations = decl.declarations.filter((declarator) => {
687
+ return collectIdentifiersFromPattern(declarator.id).some((n) => keepBindings.has(n));
688
+ });
689
+ if (decl.declarations.length === 0) return false;
690
+ if (t.isExportNamedDeclaration(stmt) && stmt.declaration) return true;
691
+ return true;
692
+ } else if (t.isFunctionDeclaration(decl) && decl.id) return keepBindings.has(decl.id.name);
693
+ else if (t.isClassDeclaration(decl) && decl.id) return keepBindings.has(decl.id.name);
694
+ return false;
695
+ });
696
+ ast.program.body = ast.program.body.map((stmt) => {
697
+ if (t.isExportNamedDeclaration(stmt) && stmt.declaration) return stmt.declaration;
698
+ return stmt;
699
+ });
700
+ const exportSpecifiers = [...opts.sharedBindings].sort((a, b) => a.localeCompare(b)).map((name) => t.exportSpecifier(t.identifier(name), t.identifier(name)));
701
+ if (exportSpecifiers.length > 0) {
702
+ const exportDecl = t.exportNamedDeclaration(null, exportSpecifiers);
703
+ ast.program.body.push(exportDecl);
704
+ babel.traverse(ast, { Program(programPath) {
705
+ const bodyPaths = programPath.get("body");
706
+ const last = bodyPaths[bodyPaths.length - 1];
707
+ if (last && last.isExportNamedDeclaration()) last.traverse({ Identifier(identPath) {
708
+ if (identPath.parentPath.isExportSpecifier() && identPath.key === "local") refIdents.add(identPath);
709
+ } });
710
+ programPath.stop();
711
+ } });
712
+ }
713
+ deadCodeElimination(ast, refIdents);
714
+ if (ast.program.body.length === 0) ast.program.directives = [];
715
+ const result = generateFromAst(ast, {
716
+ sourceMaps: true,
717
+ sourceFileName: opts.filename,
718
+ filename: opts.filename
719
+ });
720
+ if (result.map) result.map.sourcesContent = [opts.code];
721
+ return result;
1085
722
  }
723
+ /**
724
+ * This function should read get the options from by searching for the key `codeSplitGroupings`
725
+ * on createFileRoute and return it's values if it exists, else return undefined
726
+ */
1086
727
  function detectCodeSplitGroupingsFromRoute(opts) {
1087
- const ast = parseAst(opts);
1088
- let codeSplitGroupings = void 0;
1089
- babel.traverse(ast, {
1090
- Program: {
1091
- enter(programPath) {
1092
- programPath.traverse({
1093
- CallExpression(path) {
1094
- if (!t.isIdentifier(path.node.callee)) {
1095
- return;
1096
- }
1097
- if (!(path.node.callee.name === "createRoute" || path.node.callee.name === "createFileRoute")) {
1098
- return;
1099
- }
1100
- function babelHandleSplittingGroups(routeOptions) {
1101
- if (t.isObjectExpression(routeOptions)) {
1102
- routeOptions.properties.forEach((prop) => {
1103
- if (t.isObjectProperty(prop)) {
1104
- if (t.isIdentifier(prop.key)) {
1105
- if (prop.key.name === "codeSplitGroupings") {
1106
- const value = prop.value;
1107
- if (t.isArrayExpression(value)) {
1108
- codeSplitGroupings = value.elements.map((group) => {
1109
- if (t.isArrayExpression(group)) {
1110
- return group.elements.map((node) => {
1111
- if (!t.isStringLiteral(node)) {
1112
- throw new Error(
1113
- "You must provide a string literal for the codeSplitGroupings"
1114
- );
1115
- }
1116
- return node.value;
1117
- });
1118
- }
1119
- throw new Error(
1120
- "You must provide arrays with codeSplitGroupings options."
1121
- );
1122
- });
1123
- } else {
1124
- throw new Error(
1125
- "You must provide an array of arrays for the codeSplitGroupings."
1126
- );
1127
- }
1128
- }
1129
- }
1130
- }
1131
- });
1132
- }
1133
- }
1134
- if (t.isCallExpression(path.parentPath.node)) {
1135
- const options = resolveIdentifier(
1136
- path,
1137
- path.parentPath.node.arguments[0]
1138
- );
1139
- babelHandleSplittingGroups(options);
1140
- } else if (t.isVariableDeclarator(path.parentPath.node)) {
1141
- const caller = resolveIdentifier(path, path.parentPath.node.init);
1142
- if (t.isCallExpression(caller)) {
1143
- const options = resolveIdentifier(path, caller.arguments[0]);
1144
- babelHandleSplittingGroups(options);
1145
- }
1146
- }
1147
- }
1148
- });
1149
- }
1150
- }
1151
- });
1152
- return { groupings: codeSplitGroupings };
728
+ const ast = parseAst(opts);
729
+ let codeSplitGroupings = void 0;
730
+ babel.traverse(ast, { Program: { enter(programPath) {
731
+ programPath.traverse({ CallExpression(path) {
732
+ if (!t.isIdentifier(path.node.callee)) return;
733
+ if (!(path.node.callee.name === "createRoute" || path.node.callee.name === "createFileRoute")) return;
734
+ function babelHandleSplittingGroups(routeOptions) {
735
+ if (t.isObjectExpression(routeOptions)) routeOptions.properties.forEach((prop) => {
736
+ if (t.isObjectProperty(prop)) {
737
+ if (t.isIdentifier(prop.key)) {
738
+ if (prop.key.name === "codeSplitGroupings") {
739
+ const value = prop.value;
740
+ if (t.isArrayExpression(value)) codeSplitGroupings = value.elements.map((group) => {
741
+ if (t.isArrayExpression(group)) return group.elements.map((node) => {
742
+ if (!t.isStringLiteral(node)) throw new Error("You must provide a string literal for the codeSplitGroupings");
743
+ return node.value;
744
+ });
745
+ throw new Error("You must provide arrays with codeSplitGroupings options.");
746
+ });
747
+ else throw new Error("You must provide an array of arrays for the codeSplitGroupings.");
748
+ }
749
+ }
750
+ }
751
+ });
752
+ }
753
+ if (t.isCallExpression(path.parentPath.node)) babelHandleSplittingGroups(resolveIdentifier(path, path.parentPath.node.arguments[0]));
754
+ else if (t.isVariableDeclarator(path.parentPath.node)) {
755
+ const caller = resolveIdentifier(path, path.parentPath.node.init);
756
+ if (t.isCallExpression(caller)) babelHandleSplittingGroups(resolveIdentifier(path, caller.arguments[0]));
757
+ }
758
+ } });
759
+ } } });
760
+ return { groupings: codeSplitGroupings };
1153
761
  }
1154
762
  function createNotExportableMessage(filename, idents) {
1155
- const list = Array.from(idents).map((d) => `- ${d}`);
1156
- const message = [
1157
- `[tanstack-router] These exports from "${filename}" will not be code-split and will increase your bundle size:`,
1158
- ...list,
1159
- "For the best optimization, these items should either have their export statements removed, or be imported from another location that is not a route file."
1160
- ].join("\n");
1161
- return message;
763
+ const list = Array.from(idents).map((d) => `- ${d}`);
764
+ return [
765
+ `[tanstack-router] These exports from "${filename}" will not be code-split and will increase your bundle size:`,
766
+ ...list,
767
+ "For the best optimization, these items should either have their export statements removed, or be imported from another location that is not a route file."
768
+ ].join("\n");
1162
769
  }
1163
770
  function getImportSpecifierAndPathFromLocalName(programPath, name) {
1164
- let specifier = null;
1165
- let path = null;
1166
- programPath.traverse({
1167
- ImportDeclaration(importPath) {
1168
- const found = importPath.node.specifiers.find(
1169
- (targetSpecifier) => targetSpecifier.local.name === name
1170
- );
1171
- if (found) {
1172
- specifier = found;
1173
- path = importPath.node.source.value;
1174
- }
1175
- }
1176
- });
1177
- return { specifier, path };
771
+ let specifier = null;
772
+ let path = null;
773
+ programPath.traverse({ ImportDeclaration(importPath) {
774
+ const found = importPath.node.specifiers.find((targetSpecifier) => targetSpecifier.local.name === name);
775
+ if (found) {
776
+ specifier = found;
777
+ path = importPath.node.source.value;
778
+ }
779
+ } });
780
+ return {
781
+ specifier,
782
+ path
783
+ };
1178
784
  }
785
+ /**
786
+ * Recursively collects all identifier names from a destructuring pattern
787
+ * (ObjectPattern, ArrayPattern, AssignmentPattern, RestElement).
788
+ */
1179
789
  function collectIdentifiersFromPattern(node) {
1180
- if (!node) {
1181
- return [];
1182
- }
1183
- if (t.isIdentifier(node)) {
1184
- return [node.name];
1185
- }
1186
- if (t.isAssignmentPattern(node)) {
1187
- return collectIdentifiersFromPattern(node.left);
1188
- }
1189
- if (t.isRestElement(node)) {
1190
- return collectIdentifiersFromPattern(node.argument);
1191
- }
1192
- if (t.isObjectPattern(node)) {
1193
- return node.properties.flatMap((prop) => {
1194
- if (t.isObjectProperty(prop)) {
1195
- return collectIdentifiersFromPattern(prop.value);
1196
- }
1197
- if (t.isRestElement(prop)) {
1198
- return collectIdentifiersFromPattern(prop.argument);
1199
- }
1200
- return [];
1201
- });
1202
- }
1203
- if (t.isArrayPattern(node)) {
1204
- return node.elements.flatMap(
1205
- (element) => collectIdentifiersFromPattern(element)
1206
- );
1207
- }
1208
- return [];
790
+ if (!node) return [];
791
+ if (t.isIdentifier(node)) return [node.name];
792
+ if (t.isAssignmentPattern(node)) return collectIdentifiersFromPattern(node.left);
793
+ if (t.isRestElement(node)) return collectIdentifiersFromPattern(node.argument);
794
+ if (t.isObjectPattern(node)) return node.properties.flatMap((prop) => {
795
+ if (t.isObjectProperty(prop)) return collectIdentifiersFromPattern(prop.value);
796
+ if (t.isRestElement(prop)) return collectIdentifiersFromPattern(prop.argument);
797
+ return [];
798
+ });
799
+ if (t.isArrayPattern(node)) return node.elements.flatMap((element) => collectIdentifiersFromPattern(element));
800
+ return [];
1209
801
  }
1210
802
  function resolveIdentifier(path, node) {
1211
- if (t.isIdentifier(node)) {
1212
- const binding = path.scope.getBinding(node.name);
1213
- if (binding) {
1214
- const declarator = binding.path.node;
1215
- if (t.isObjectExpression(declarator.init)) {
1216
- return declarator.init;
1217
- } else if (t.isFunctionDeclaration(declarator.init)) {
1218
- return declarator.init;
1219
- }
1220
- }
1221
- return void 0;
1222
- }
1223
- return node;
803
+ if (t.isIdentifier(node)) {
804
+ const binding = path.scope.getBinding(node.name);
805
+ if (binding) {
806
+ const declarator = binding.path.node;
807
+ if (t.isObjectExpression(declarator.init)) return declarator.init;
808
+ else if (t.isFunctionDeclaration(declarator.init)) return declarator.init;
809
+ }
810
+ return;
811
+ }
812
+ return node;
1224
813
  }
1225
814
  function removeIdentifierLiteral(path, node) {
1226
- const binding = path.scope.getBinding(node.name);
1227
- if (binding) {
1228
- if (t.isVariableDeclarator(binding.path.node) && t.isObjectPattern(binding.path.node.id)) {
1229
- const objectPattern = binding.path.node.id;
1230
- objectPattern.properties = objectPattern.properties.filter((prop) => {
1231
- if (!t.isObjectProperty(prop)) {
1232
- return true;
1233
- }
1234
- if (t.isIdentifier(prop.value) && prop.value.name === node.name) {
1235
- return false;
1236
- }
1237
- if (t.isAssignmentPattern(prop.value) && t.isIdentifier(prop.value.left) && prop.value.left.name === node.name) {
1238
- return false;
1239
- }
1240
- return true;
1241
- });
1242
- if (objectPattern.properties.length === 0) {
1243
- binding.path.remove();
1244
- }
1245
- return;
1246
- }
1247
- binding.path.remove();
1248
- }
815
+ const binding = path.scope.getBinding(node.name);
816
+ if (binding) {
817
+ if (t.isVariableDeclarator(binding.path.node) && t.isObjectPattern(binding.path.node.id)) {
818
+ const objectPattern = binding.path.node.id;
819
+ objectPattern.properties = objectPattern.properties.filter((prop) => {
820
+ if (!t.isObjectProperty(prop)) return true;
821
+ if (t.isIdentifier(prop.value) && prop.value.name === node.name) return false;
822
+ if (t.isAssignmentPattern(prop.value) && t.isIdentifier(prop.value.left) && prop.value.left.name === node.name) return false;
823
+ return true;
824
+ });
825
+ if (objectPattern.properties.length === 0) binding.path.remove();
826
+ return;
827
+ }
828
+ binding.path.remove();
829
+ }
1249
830
  }
1250
831
  function hasExport(ast, node) {
1251
- let found = false;
1252
- babel.traverse(ast, {
1253
- ExportNamedDeclaration(path) {
1254
- if (path.node.declaration) {
1255
- if (t.isVariableDeclaration(path.node.declaration)) {
1256
- path.node.declaration.declarations.forEach((decl) => {
1257
- if (t.isVariableDeclarator(decl)) {
1258
- if (t.isIdentifier(decl.id)) {
1259
- if (decl.id.name === node.name) {
1260
- found = true;
1261
- }
1262
- } else if (t.isObjectPattern(decl.id) || t.isArrayPattern(decl.id)) {
1263
- const names = collectIdentifiersFromPattern(decl.id);
1264
- if (names.includes(node.name)) {
1265
- found = true;
1266
- }
1267
- }
1268
- }
1269
- });
1270
- }
1271
- if (t.isFunctionDeclaration(path.node.declaration)) {
1272
- if (t.isIdentifier(path.node.declaration.id)) {
1273
- if (path.node.declaration.id.name === node.name) {
1274
- found = true;
1275
- }
1276
- }
1277
- }
1278
- }
1279
- },
1280
- ExportDefaultDeclaration(path) {
1281
- if (t.isIdentifier(path.node.declaration)) {
1282
- if (path.node.declaration.name === node.name) {
1283
- found = true;
1284
- }
1285
- }
1286
- if (t.isFunctionDeclaration(path.node.declaration)) {
1287
- if (t.isIdentifier(path.node.declaration.id)) {
1288
- if (path.node.declaration.id.name === node.name) {
1289
- found = true;
1290
- }
1291
- }
1292
- }
1293
- }
1294
- });
1295
- return found;
832
+ let found = false;
833
+ babel.traverse(ast, {
834
+ ExportNamedDeclaration(path) {
835
+ if (path.node.declaration) {
836
+ if (t.isVariableDeclaration(path.node.declaration)) path.node.declaration.declarations.forEach((decl) => {
837
+ if (t.isVariableDeclarator(decl)) {
838
+ if (t.isIdentifier(decl.id)) {
839
+ if (decl.id.name === node.name) found = true;
840
+ } else if (t.isObjectPattern(decl.id) || t.isArrayPattern(decl.id)) {
841
+ if (collectIdentifiersFromPattern(decl.id).includes(node.name)) found = true;
842
+ }
843
+ }
844
+ });
845
+ if (t.isFunctionDeclaration(path.node.declaration)) {
846
+ if (t.isIdentifier(path.node.declaration.id)) {
847
+ if (path.node.declaration.id.name === node.name) found = true;
848
+ }
849
+ }
850
+ }
851
+ },
852
+ ExportDefaultDeclaration(path) {
853
+ if (t.isIdentifier(path.node.declaration)) {
854
+ if (path.node.declaration.name === node.name) found = true;
855
+ }
856
+ if (t.isFunctionDeclaration(path.node.declaration)) {
857
+ if (t.isIdentifier(path.node.declaration.id)) {
858
+ if (path.node.declaration.id.name === node.name) found = true;
859
+ }
860
+ }
861
+ }
862
+ });
863
+ return found;
1296
864
  }
1297
865
  function removeExports(ast, node) {
1298
- let removed = false;
1299
- babel.traverse(ast, {
1300
- ExportNamedDeclaration(path) {
1301
- if (path.node.declaration) {
1302
- if (t.isVariableDeclaration(path.node.declaration)) {
1303
- path.node.declaration.declarations.forEach((decl) => {
1304
- if (t.isVariableDeclarator(decl)) {
1305
- if (t.isIdentifier(decl.id)) {
1306
- if (decl.id.name === node.name) {
1307
- path.remove();
1308
- removed = true;
1309
- }
1310
- } else if (t.isObjectPattern(decl.id) || t.isArrayPattern(decl.id)) {
1311
- const names = collectIdentifiersFromPattern(decl.id);
1312
- if (names.includes(node.name)) {
1313
- path.remove();
1314
- removed = true;
1315
- }
1316
- }
1317
- }
1318
- });
1319
- } else if (t.isFunctionDeclaration(path.node.declaration)) {
1320
- if (t.isIdentifier(path.node.declaration.id)) {
1321
- if (path.node.declaration.id.name === node.name) {
1322
- path.remove();
1323
- removed = true;
1324
- }
1325
- }
1326
- }
1327
- }
1328
- },
1329
- ExportDefaultDeclaration(path) {
1330
- if (t.isIdentifier(path.node.declaration)) {
1331
- if (path.node.declaration.name === node.name) {
1332
- path.remove();
1333
- removed = true;
1334
- }
1335
- } else if (t.isFunctionDeclaration(path.node.declaration)) {
1336
- if (t.isIdentifier(path.node.declaration.id)) {
1337
- if (path.node.declaration.id.name === node.name) {
1338
- path.remove();
1339
- removed = true;
1340
- }
1341
- }
1342
- }
1343
- }
1344
- });
1345
- return removed;
866
+ let removed = false;
867
+ babel.traverse(ast, {
868
+ ExportNamedDeclaration(path) {
869
+ if (path.node.declaration) {
870
+ if (t.isVariableDeclaration(path.node.declaration)) path.node.declaration.declarations.forEach((decl) => {
871
+ if (t.isVariableDeclarator(decl)) {
872
+ if (t.isIdentifier(decl.id)) {
873
+ if (decl.id.name === node.name) {
874
+ path.remove();
875
+ removed = true;
876
+ }
877
+ } else if (t.isObjectPattern(decl.id) || t.isArrayPattern(decl.id)) {
878
+ if (collectIdentifiersFromPattern(decl.id).includes(node.name)) {
879
+ path.remove();
880
+ removed = true;
881
+ }
882
+ }
883
+ }
884
+ });
885
+ else if (t.isFunctionDeclaration(path.node.declaration)) {
886
+ if (t.isIdentifier(path.node.declaration.id)) {
887
+ if (path.node.declaration.id.name === node.name) {
888
+ path.remove();
889
+ removed = true;
890
+ }
891
+ }
892
+ }
893
+ }
894
+ },
895
+ ExportDefaultDeclaration(path) {
896
+ if (t.isIdentifier(path.node.declaration)) {
897
+ if (path.node.declaration.name === node.name) {
898
+ path.remove();
899
+ removed = true;
900
+ }
901
+ } else if (t.isFunctionDeclaration(path.node.declaration)) {
902
+ if (t.isIdentifier(path.node.declaration.id)) {
903
+ if (path.node.declaration.id.name === node.name) {
904
+ path.remove();
905
+ removed = true;
906
+ }
907
+ }
908
+ }
909
+ }
910
+ });
911
+ return removed;
1346
912
  }
1347
- export {
1348
- addSharedSearchParamToFilename,
1349
- buildDeclarationMap,
1350
- buildDependencyGraph,
1351
- collectIdentifiersFromNode,
1352
- collectLocalBindingsFromStatement,
1353
- collectModuleLevelRefsFromNode,
1354
- compileCodeSplitReferenceRoute,
1355
- compileCodeSplitSharedRoute,
1356
- compileCodeSplitVirtualRoute,
1357
- computeSharedBindings,
1358
- detectCodeSplitGroupingsFromRoute,
1359
- expandDestructuredDeclarations,
1360
- expandSharedDestructuredDeclarators,
1361
- expandTransitively,
1362
- removeBindingsDependingOnRoute
1363
- };
1364
- //# sourceMappingURL=compilers.js.map
913
+ //#endregion
914
+ export { compileCodeSplitReferenceRoute, compileCodeSplitSharedRoute, compileCodeSplitVirtualRoute, computeSharedBindings, detectCodeSplitGroupingsFromRoute };
915
+
916
+ //# sourceMappingURL=compilers.js.map