@tanstack/router-plugin 1.159.10 → 1.159.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.
- package/dist/cjs/core/code-splitter/compilers.cjs +571 -6
- package/dist/cjs/core/code-splitter/compilers.cjs.map +1 -1
- package/dist/cjs/core/code-splitter/compilers.d.cts +82 -0
- package/dist/cjs/core/constants.cjs +2 -0
- package/dist/cjs/core/constants.cjs.map +1 -1
- package/dist/cjs/core/constants.d.cts +1 -0
- package/dist/cjs/core/router-code-splitter-plugin.cjs +62 -3
- package/dist/cjs/core/router-code-splitter-plugin.cjs.map +1 -1
- package/dist/esm/core/code-splitter/compilers.d.ts +82 -0
- package/dist/esm/core/code-splitter/compilers.js +573 -8
- package/dist/esm/core/code-splitter/compilers.js.map +1 -1
- package/dist/esm/core/constants.d.ts +1 -0
- package/dist/esm/core/constants.js +2 -0
- package/dist/esm/core/constants.js.map +1 -1
- package/dist/esm/core/router-code-splitter-plugin.js +64 -5
- package/dist/esm/core/router-code-splitter-plugin.js.map +1 -1
- package/package.json +3 -3
- package/src/core/code-splitter/compilers.ts +919 -7
- package/src/core/constants.ts +1 -0
- package/src/core/router-code-splitter-plugin.ts +78 -1
|
@@ -2,7 +2,7 @@ import * as t from "@babel/types";
|
|
|
2
2
|
import babel from "@babel/core";
|
|
3
3
|
import * as template from "@babel/template";
|
|
4
4
|
import { parseAst, findReferencedIdentifiers, deadCodeElimination, generateFromAst } from "@tanstack/router-utils";
|
|
5
|
-
import { tsrSplit } from "../constants.js";
|
|
5
|
+
import { tsrShared, tsrSplit } from "../constants.js";
|
|
6
6
|
import { routeHmrStatement } from "../route-hmr-statement.js";
|
|
7
7
|
import { createIdentifier } from "./path-ids.js";
|
|
8
8
|
import { getFrameworkOptions } from "./framework-options.js";
|
|
@@ -85,6 +85,10 @@ function removeSplitSearchParamFromFilename(filename) {
|
|
|
85
85
|
const [bareFilename] = filename.split("?");
|
|
86
86
|
return bareFilename;
|
|
87
87
|
}
|
|
88
|
+
function addSharedSearchParamToFilename(filename) {
|
|
89
|
+
const [bareFilename] = filename.split("?");
|
|
90
|
+
return `${bareFilename}?${tsrShared}=1`;
|
|
91
|
+
}
|
|
88
92
|
const splittableCreateRouteFns = ["createFileRoute"];
|
|
89
93
|
const unsplittableCreateRouteFns = [
|
|
90
94
|
"createRootRoute",
|
|
@@ -94,6 +98,304 @@ const allCreateRouteFns = [
|
|
|
94
98
|
...splittableCreateRouteFns,
|
|
95
99
|
...unsplittableCreateRouteFns
|
|
96
100
|
];
|
|
101
|
+
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;
|
|
139
|
+
}
|
|
140
|
+
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;
|
|
157
|
+
}
|
|
158
|
+
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;
|
|
170
|
+
}
|
|
171
|
+
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;
|
|
253
|
+
}
|
|
254
|
+
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
|
+
}
|
|
275
|
+
}
|
|
276
|
+
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
|
+
}
|
|
289
|
+
}
|
|
290
|
+
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;
|
|
297
|
+
}
|
|
298
|
+
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
|
+
}
|
|
314
|
+
}
|
|
315
|
+
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
|
+
}
|
|
344
|
+
}
|
|
345
|
+
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
|
+
}
|
|
361
|
+
}
|
|
362
|
+
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;
|
|
381
|
+
}
|
|
382
|
+
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
|
+
});
|
|
398
|
+
}
|
|
97
399
|
function compileCodeSplitReferenceRoute(opts) {
|
|
98
400
|
const ast = parseAst(opts);
|
|
99
401
|
const refIdents = findReferencedIdentifiers(ast);
|
|
@@ -110,6 +412,7 @@ function compileCodeSplitReferenceRoute(opts) {
|
|
|
110
412
|
let createRouteFn;
|
|
111
413
|
let modified = false;
|
|
112
414
|
let hmrAdded = false;
|
|
415
|
+
let sharedExportedNames;
|
|
113
416
|
babel.traverse(ast, {
|
|
114
417
|
Program: {
|
|
115
418
|
enter(programPath) {
|
|
@@ -305,6 +608,44 @@ function compileCodeSplitReferenceRoute(opts) {
|
|
|
305
608
|
}
|
|
306
609
|
});
|
|
307
610
|
}
|
|
611
|
+
if (opts.sharedBindings && opts.sharedBindings.size > 0) {
|
|
612
|
+
sharedExportedNames = findExportedSharedBindings(
|
|
613
|
+
ast,
|
|
614
|
+
opts.sharedBindings
|
|
615
|
+
);
|
|
616
|
+
removeSharedDeclarations(ast, opts.sharedBindings);
|
|
617
|
+
const sharedModuleUrl = addSharedSearchParamToFilename(opts.filename);
|
|
618
|
+
const sharedImportSpecifiers = [...opts.sharedBindings].map(
|
|
619
|
+
(name) => t.importSpecifier(t.identifier(name), t.identifier(name))
|
|
620
|
+
);
|
|
621
|
+
const [sharedImportPath] = programPath.unshiftContainer(
|
|
622
|
+
"body",
|
|
623
|
+
t.importDeclaration(
|
|
624
|
+
sharedImportSpecifiers,
|
|
625
|
+
t.stringLiteral(sharedModuleUrl)
|
|
626
|
+
)
|
|
627
|
+
);
|
|
628
|
+
sharedImportPath.traverse({
|
|
629
|
+
Identifier(identPath) {
|
|
630
|
+
if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") {
|
|
631
|
+
refIdents.add(identPath);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
if (sharedExportedNames.size > 0) {
|
|
636
|
+
const reExportSpecifiers = [...sharedExportedNames].map(
|
|
637
|
+
(name) => t.exportSpecifier(t.identifier(name), t.identifier(name))
|
|
638
|
+
);
|
|
639
|
+
programPath.pushContainer(
|
|
640
|
+
"body",
|
|
641
|
+
t.exportNamedDeclaration(
|
|
642
|
+
null,
|
|
643
|
+
reExportSpecifiers,
|
|
644
|
+
t.stringLiteral(sharedModuleUrl)
|
|
645
|
+
)
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
308
649
|
}
|
|
309
650
|
}
|
|
310
651
|
});
|
|
@@ -334,6 +675,9 @@ function compileCodeSplitReferenceRoute(opts) {
|
|
|
334
675
|
function compileCodeSplitVirtualRoute(opts) {
|
|
335
676
|
const ast = parseAst(opts);
|
|
336
677
|
const refIdents = findReferencedIdentifiers(ast);
|
|
678
|
+
if (opts.sharedBindings && opts.sharedBindings.size > 0) {
|
|
679
|
+
removeSharedDeclarations(ast, opts.sharedBindings);
|
|
680
|
+
}
|
|
337
681
|
const intendedSplitNodes = new Set(opts.splitTargets);
|
|
338
682
|
const knownExportedIdents = /* @__PURE__ */ new Set();
|
|
339
683
|
babel.traverse(ast, {
|
|
@@ -410,6 +754,10 @@ function compileCodeSplitVirtualRoute(opts) {
|
|
|
410
754
|
}
|
|
411
755
|
let splitNode = splitKey.node;
|
|
412
756
|
const splitMeta = { ...splitKey.meta, shouldRemoveNode: true };
|
|
757
|
+
let originalIdentName;
|
|
758
|
+
if (t.isIdentifier(splitNode)) {
|
|
759
|
+
originalIdentName = splitNode.name;
|
|
760
|
+
}
|
|
413
761
|
while (t.isIdentifier(splitNode)) {
|
|
414
762
|
const binding = programPath.scope.getBinding(splitNode.name);
|
|
415
763
|
splitNode = binding?.path.node;
|
|
@@ -447,6 +795,11 @@ function compileCodeSplitVirtualRoute(opts) {
|
|
|
447
795
|
if (t.isIdentifier(splitNode.id)) {
|
|
448
796
|
splitMeta.localExporterIdent = splitNode.id.name;
|
|
449
797
|
splitMeta.shouldRemoveNode = false;
|
|
798
|
+
} else if (t.isObjectPattern(splitNode.id)) {
|
|
799
|
+
if (originalIdentName) {
|
|
800
|
+
splitMeta.localExporterIdent = originalIdentName;
|
|
801
|
+
}
|
|
802
|
+
splitMeta.shouldRemoveNode = false;
|
|
450
803
|
} else {
|
|
451
804
|
throw new Error(
|
|
452
805
|
`Unexpected splitNode type ☝️: ${splitNode.type}`
|
|
@@ -532,13 +885,41 @@ function compileCodeSplitVirtualRoute(opts) {
|
|
|
532
885
|
ExportNamedDeclaration(path) {
|
|
533
886
|
if (path.node.declaration) {
|
|
534
887
|
if (t.isVariableDeclaration(path.node.declaration)) {
|
|
888
|
+
const specifiers = path.node.declaration.declarations.flatMap(
|
|
889
|
+
(decl) => {
|
|
890
|
+
if (t.isIdentifier(decl.id)) {
|
|
891
|
+
return [
|
|
892
|
+
t.importSpecifier(
|
|
893
|
+
t.identifier(decl.id.name),
|
|
894
|
+
t.identifier(decl.id.name)
|
|
895
|
+
)
|
|
896
|
+
];
|
|
897
|
+
}
|
|
898
|
+
if (t.isObjectPattern(decl.id)) {
|
|
899
|
+
return collectIdentifiersFromPattern(decl.id).map(
|
|
900
|
+
(name) => t.importSpecifier(
|
|
901
|
+
t.identifier(name),
|
|
902
|
+
t.identifier(name)
|
|
903
|
+
)
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
if (t.isArrayPattern(decl.id)) {
|
|
907
|
+
return collectIdentifiersFromPattern(decl.id).map(
|
|
908
|
+
(name) => t.importSpecifier(
|
|
909
|
+
t.identifier(name),
|
|
910
|
+
t.identifier(name)
|
|
911
|
+
)
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
return [];
|
|
915
|
+
}
|
|
916
|
+
);
|
|
917
|
+
if (specifiers.length === 0) {
|
|
918
|
+
path.remove();
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
535
921
|
const importDecl = t.importDeclaration(
|
|
536
|
-
|
|
537
|
-
(decl) => t.importSpecifier(
|
|
538
|
-
t.identifier(decl.id.name),
|
|
539
|
-
t.identifier(decl.id.name)
|
|
540
|
-
)
|
|
541
|
-
),
|
|
922
|
+
specifiers,
|
|
542
923
|
t.stringLiteral(
|
|
543
924
|
removeSplitSearchParamFromFilename(opts.filename)
|
|
544
925
|
)
|
|
@@ -555,10 +936,121 @@ function compileCodeSplitVirtualRoute(opts) {
|
|
|
555
936
|
}
|
|
556
937
|
}
|
|
557
938
|
});
|
|
939
|
+
if (opts.sharedBindings && opts.sharedBindings.size > 0) {
|
|
940
|
+
const sharedImportSpecifiers = [...opts.sharedBindings].map(
|
|
941
|
+
(name) => t.importSpecifier(t.identifier(name), t.identifier(name))
|
|
942
|
+
);
|
|
943
|
+
const sharedModuleUrl = addSharedSearchParamToFilename(
|
|
944
|
+
removeSplitSearchParamFromFilename(opts.filename)
|
|
945
|
+
);
|
|
946
|
+
const [sharedImportPath] = programPath.unshiftContainer(
|
|
947
|
+
"body",
|
|
948
|
+
t.importDeclaration(
|
|
949
|
+
sharedImportSpecifiers,
|
|
950
|
+
t.stringLiteral(sharedModuleUrl)
|
|
951
|
+
)
|
|
952
|
+
);
|
|
953
|
+
sharedImportPath.traverse({
|
|
954
|
+
Identifier(identPath) {
|
|
955
|
+
if (identPath.parentPath.isImportSpecifier() && identPath.key === "local") {
|
|
956
|
+
refIdents.add(identPath);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
deadCodeElimination(ast, refIdents);
|
|
965
|
+
{
|
|
966
|
+
const locallyBound = /* @__PURE__ */ new Set();
|
|
967
|
+
for (const stmt of ast.program.body) {
|
|
968
|
+
collectLocalBindingsFromStatement(stmt, locallyBound);
|
|
969
|
+
}
|
|
970
|
+
ast.program.body = ast.program.body.filter((stmt) => {
|
|
971
|
+
if (!t.isExpressionStatement(stmt)) return true;
|
|
972
|
+
const refs = collectIdentifiersFromNode(stmt);
|
|
973
|
+
return [...refs].some((name) => locallyBound.has(name));
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
if (ast.program.body.length === 0) {
|
|
977
|
+
ast.program.directives = [];
|
|
978
|
+
}
|
|
979
|
+
return generateFromAst(ast, {
|
|
980
|
+
sourceMaps: true,
|
|
981
|
+
sourceFileName: opts.filename,
|
|
982
|
+
filename: opts.filename
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
function compileCodeSplitSharedRoute(opts) {
|
|
986
|
+
const ast = parseAst(opts);
|
|
987
|
+
const refIdents = findReferencedIdentifiers(ast);
|
|
988
|
+
const localBindings = /* @__PURE__ */ new Set();
|
|
989
|
+
for (const node of ast.program.body) {
|
|
990
|
+
collectLocalBindingsFromStatement(node, localBindings);
|
|
991
|
+
}
|
|
992
|
+
localBindings.delete("Route");
|
|
993
|
+
const declMap = buildDeclarationMap(ast);
|
|
994
|
+
const depGraph = buildDependencyGraph(declMap, localBindings);
|
|
995
|
+
const keepBindings = new Set(opts.sharedBindings);
|
|
996
|
+
keepBindings.delete("Route");
|
|
997
|
+
expandTransitively(keepBindings, depGraph);
|
|
998
|
+
ast.program.body = ast.program.body.filter((stmt) => {
|
|
999
|
+
if (t.isImportDeclaration(stmt)) return true;
|
|
1000
|
+
const decl = t.isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;
|
|
1001
|
+
if (t.isVariableDeclaration(decl)) {
|
|
1002
|
+
decl.declarations = decl.declarations.filter((declarator) => {
|
|
1003
|
+
const names = collectIdentifiersFromPattern(declarator.id);
|
|
1004
|
+
return names.some((n) => keepBindings.has(n));
|
|
1005
|
+
});
|
|
1006
|
+
if (decl.declarations.length === 0) return false;
|
|
1007
|
+
if (t.isExportNamedDeclaration(stmt) && stmt.declaration) {
|
|
1008
|
+
return true;
|
|
558
1009
|
}
|
|
1010
|
+
return true;
|
|
1011
|
+
} else if (t.isFunctionDeclaration(decl) && decl.id) {
|
|
1012
|
+
return keepBindings.has(decl.id.name);
|
|
1013
|
+
} else if (t.isClassDeclaration(decl) && decl.id) {
|
|
1014
|
+
return keepBindings.has(decl.id.name);
|
|
1015
|
+
}
|
|
1016
|
+
return false;
|
|
1017
|
+
});
|
|
1018
|
+
ast.program.body = ast.program.body.map((stmt) => {
|
|
1019
|
+
if (t.isExportNamedDeclaration(stmt) && stmt.declaration) {
|
|
1020
|
+
return stmt.declaration;
|
|
559
1021
|
}
|
|
1022
|
+
return stmt;
|
|
560
1023
|
});
|
|
1024
|
+
const exportNames = [...opts.sharedBindings].sort(
|
|
1025
|
+
(a, b) => a.localeCompare(b)
|
|
1026
|
+
);
|
|
1027
|
+
const exportSpecifiers = exportNames.map(
|
|
1028
|
+
(name) => t.exportSpecifier(t.identifier(name), t.identifier(name))
|
|
1029
|
+
);
|
|
1030
|
+
if (exportSpecifiers.length > 0) {
|
|
1031
|
+
const exportDecl = t.exportNamedDeclaration(null, exportSpecifiers);
|
|
1032
|
+
ast.program.body.push(exportDecl);
|
|
1033
|
+
babel.traverse(ast, {
|
|
1034
|
+
Program(programPath) {
|
|
1035
|
+
const bodyPaths = programPath.get("body");
|
|
1036
|
+
const last = bodyPaths[bodyPaths.length - 1];
|
|
1037
|
+
if (last && last.isExportNamedDeclaration()) {
|
|
1038
|
+
last.traverse({
|
|
1039
|
+
Identifier(identPath) {
|
|
1040
|
+
if (identPath.parentPath.isExportSpecifier() && identPath.key === "local") {
|
|
1041
|
+
refIdents.add(identPath);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
programPath.stop();
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
561
1050
|
deadCodeElimination(ast, refIdents);
|
|
1051
|
+
if (ast.program.body.length === 0) {
|
|
1052
|
+
ast.program.directives = [];
|
|
1053
|
+
}
|
|
562
1054
|
return generateFromAst(ast, {
|
|
563
1055
|
sourceMaps: true,
|
|
564
1056
|
sourceFileName: opts.filename,
|
|
@@ -658,6 +1150,37 @@ function getImportSpecifierAndPathFromLocalName(programPath, name) {
|
|
|
658
1150
|
});
|
|
659
1151
|
return { specifier, path };
|
|
660
1152
|
}
|
|
1153
|
+
function collectIdentifiersFromPattern(node) {
|
|
1154
|
+
if (!node) {
|
|
1155
|
+
return [];
|
|
1156
|
+
}
|
|
1157
|
+
if (t.isIdentifier(node)) {
|
|
1158
|
+
return [node.name];
|
|
1159
|
+
}
|
|
1160
|
+
if (t.isAssignmentPattern(node)) {
|
|
1161
|
+
return collectIdentifiersFromPattern(node.left);
|
|
1162
|
+
}
|
|
1163
|
+
if (t.isRestElement(node)) {
|
|
1164
|
+
return collectIdentifiersFromPattern(node.argument);
|
|
1165
|
+
}
|
|
1166
|
+
if (t.isObjectPattern(node)) {
|
|
1167
|
+
return node.properties.flatMap((prop) => {
|
|
1168
|
+
if (t.isObjectProperty(prop)) {
|
|
1169
|
+
return collectIdentifiersFromPattern(prop.value);
|
|
1170
|
+
}
|
|
1171
|
+
if (t.isRestElement(prop)) {
|
|
1172
|
+
return collectIdentifiersFromPattern(prop.argument);
|
|
1173
|
+
}
|
|
1174
|
+
return [];
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
if (t.isArrayPattern(node)) {
|
|
1178
|
+
return node.elements.flatMap(
|
|
1179
|
+
(element) => collectIdentifiersFromPattern(element)
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
return [];
|
|
1183
|
+
}
|
|
661
1184
|
function resolveIdentifier(path, node) {
|
|
662
1185
|
if (t.isIdentifier(node)) {
|
|
663
1186
|
const binding = path.scope.getBinding(node.name);
|
|
@@ -676,6 +1199,25 @@ function resolveIdentifier(path, node) {
|
|
|
676
1199
|
function removeIdentifierLiteral(path, node) {
|
|
677
1200
|
const binding = path.scope.getBinding(node.name);
|
|
678
1201
|
if (binding) {
|
|
1202
|
+
if (t.isVariableDeclarator(binding.path.node) && t.isObjectPattern(binding.path.node.id)) {
|
|
1203
|
+
const objectPattern = binding.path.node.id;
|
|
1204
|
+
objectPattern.properties = objectPattern.properties.filter((prop) => {
|
|
1205
|
+
if (!t.isObjectProperty(prop)) {
|
|
1206
|
+
return true;
|
|
1207
|
+
}
|
|
1208
|
+
if (t.isIdentifier(prop.value) && prop.value.name === node.name) {
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
if (t.isAssignmentPattern(prop.value) && t.isIdentifier(prop.value.left) && prop.value.left.name === node.name) {
|
|
1212
|
+
return false;
|
|
1213
|
+
}
|
|
1214
|
+
return true;
|
|
1215
|
+
});
|
|
1216
|
+
if (objectPattern.properties.length === 0) {
|
|
1217
|
+
binding.path.remove();
|
|
1218
|
+
}
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
679
1221
|
binding.path.remove();
|
|
680
1222
|
}
|
|
681
1223
|
}
|
|
@@ -691,6 +1233,11 @@ function hasExport(ast, node) {
|
|
|
691
1233
|
if (decl.id.name === node.name) {
|
|
692
1234
|
found = true;
|
|
693
1235
|
}
|
|
1236
|
+
} else if (t.isObjectPattern(decl.id) || t.isArrayPattern(decl.id)) {
|
|
1237
|
+
const names = collectIdentifiersFromPattern(decl.id);
|
|
1238
|
+
if (names.includes(node.name)) {
|
|
1239
|
+
found = true;
|
|
1240
|
+
}
|
|
694
1241
|
}
|
|
695
1242
|
}
|
|
696
1243
|
});
|
|
@@ -734,6 +1281,12 @@ function removeExports(ast, node) {
|
|
|
734
1281
|
path.remove();
|
|
735
1282
|
removed = true;
|
|
736
1283
|
}
|
|
1284
|
+
} else if (t.isObjectPattern(decl.id) || t.isArrayPattern(decl.id)) {
|
|
1285
|
+
const names = collectIdentifiersFromPattern(decl.id);
|
|
1286
|
+
if (names.includes(node.name)) {
|
|
1287
|
+
path.remove();
|
|
1288
|
+
removed = true;
|
|
1289
|
+
}
|
|
737
1290
|
}
|
|
738
1291
|
}
|
|
739
1292
|
});
|
|
@@ -766,8 +1319,20 @@ function removeExports(ast, node) {
|
|
|
766
1319
|
return removed;
|
|
767
1320
|
}
|
|
768
1321
|
export {
|
|
1322
|
+
addSharedSearchParamToFilename,
|
|
1323
|
+
buildDeclarationMap,
|
|
1324
|
+
buildDependencyGraph,
|
|
1325
|
+
collectIdentifiersFromNode,
|
|
1326
|
+
collectLocalBindingsFromStatement,
|
|
1327
|
+
collectModuleLevelRefsFromNode,
|
|
769
1328
|
compileCodeSplitReferenceRoute,
|
|
1329
|
+
compileCodeSplitSharedRoute,
|
|
770
1330
|
compileCodeSplitVirtualRoute,
|
|
771
|
-
|
|
1331
|
+
computeSharedBindings,
|
|
1332
|
+
detectCodeSplitGroupingsFromRoute,
|
|
1333
|
+
expandDestructuredDeclarations,
|
|
1334
|
+
expandSharedDestructuredDeclarators,
|
|
1335
|
+
expandTransitively,
|
|
1336
|
+
removeBindingsDependingOnRoute
|
|
772
1337
|
};
|
|
773
1338
|
//# sourceMappingURL=compilers.js.map
|