@react-router/dev 0.0.0-experimental-beaa4f52a → 0.0.0-experimental-a383e1e6e

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/vite.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @react-router/dev v0.0.0-experimental-beaa4f52a
2
+ * @react-router/dev v0.0.0-experimental-a383e1e6e
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -54,6 +54,7 @@ var import_react_router2 = require("react-router");
54
54
  var import_es_module_lexer = require("es-module-lexer");
55
55
  var import_jsesc = __toESM(require("jsesc"));
56
56
  var import_picocolors3 = __toESM(require("picocolors"));
57
+ var import_kebabCase = __toESM(require("lodash/kebabCase"));
57
58
 
58
59
  // typegen/index.ts
59
60
  var import_node_fs2 = __toESM(require("fs"));
@@ -443,7 +444,8 @@ async function resolveConfig({
443
444
  );
444
445
  }
445
446
  let future = {
446
- unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false
447
+ unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
448
+ unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false
447
449
  };
448
450
  let reactRouterConfig = deepFreeze({
449
451
  appDirectory,
@@ -692,8 +694,8 @@ function generate(ctx, route) {
692
694
  export type HeadersArgs = T.HeadersArgs
693
695
  export type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit
694
696
 
695
- export type MiddlewareArgs = T.CreateServerMiddlewareArgs<Info>
696
- export type ClientMiddlewareArgs = T.CreateClientMiddlewareArgs<Info>
697
+ export type unstable_MiddlewareArgs = T.CreateServerMiddlewareArgs<Info>
698
+ export type unstable_ClientMiddlewareArgs = T.CreateClientMiddlewareArgs<Info>
697
699
  export type LoaderArgs = T.CreateServerLoaderArgs<Info>
698
700
  export type ClientLoaderArgs = T.CreateClientLoaderArgs<Info>
699
701
  export type ActionArgs = T.CreateServerActionArgs<Info>
@@ -1161,6 +1163,611 @@ function invalidDestructureError(name) {
1161
1163
  return new Error(`Cannot remove destructured export "${name}"`);
1162
1164
  }
1163
1165
 
1166
+ // vite/cache.ts
1167
+ function getOrSetFromCache(cache, key, version, getValue) {
1168
+ if (!cache) {
1169
+ return getValue();
1170
+ }
1171
+ let entry = cache.get(key);
1172
+ if (entry?.version === version) {
1173
+ return entry.value;
1174
+ }
1175
+ let value = getValue();
1176
+ let newEntry = { value, version };
1177
+ cache.set(key, newEntry);
1178
+ return value;
1179
+ }
1180
+
1181
+ // vite/route-chunks.ts
1182
+ function codeToAst(code, cache, cacheKey) {
1183
+ return structuredClone(
1184
+ getOrSetFromCache(
1185
+ cache,
1186
+ `${cacheKey}::codeToAst`,
1187
+ code,
1188
+ () => (0, import_parser.parse)(code, { sourceType: "module" })
1189
+ )
1190
+ );
1191
+ }
1192
+ function assertNodePath(path7) {
1193
+ invariant(
1194
+ path7 && !Array.isArray(path7),
1195
+ `Expected a Path, but got ${Array.isArray(path7) ? "an array" : path7}`
1196
+ );
1197
+ }
1198
+ function assertNodePathIsStatement(path7) {
1199
+ invariant(
1200
+ path7 && !Array.isArray(path7) && t.isStatement(path7.node),
1201
+ `Expected a Statement path, but got ${Array.isArray(path7) ? "an array" : path7?.node?.type}`
1202
+ );
1203
+ }
1204
+ function assertNodePathIsVariableDeclarator(path7) {
1205
+ invariant(
1206
+ path7 && !Array.isArray(path7) && t.isVariableDeclarator(path7.node),
1207
+ `Expected an Identifier path, but got ${Array.isArray(path7) ? "an array" : path7?.node?.type}`
1208
+ );
1209
+ }
1210
+ function assertNodePathIsPattern(path7) {
1211
+ invariant(
1212
+ path7 && !Array.isArray(path7) && t.isPattern(path7.node),
1213
+ `Expected a Pattern path, but got ${Array.isArray(path7) ? "an array" : path7?.node?.type}`
1214
+ );
1215
+ }
1216
+ function getExportDependencies(code, cache, cacheKey) {
1217
+ return getOrSetFromCache(
1218
+ cache,
1219
+ `${cacheKey}::getExportDependencies`,
1220
+ code,
1221
+ () => {
1222
+ let exportDependencies = /* @__PURE__ */ new Map();
1223
+ let ast = codeToAst(code, cache, cacheKey);
1224
+ function handleExport(exportName, exportPath, identifiersPath = exportPath) {
1225
+ let identifiers = getDependentIdentifiersForPath(identifiersPath);
1226
+ let topLevelStatements = /* @__PURE__ */ new Set([
1227
+ exportPath.node,
1228
+ ...getTopLevelStatementsForPaths(identifiers)
1229
+ ]);
1230
+ let topLevelNonModuleStatements = new Set(
1231
+ Array.from(topLevelStatements).filter(
1232
+ (statement) => !t.isImportDeclaration(statement) && !t.isExportDeclaration(statement)
1233
+ )
1234
+ );
1235
+ let importedIdentifierNames = /* @__PURE__ */ new Set();
1236
+ for (let identifier of identifiers) {
1237
+ if (identifier.parentPath.parentPath?.isImportDeclaration()) {
1238
+ importedIdentifierNames.add(identifier.node.name);
1239
+ }
1240
+ }
1241
+ let exportedVariableDeclarators = /* @__PURE__ */ new Set();
1242
+ for (let identifier of identifiers) {
1243
+ if (identifier.parentPath.isVariableDeclarator() && identifier.parentPath.parentPath.parentPath?.isExportNamedDeclaration()) {
1244
+ exportedVariableDeclarators.add(identifier.parentPath.node);
1245
+ continue;
1246
+ }
1247
+ let isWithinExportDestructuring = Boolean(
1248
+ identifier.findParent(
1249
+ (path7) => Boolean(
1250
+ path7.isPattern() && path7.parentPath?.isVariableDeclarator() && path7.parentPath.parentPath?.parentPath?.isExportNamedDeclaration()
1251
+ )
1252
+ )
1253
+ );
1254
+ if (isWithinExportDestructuring) {
1255
+ let currentPath = identifier;
1256
+ while (currentPath) {
1257
+ if (
1258
+ // Check the identifier is within a variable declaration, and if
1259
+ // so, ensure we're on the left-hand side of the expression
1260
+ // since these identifiers are what make up the export names,
1261
+ // e.g. export const { foo } = { foo: bar }; should pick up
1262
+ // `foo` but not `bar`.
1263
+ currentPath.parentPath?.isVariableDeclarator() && currentPath.parentKey === "id"
1264
+ ) {
1265
+ exportedVariableDeclarators.add(currentPath.parentPath.node);
1266
+ break;
1267
+ }
1268
+ currentPath = currentPath.parentPath;
1269
+ }
1270
+ }
1271
+ }
1272
+ let dependencies = {
1273
+ topLevelStatements,
1274
+ topLevelNonModuleStatements,
1275
+ importedIdentifierNames,
1276
+ exportedVariableDeclarators
1277
+ };
1278
+ exportDependencies.set(exportName, dependencies);
1279
+ }
1280
+ traverse(ast, {
1281
+ ExportDeclaration(exportPath) {
1282
+ let { node } = exportPath;
1283
+ if (t.isExportAllDeclaration(node)) {
1284
+ return;
1285
+ }
1286
+ if (t.isExportDefaultDeclaration(node)) {
1287
+ handleExport("default", exportPath);
1288
+ return;
1289
+ }
1290
+ let { declaration } = node;
1291
+ if (t.isVariableDeclaration(declaration)) {
1292
+ let { declarations } = declaration;
1293
+ for (let i = 0; i < declarations.length; i++) {
1294
+ let declarator = declarations[i];
1295
+ if (t.isIdentifier(declarator.id)) {
1296
+ let declaratorPath = exportPath.get(
1297
+ `declaration.declarations.${i}`
1298
+ );
1299
+ assertNodePathIsVariableDeclarator(declaratorPath);
1300
+ handleExport(declarator.id.name, exportPath, declaratorPath);
1301
+ continue;
1302
+ }
1303
+ if (t.isPattern(declarator.id)) {
1304
+ let exportedPatternPath = exportPath.get(
1305
+ `declaration.declarations.${i}.id`
1306
+ );
1307
+ assertNodePathIsPattern(exportedPatternPath);
1308
+ let identifiers = getIdentifiersForPatternPath(exportedPatternPath);
1309
+ for (let identifier of identifiers) {
1310
+ handleExport(identifier.node.name, exportPath, identifier);
1311
+ }
1312
+ }
1313
+ }
1314
+ return;
1315
+ }
1316
+ if (t.isFunctionDeclaration(declaration) || t.isClassDeclaration(declaration)) {
1317
+ invariant(
1318
+ declaration.id,
1319
+ "Expected exported function or class declaration to have a name when not the default export"
1320
+ );
1321
+ handleExport(declaration.id.name, exportPath);
1322
+ return;
1323
+ }
1324
+ if (t.isExportNamedDeclaration(node)) {
1325
+ for (let specifier of node.specifiers) {
1326
+ if (t.isIdentifier(specifier.exported)) {
1327
+ let name = specifier.exported.name;
1328
+ let specifierPath = exportPath.get("specifiers").find((path7) => path7.node === specifier);
1329
+ invariant(
1330
+ specifierPath,
1331
+ `Expected to find specifier path for ${name}`
1332
+ );
1333
+ handleExport(name, exportPath, specifierPath);
1334
+ }
1335
+ }
1336
+ return;
1337
+ }
1338
+ throw new Error(`Unknown export node type: ${node.type}`);
1339
+ }
1340
+ });
1341
+ return exportDependencies;
1342
+ }
1343
+ );
1344
+ }
1345
+ function getDependentIdentifiersForPath(path7, state) {
1346
+ let { visited, identifiers } = state ?? {
1347
+ visited: /* @__PURE__ */ new Set(),
1348
+ identifiers: /* @__PURE__ */ new Set()
1349
+ };
1350
+ if (visited.has(path7)) {
1351
+ return identifiers;
1352
+ }
1353
+ visited.add(path7);
1354
+ path7.traverse({
1355
+ Identifier(path8) {
1356
+ if (identifiers.has(path8)) {
1357
+ return;
1358
+ }
1359
+ identifiers.add(path8);
1360
+ let binding = path8.scope.getBinding(path8.node.name);
1361
+ if (!binding) {
1362
+ return;
1363
+ }
1364
+ getDependentIdentifiersForPath(binding.path, { visited, identifiers });
1365
+ for (let reference of binding.referencePaths) {
1366
+ if (reference.isExportNamedDeclaration()) {
1367
+ continue;
1368
+ }
1369
+ getDependentIdentifiersForPath(reference, {
1370
+ visited,
1371
+ identifiers
1372
+ });
1373
+ }
1374
+ for (let constantViolation of binding.constantViolations) {
1375
+ getDependentIdentifiersForPath(constantViolation, {
1376
+ visited,
1377
+ identifiers
1378
+ });
1379
+ }
1380
+ }
1381
+ });
1382
+ let topLevelStatement = getTopLevelStatementPathForPath(path7);
1383
+ let withinImportStatement = topLevelStatement.isImportDeclaration();
1384
+ let withinExportStatement = topLevelStatement.isExportDeclaration();
1385
+ if (!withinImportStatement && !withinExportStatement) {
1386
+ getDependentIdentifiersForPath(topLevelStatement, {
1387
+ visited,
1388
+ identifiers
1389
+ });
1390
+ }
1391
+ if (withinExportStatement && path7.isIdentifier() && (t.isPattern(path7.parentPath.node) || // [foo]
1392
+ t.isPattern(path7.parentPath.parentPath?.node))) {
1393
+ let variableDeclarator = path7.findParent((p) => p.isVariableDeclarator());
1394
+ assertNodePath(variableDeclarator);
1395
+ getDependentIdentifiersForPath(variableDeclarator, {
1396
+ visited,
1397
+ identifiers
1398
+ });
1399
+ }
1400
+ return identifiers;
1401
+ }
1402
+ function getTopLevelStatementPathForPath(path7) {
1403
+ let ancestry = path7.getAncestry();
1404
+ let topLevelStatement = ancestry[ancestry.length - 2];
1405
+ assertNodePathIsStatement(topLevelStatement);
1406
+ return topLevelStatement;
1407
+ }
1408
+ function getTopLevelStatementsForPaths(paths) {
1409
+ let topLevelStatements = /* @__PURE__ */ new Set();
1410
+ for (let path7 of paths) {
1411
+ let topLevelStatement = getTopLevelStatementPathForPath(path7);
1412
+ topLevelStatements.add(topLevelStatement.node);
1413
+ }
1414
+ return topLevelStatements;
1415
+ }
1416
+ function getIdentifiersForPatternPath(patternPath, identifiers = /* @__PURE__ */ new Set()) {
1417
+ function walk(currentPath) {
1418
+ if (currentPath.isIdentifier()) {
1419
+ identifiers.add(currentPath);
1420
+ return;
1421
+ }
1422
+ if (currentPath.isObjectPattern()) {
1423
+ let { properties } = currentPath.node;
1424
+ for (let i = 0; i < properties.length; i++) {
1425
+ const property = properties[i];
1426
+ if (t.isObjectProperty(property)) {
1427
+ let valuePath = currentPath.get(`properties.${i}.value`);
1428
+ assertNodePath(valuePath);
1429
+ walk(valuePath);
1430
+ } else if (t.isRestElement(property)) {
1431
+ let argumentPath = currentPath.get(`properties.${i}.argument`);
1432
+ assertNodePath(argumentPath);
1433
+ walk(argumentPath);
1434
+ }
1435
+ }
1436
+ } else if (currentPath.isArrayPattern()) {
1437
+ let { elements } = currentPath.node;
1438
+ for (let i = 0; i < elements.length; i++) {
1439
+ const element = elements[i];
1440
+ if (element) {
1441
+ let elementPath = currentPath.get(`elements.${i}`);
1442
+ assertNodePath(elementPath);
1443
+ walk(elementPath);
1444
+ }
1445
+ }
1446
+ } else if (currentPath.isRestElement()) {
1447
+ let argumentPath = currentPath.get("argument");
1448
+ assertNodePath(argumentPath);
1449
+ walk(argumentPath);
1450
+ }
1451
+ }
1452
+ walk(patternPath);
1453
+ return identifiers;
1454
+ }
1455
+ var getExportedName = (exported) => {
1456
+ return t.isIdentifier(exported) ? exported.name : exported.value;
1457
+ };
1458
+ function setsIntersect(set1, set2) {
1459
+ let smallerSet = set1;
1460
+ let largerSet = set2;
1461
+ if (set1.size > set2.size) {
1462
+ smallerSet = set2;
1463
+ largerSet = set1;
1464
+ }
1465
+ for (let element of smallerSet) {
1466
+ if (largerSet.has(element)) {
1467
+ return true;
1468
+ }
1469
+ }
1470
+ return false;
1471
+ }
1472
+ function hasChunkableExport(code, exportName, cache, cacheKey) {
1473
+ return getOrSetFromCache(
1474
+ cache,
1475
+ `${cacheKey}::hasChunkableExport::${exportName}`,
1476
+ code,
1477
+ () => {
1478
+ let exportDependencies = getExportDependencies(code, cache, cacheKey);
1479
+ let dependencies = exportDependencies.get(exportName);
1480
+ if (!dependencies) {
1481
+ return false;
1482
+ }
1483
+ for (let [currentExportName, currentDependencies] of exportDependencies) {
1484
+ if (currentExportName === exportName) {
1485
+ continue;
1486
+ }
1487
+ if (setsIntersect(
1488
+ currentDependencies.topLevelNonModuleStatements,
1489
+ dependencies.topLevelNonModuleStatements
1490
+ )) {
1491
+ return false;
1492
+ }
1493
+ }
1494
+ if (dependencies.exportedVariableDeclarators.size > 1) {
1495
+ return false;
1496
+ }
1497
+ if (dependencies.exportedVariableDeclarators.size > 0) {
1498
+ for (let [
1499
+ currentExportName,
1500
+ currentDependencies
1501
+ ] of exportDependencies) {
1502
+ if (currentExportName === exportName) {
1503
+ continue;
1504
+ }
1505
+ if (setsIntersect(
1506
+ currentDependencies.exportedVariableDeclarators,
1507
+ dependencies.exportedVariableDeclarators
1508
+ )) {
1509
+ return false;
1510
+ }
1511
+ }
1512
+ }
1513
+ return true;
1514
+ }
1515
+ );
1516
+ }
1517
+ function getChunkedExport(code, exportName, generateOptions = {}, cache, cacheKey) {
1518
+ return getOrSetFromCache(
1519
+ cache,
1520
+ `${cacheKey}::getChunkedExport::${exportName}::${JSON.stringify(
1521
+ generateOptions
1522
+ )}`,
1523
+ code,
1524
+ () => {
1525
+ if (!hasChunkableExport(code, exportName, cache, cacheKey)) {
1526
+ return void 0;
1527
+ }
1528
+ let exportDependencies = getExportDependencies(code, cache, cacheKey);
1529
+ let dependencies = exportDependencies.get(exportName);
1530
+ invariant(dependencies, "Expected export to have dependencies");
1531
+ let topLevelStatementsArray = Array.from(dependencies.topLevelStatements);
1532
+ let exportedVariableDeclaratorsArray = Array.from(
1533
+ dependencies.exportedVariableDeclarators
1534
+ );
1535
+ let ast = codeToAst(code, cache, cacheKey);
1536
+ ast.program.body = ast.program.body.filter(
1537
+ (node) => topLevelStatementsArray.some(
1538
+ (statement) => t.isNodesEquivalent(node, statement)
1539
+ )
1540
+ ).map((node) => {
1541
+ if (!t.isImportDeclaration(node)) {
1542
+ return node;
1543
+ }
1544
+ if (dependencies.importedIdentifierNames.size === 0) {
1545
+ return null;
1546
+ }
1547
+ node.specifiers = node.specifiers.filter(
1548
+ (specifier) => dependencies.importedIdentifierNames.has(specifier.local.name)
1549
+ );
1550
+ invariant(
1551
+ node.specifiers.length > 0,
1552
+ "Expected import statement to have used specifiers"
1553
+ );
1554
+ return node;
1555
+ }).map((node) => {
1556
+ if (!t.isExportDeclaration(node)) {
1557
+ return node;
1558
+ }
1559
+ if (t.isExportAllDeclaration(node)) {
1560
+ return null;
1561
+ }
1562
+ if (t.isExportDefaultDeclaration(node)) {
1563
+ return exportName === "default" ? node : null;
1564
+ }
1565
+ let { declaration } = node;
1566
+ if (t.isVariableDeclaration(declaration)) {
1567
+ declaration.declarations = declaration.declarations.filter(
1568
+ (node2) => exportedVariableDeclaratorsArray.some(
1569
+ (declarator) => t.isNodesEquivalent(node2, declarator)
1570
+ )
1571
+ );
1572
+ if (declaration.declarations.length === 0) {
1573
+ return null;
1574
+ }
1575
+ return node;
1576
+ }
1577
+ if (t.isFunctionDeclaration(node.declaration) || t.isClassDeclaration(node.declaration)) {
1578
+ return node.declaration.id?.name === exportName ? node : null;
1579
+ }
1580
+ if (t.isExportNamedDeclaration(node)) {
1581
+ if (node.specifiers.length === 0) {
1582
+ return null;
1583
+ }
1584
+ node.specifiers = node.specifiers.filter(
1585
+ (specifier) => getExportedName(specifier.exported) === exportName
1586
+ );
1587
+ if (node.specifiers.length === 0) {
1588
+ return null;
1589
+ }
1590
+ return node;
1591
+ }
1592
+ throw new Error(`Unknown export node type: ${node.type}`);
1593
+ }).filter((node) => node !== null);
1594
+ return generate2(ast, generateOptions);
1595
+ }
1596
+ );
1597
+ }
1598
+ function omitChunkedExports(code, exportNames, generateOptions = {}, cache, cacheKey) {
1599
+ return getOrSetFromCache(
1600
+ cache,
1601
+ `${cacheKey}::omitChunkedExports::${exportNames.join(
1602
+ ","
1603
+ )}::${JSON.stringify(generateOptions)}`,
1604
+ code,
1605
+ () => {
1606
+ const isChunkable = (exportName) => hasChunkableExport(code, exportName, cache, cacheKey);
1607
+ const isOmitted = (exportName) => exportNames.includes(exportName) && isChunkable(exportName);
1608
+ const isRetained = (exportName) => !isOmitted(exportName);
1609
+ let exportDependencies = getExportDependencies(code, cache, cacheKey);
1610
+ let allExportNames = Array.from(exportDependencies.keys());
1611
+ let omittedExportNames = allExportNames.filter(isOmitted);
1612
+ let retainedExportNames = allExportNames.filter(isRetained);
1613
+ let omittedStatements = /* @__PURE__ */ new Set();
1614
+ let omittedExportedVariableDeclarators = /* @__PURE__ */ new Set();
1615
+ for (let omittedExportName of omittedExportNames) {
1616
+ let dependencies = exportDependencies.get(omittedExportName);
1617
+ invariant(
1618
+ dependencies,
1619
+ `Expected dependencies for ${omittedExportName}`
1620
+ );
1621
+ for (let statement of dependencies.topLevelNonModuleStatements) {
1622
+ omittedStatements.add(statement);
1623
+ }
1624
+ for (let declarator of dependencies.exportedVariableDeclarators) {
1625
+ omittedExportedVariableDeclarators.add(declarator);
1626
+ }
1627
+ }
1628
+ let ast = codeToAst(code, cache, cacheKey);
1629
+ let omittedStatementsArray = Array.from(omittedStatements);
1630
+ let omittedExportedVariableDeclaratorsArray = Array.from(
1631
+ omittedExportedVariableDeclarators
1632
+ );
1633
+ ast.program.body = ast.program.body.filter(
1634
+ (node) => omittedStatementsArray.every(
1635
+ (statement) => !t.isNodesEquivalent(node, statement)
1636
+ )
1637
+ ).map((node) => {
1638
+ if (!t.isImportDeclaration(node)) {
1639
+ return node;
1640
+ }
1641
+ if (node.specifiers.length === 0) {
1642
+ return node;
1643
+ }
1644
+ node.specifiers = node.specifiers.filter((specifier) => {
1645
+ let importedName = specifier.local.name;
1646
+ for (let retainedExportName of retainedExportNames) {
1647
+ let dependencies = exportDependencies.get(retainedExportName);
1648
+ if (dependencies?.importedIdentifierNames?.has(importedName)) {
1649
+ return true;
1650
+ }
1651
+ }
1652
+ for (let omittedExportName of omittedExportNames) {
1653
+ let dependencies = exportDependencies.get(omittedExportName);
1654
+ if (dependencies?.importedIdentifierNames?.has(importedName)) {
1655
+ return false;
1656
+ }
1657
+ }
1658
+ return true;
1659
+ });
1660
+ if (node.specifiers.length === 0) {
1661
+ return null;
1662
+ }
1663
+ return node;
1664
+ }).map((node) => {
1665
+ if (!t.isExportDeclaration(node)) {
1666
+ return node;
1667
+ }
1668
+ if (t.isExportAllDeclaration(node)) {
1669
+ return node;
1670
+ }
1671
+ if (t.isExportDefaultDeclaration(node)) {
1672
+ return isOmitted("default") ? null : node;
1673
+ }
1674
+ if (t.isVariableDeclaration(node.declaration)) {
1675
+ node.declaration.declarations = node.declaration.declarations.filter(
1676
+ (node2) => omittedExportedVariableDeclaratorsArray.every(
1677
+ (declarator) => !t.isNodesEquivalent(node2, declarator)
1678
+ )
1679
+ );
1680
+ if (node.declaration.declarations.length === 0) {
1681
+ return null;
1682
+ }
1683
+ return node;
1684
+ }
1685
+ if (t.isFunctionDeclaration(node.declaration) || t.isClassDeclaration(node.declaration)) {
1686
+ invariant(
1687
+ node.declaration.id,
1688
+ "Expected exported function or class declaration to have a name when not the default export"
1689
+ );
1690
+ return isOmitted(node.declaration.id.name) ? null : node;
1691
+ }
1692
+ if (t.isExportNamedDeclaration(node)) {
1693
+ if (node.specifiers.length === 0) {
1694
+ return node;
1695
+ }
1696
+ node.specifiers = node.specifiers.filter((specifier) => {
1697
+ const exportedName = getExportedName(specifier.exported);
1698
+ return !isOmitted(exportedName);
1699
+ });
1700
+ if (node.specifiers.length === 0) {
1701
+ return null;
1702
+ }
1703
+ return node;
1704
+ }
1705
+ throw new Error(`Unknown node type: ${node.type}`);
1706
+ }).filter((node) => node !== null);
1707
+ if (ast.program.body.length === 0) {
1708
+ return void 0;
1709
+ }
1710
+ return generate2(ast, generateOptions);
1711
+ }
1712
+ );
1713
+ }
1714
+ function detectRouteChunks(code, cache, cacheKey) {
1715
+ const hasRouteChunkByExportName = Object.fromEntries(
1716
+ routeChunkExportNames.map((exportName) => [
1717
+ exportName,
1718
+ hasChunkableExport(code, exportName, cache, cacheKey)
1719
+ ])
1720
+ );
1721
+ const chunkedExports = Object.entries(hasRouteChunkByExportName).filter(([, isChunked]) => isChunked).map(([exportName]) => exportName);
1722
+ const hasRouteChunks = chunkedExports.length > 0;
1723
+ return {
1724
+ hasRouteChunks,
1725
+ hasRouteChunkByExportName,
1726
+ chunkedExports
1727
+ };
1728
+ }
1729
+ var routeChunkExportNames = [
1730
+ "clientAction",
1731
+ "clientLoader",
1732
+ "HydrateFallback"
1733
+ ];
1734
+ var mainChunkName = "main";
1735
+ var routeChunkNames = ["main", ...routeChunkExportNames];
1736
+ function getRouteChunkCode(code, chunkName, cache, cacheKey) {
1737
+ if (chunkName === mainChunkName) {
1738
+ return omitChunkedExports(code, routeChunkExportNames, {}, cache, cacheKey);
1739
+ }
1740
+ return getChunkedExport(code, chunkName, {}, cache, cacheKey);
1741
+ }
1742
+ var routeChunkQueryStringPrefix = "?route-chunk=";
1743
+ var routeChunkQueryStrings = {
1744
+ main: `${routeChunkQueryStringPrefix}main`,
1745
+ clientAction: `${routeChunkQueryStringPrefix}clientAction`,
1746
+ clientLoader: `${routeChunkQueryStringPrefix}clientLoader`,
1747
+ HydrateFallback: `${routeChunkQueryStringPrefix}HydrateFallback`
1748
+ };
1749
+ function getRouteChunkModuleId(filePath, chunkName) {
1750
+ return `${filePath}${routeChunkQueryStrings[chunkName]}`;
1751
+ }
1752
+ function isRouteChunkModuleId(id) {
1753
+ return Object.values(routeChunkQueryStrings).some(
1754
+ (queryString) => id.endsWith(queryString)
1755
+ );
1756
+ }
1757
+ function isRouteChunkName(name) {
1758
+ return name === mainChunkName || routeChunkExportNames.includes(name);
1759
+ }
1760
+ function getRouteChunkNameFromModuleId(id) {
1761
+ if (!isRouteChunkModuleId(id)) {
1762
+ return null;
1763
+ }
1764
+ let chunkName = id.split(routeChunkQueryStringPrefix)[1].split("&")[0];
1765
+ if (!isRouteChunkName(chunkName)) {
1766
+ return null;
1767
+ }
1768
+ return chunkName;
1769
+ }
1770
+
1164
1771
  // vite/with-props.ts
1165
1772
  var import_dedent2 = __toESM(require("dedent"));
1166
1773
  var vmod = create("with-props");
@@ -1286,23 +1893,43 @@ function toFunctionExpression(decl) {
1286
1893
  }
1287
1894
 
1288
1895
  // vite/plugin.ts
1289
- var SERVER_ONLY_ROUTE_EXPORTS = ["loader", "action", "middleware", "headers"];
1290
- var CLIENT_ROUTE_EXPORTS = [
1896
+ var SERVER_ONLY_ROUTE_EXPORTS = [
1897
+ "loader",
1898
+ "action",
1899
+ "unstable_middleware",
1900
+ "headers"
1901
+ ];
1902
+ var CLIENT_ONLY_NON_COMPONENT_EXPORTS = [
1291
1903
  "clientAction",
1292
1904
  "clientLoader",
1293
- "clientMiddleware",
1294
- "default",
1295
- "ErrorBoundary",
1905
+ "unstable_clientMiddleware",
1296
1906
  "handle",
1297
- "HydrateFallback",
1298
- "Layout",
1299
- "links",
1300
1907
  "meta",
1908
+ "links",
1301
1909
  "shouldRevalidate"
1302
1910
  ];
1911
+ var CLIENT_ROUTE_EXPORTS = [
1912
+ ...CLIENT_ONLY_NON_COMPONENT_EXPORTS,
1913
+ "default",
1914
+ "ErrorBoundary",
1915
+ "HydrateFallback",
1916
+ "Layout"
1917
+ ];
1303
1918
  var BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
1919
+ var isRouteEntryModuleId = (id) => {
1920
+ return id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING);
1921
+ };
1922
+ var isRouteVirtualModule = (id) => {
1923
+ return isRouteEntryModuleId(id) || isRouteChunkModuleId(id);
1924
+ };
1304
1925
  var virtualHmrRuntime = create("hmr-runtime");
1305
1926
  var virtualInjectHmrRuntime = create("inject-hmr-runtime");
1927
+ var normalizeRelativeFilePath = (file, reactRouterConfig) => {
1928
+ let vite2 = getVite();
1929
+ let fullPath = path6.resolve(reactRouterConfig.appDirectory, file);
1930
+ let relativePath = path6.relative(reactRouterConfig.appDirectory, fullPath);
1931
+ return vite2.normalizePath(relativePath).split("?")[0];
1932
+ };
1306
1933
  var resolveRelativeRouteFilePath = (route, reactRouterConfig) => {
1307
1934
  let vite2 = getVite();
1308
1935
  let file = route.file;
@@ -1331,23 +1958,35 @@ var resolveChunk = (ctx, viteManifest, absoluteFilePath) => {
1331
1958
  let rootRelativeFilePath = vite2.normalizePath(
1332
1959
  path6.relative(ctx.rootDirectory, absoluteFilePath)
1333
1960
  );
1334
- let entryChunk = viteManifest[rootRelativeFilePath + BUILD_CLIENT_ROUTE_QUERY_STRING] ?? viteManifest[rootRelativeFilePath];
1961
+ let entryChunk = viteManifest[rootRelativeFilePath];
1335
1962
  if (!entryChunk) {
1336
- let knownManifestKeys = Object.keys(viteManifest).map((key) => '"' + key + '"').join(", ");
1337
- throw new Error(
1338
- `No manifest entry found for "${rootRelativeFilePath}". Known manifest keys: ${knownManifestKeys}`
1339
- );
1963
+ return void 0;
1340
1964
  }
1341
1965
  return entryChunk;
1342
1966
  };
1967
+ var getPublicModulePathForEntry = (ctx, viteManifest, entryFilePath) => {
1968
+ let entryChunk = resolveChunk(ctx, viteManifest, entryFilePath);
1969
+ return entryChunk ? `${ctx.publicPath}${entryChunk.file}` : void 0;
1970
+ };
1343
1971
  var getReactRouterManifestBuildAssets = (ctx, viteManifest, entryFilePath, prependedAssetFilePaths = []) => {
1344
1972
  let entryChunk = resolveChunk(ctx, viteManifest, entryFilePath);
1345
- let prependedAssetChunks = prependedAssetFilePaths.map(
1346
- (filePath) => resolveChunk(ctx, viteManifest, filePath)
1347
- );
1973
+ invariant(entryChunk, "Chunk not found");
1974
+ let prependedAssetChunks = prependedAssetFilePaths.map((filePath) => {
1975
+ let chunk = resolveChunk(ctx, viteManifest, filePath);
1976
+ invariant(chunk, "Chunk not found");
1977
+ return chunk;
1978
+ });
1979
+ let routeModuleChunks = routeChunkNames.map(
1980
+ (routeChunkName) => resolveChunk(
1981
+ ctx,
1982
+ viteManifest,
1983
+ getRouteChunkModuleId(entryFilePath.split("?")[0], routeChunkName)
1984
+ )
1985
+ ).filter(isNonNullable);
1348
1986
  let chunks = resolveDependantChunks(viteManifest, [
1349
1987
  ...prependedAssetChunks,
1350
- entryChunk
1988
+ entryChunk,
1989
+ ...routeModuleChunks
1351
1990
  ]);
1352
1991
  return {
1353
1992
  module: `${ctx.publicPath}${entryChunk.file}`,
@@ -1384,6 +2023,10 @@ var writeFileSafe = async (file, contents) => {
1384
2023
  await fse.ensureDir(path6.dirname(file));
1385
2024
  await fse.writeFile(file, contents);
1386
2025
  };
2026
+ var getExportNames = (code) => {
2027
+ let [, exportSpecifiers] = (0, import_es_module_lexer.parse)(code);
2028
+ return exportSpecifiers.map(({ n: name }) => name);
2029
+ };
1387
2030
  var getRouteManifestModuleExports = async (viteChildCompiler, ctx) => {
1388
2031
  let entries = await Promise.all(
1389
2032
  Object.entries(ctx.reactRouterConfig.routes).map(async ([key, route]) => {
@@ -1397,7 +2040,7 @@ var getRouteManifestModuleExports = async (viteChildCompiler, ctx) => {
1397
2040
  );
1398
2041
  return Object.fromEntries(entries);
1399
2042
  };
1400
- var getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRouteFile) => {
2043
+ var compileRouteFile = async (viteChildCompiler, ctx, routeFile, readRouteFile) => {
1401
2044
  if (!viteChildCompiler) {
1402
2045
  throw new Error("Vite child compiler not found");
1403
2046
  }
@@ -1417,9 +2060,19 @@ var getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRouteF
1417
2060
  moduleGraph.ensureEntryFromUrl(url2, ssr)
1418
2061
  ]);
1419
2062
  let transformed = await pluginContainer.transform(code, id, { ssr });
1420
- let [, exports2] = (0, import_es_module_lexer.parse)(transformed.code);
1421
- let exportNames = exports2.map((e) => e.n);
1422
- return exportNames;
2063
+ return transformed.code;
2064
+ };
2065
+ var getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRouteFile) => {
2066
+ if (!viteChildCompiler) {
2067
+ throw new Error("Vite child compiler not found");
2068
+ }
2069
+ let code = await compileRouteFile(
2070
+ viteChildCompiler,
2071
+ ctx,
2072
+ routeFile,
2073
+ readRouteFile
2074
+ );
2075
+ return getExportNames(code);
1423
2076
  };
1424
2077
  var getServerBundleBuildConfig = (viteUserConfig) => {
1425
2078
  if (!("__reactRouterServerBundleBuildConfig" in viteUserConfig) || !viteUserConfig.__reactRouterServerBundleBuildConfig) {
@@ -1450,6 +2103,7 @@ var reactRouterVitePlugin = () => {
1450
2103
  let viteConfig;
1451
2104
  let cssModulesManifest = {};
1452
2105
  let viteChildCompiler = null;
2106
+ let cache = /* @__PURE__ */ new Map();
1453
2107
  let reactRouterConfigLoader;
1454
2108
  let typegenWatcherPromise;
1455
2109
  let logger;
@@ -1535,7 +2189,8 @@ var reactRouterVitePlugin = () => {
1535
2189
  )};
1536
2190
  export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)};
1537
2191
  export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
1538
- export const isSpaMode = ${!ctx.reactRouterConfig.ssr && ctx.reactRouterConfig.prerender == null};
2192
+ export const ssr = ${ctx.reactRouterConfig.ssr};
2193
+ export const isSpaMode = ${isSpaModeEnabled(ctx.reactRouterConfig)};
1539
2194
  export const publicPath = ${JSON.stringify(ctx.publicPath)};
1540
2195
  export const entry = { module: entryServer };
1541
2196
  export const routes = {
@@ -1589,13 +2244,31 @@ var reactRouterVitePlugin = () => {
1589
2244
  viteChildCompiler,
1590
2245
  ctx
1591
2246
  );
2247
+ let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
1592
2248
  for (let [key, route] of Object.entries(ctx.reactRouterConfig.routes)) {
1593
- let routeFilePath = path6.join(
1594
- ctx.reactRouterConfig.appDirectory,
1595
- route.file
1596
- );
2249
+ let routeFile = path6.join(ctx.reactRouterConfig.appDirectory, route.file);
1597
2250
  let sourceExports = routeManifestExports[key];
1598
2251
  let isRootRoute = route.parentId === void 0;
2252
+ let hasClientAction = sourceExports.includes("clientAction");
2253
+ let hasClientLoader = sourceExports.includes("clientLoader");
2254
+ let hasHydrateFallback = sourceExports.includes("HydrateFallback");
2255
+ let { hasRouteChunkByExportName } = await detectRouteChunksIfEnabled(
2256
+ cache,
2257
+ ctx,
2258
+ routeFile,
2259
+ { routeFile, viteChildCompiler }
2260
+ );
2261
+ if (enforceSplitRouteModules) {
2262
+ validateRouteChunks({
2263
+ ctx,
2264
+ id: route.file,
2265
+ valid: {
2266
+ clientAction: !hasClientAction || hasRouteChunkByExportName.clientAction,
2267
+ clientLoader: !hasClientLoader || hasRouteChunkByExportName.clientLoader,
2268
+ HydrateFallback: !hasHydrateFallback || hasRouteChunkByExportName.HydrateFallback
2269
+ }
2270
+ });
2271
+ }
1599
2272
  let routeManifestEntry = {
1600
2273
  id: route.id,
1601
2274
  parentId: route.parentId,
@@ -1604,18 +2277,33 @@ var reactRouterVitePlugin = () => {
1604
2277
  caseSensitive: route.caseSensitive,
1605
2278
  hasAction: sourceExports.includes("action"),
1606
2279
  hasLoader: sourceExports.includes("loader"),
1607
- hasClientAction: sourceExports.includes("clientAction"),
1608
- hasClientLoader: sourceExports.includes("clientLoader"),
2280
+ hasClientAction,
2281
+ hasClientLoader,
1609
2282
  hasErrorBoundary: sourceExports.includes("ErrorBoundary"),
1610
2283
  ...getReactRouterManifestBuildAssets(
1611
2284
  ctx,
1612
2285
  viteManifest,
1613
- routeFilePath,
2286
+ `${routeFile}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
1614
2287
  // If this is the root route, we also need to include assets from the
1615
2288
  // client entry file as this is a common way for consumers to import
1616
2289
  // global reset styles, etc.
1617
2290
  isRootRoute ? [ctx.entryClientFilePath] : []
1618
- )
2291
+ ),
2292
+ clientActionModule: hasRouteChunkByExportName.clientAction ? getPublicModulePathForEntry(
2293
+ ctx,
2294
+ viteManifest,
2295
+ getRouteChunkModuleId(routeFile, "clientAction")
2296
+ ) : void 0,
2297
+ clientLoaderModule: hasRouteChunkByExportName.clientLoader ? getPublicModulePathForEntry(
2298
+ ctx,
2299
+ viteManifest,
2300
+ getRouteChunkModuleId(routeFile, "clientLoader")
2301
+ ) : void 0,
2302
+ hydrateFallbackModule: hasRouteChunkByExportName.HydrateFallback ? getPublicModulePathForEntry(
2303
+ ctx,
2304
+ viteManifest,
2305
+ getRouteChunkModuleId(routeFile, "HydrateFallback")
2306
+ ) : void 0
1619
2307
  };
1620
2308
  browserRoutes[key] = routeManifestEntry;
1621
2309
  let serverBundleRoutes = ctx.serverBundleBuildConfig?.routes;
@@ -1656,25 +2344,52 @@ var reactRouterVitePlugin = () => {
1656
2344
  viteChildCompiler,
1657
2345
  ctx
1658
2346
  );
2347
+ let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
1659
2348
  for (let [key, route] of Object.entries(ctx.reactRouterConfig.routes)) {
2349
+ let routeFile = route.file;
1660
2350
  let sourceExports = routeManifestExports[key];
2351
+ let hasClientAction = sourceExports.includes("clientAction");
2352
+ let hasClientLoader = sourceExports.includes("clientLoader");
2353
+ let hasHydrateFallback = sourceExports.includes("HydrateFallback");
2354
+ let routeModulePath = combineURLs(
2355
+ ctx.publicPath,
2356
+ `${resolveFileUrl(
2357
+ ctx,
2358
+ resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
2359
+ )}`
2360
+ );
2361
+ if (enforceSplitRouteModules) {
2362
+ let { hasRouteChunkByExportName } = await detectRouteChunksIfEnabled(
2363
+ cache,
2364
+ ctx,
2365
+ routeFile,
2366
+ { routeFile, viteChildCompiler }
2367
+ );
2368
+ validateRouteChunks({
2369
+ ctx,
2370
+ id: route.file,
2371
+ valid: {
2372
+ clientAction: !hasClientAction || hasRouteChunkByExportName.clientAction,
2373
+ clientLoader: !hasClientLoader || hasRouteChunkByExportName.clientLoader,
2374
+ HydrateFallback: !hasHydrateFallback || hasRouteChunkByExportName.HydrateFallback
2375
+ }
2376
+ });
2377
+ }
1661
2378
  routes[key] = {
1662
2379
  id: route.id,
1663
2380
  parentId: route.parentId,
1664
2381
  path: route.path,
1665
2382
  index: route.index,
1666
2383
  caseSensitive: route.caseSensitive,
1667
- module: combineURLs(
1668
- ctx.publicPath,
1669
- resolveFileUrl(
1670
- ctx,
1671
- resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
1672
- )
1673
- ),
2384
+ module: routeModulePath,
2385
+ // Split route modules are a build-time optimization
2386
+ clientActionModule: void 0,
2387
+ clientLoaderModule: void 0,
2388
+ hydrateFallbackModule: void 0,
1674
2389
  hasAction: sourceExports.includes("action"),
1675
2390
  hasLoader: sourceExports.includes("loader"),
1676
- hasClientAction: sourceExports.includes("clientAction"),
1677
- hasClientLoader: sourceExports.includes("clientLoader"),
2391
+ hasClientAction,
2392
+ hasClientLoader,
1678
2393
  hasErrorBoundary: sourceExports.includes("ErrorBoundary"),
1679
2394
  imports: []
1680
2395
  };
@@ -1825,14 +2540,40 @@ var reactRouterVitePlugin = () => {
1825
2540
  rollupOptions: {
1826
2541
  ...baseRollupOptions,
1827
2542
  preserveEntrySignatures: "exports-only",
2543
+ output: {
2544
+ entryFileNames({ moduleIds }) {
2545
+ let routeChunkModuleId = moduleIds.find(isRouteChunkModuleId);
2546
+ let routeChunkName = routeChunkModuleId ? getRouteChunkNameFromModuleId(
2547
+ routeChunkModuleId
2548
+ ) : null;
2549
+ let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
2550
+ return `assets/[name]${routeChunkSuffix}-[hash].js`;
2551
+ }
2552
+ },
1828
2553
  input: [
1829
2554
  ctx.entryClientFilePath,
1830
- ...Object.values(ctx.reactRouterConfig.routes).map(
1831
- (route) => `${path6.resolve(
2555
+ ...Object.values(
2556
+ ctx.reactRouterConfig.routes
2557
+ ).flatMap((route) => {
2558
+ let routeFilePath = path6.resolve(
1832
2559
  ctx.reactRouterConfig.appDirectory,
1833
2560
  route.file
1834
- )}${BUILD_CLIENT_ROUTE_QUERY_STRING}`
1835
- )
2561
+ );
2562
+ let isRootRoute = route.file === ctx.reactRouterConfig.routes.root.file;
2563
+ let code = fse.readFileSync(
2564
+ routeFilePath,
2565
+ "utf-8"
2566
+ );
2567
+ return [
2568
+ `${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
2569
+ ...ctx.reactRouterConfig.future.unstable_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
2570
+ (exportName) => code.includes(exportName) ? getRouteChunkModuleId(
2571
+ routeFilePath,
2572
+ exportName
2573
+ ) : null
2574
+ ) : []
2575
+ ].filter(isNonNullable);
2576
+ })
1836
2577
  ]
1837
2578
  }
1838
2579
  } : {
@@ -2102,10 +2843,59 @@ var reactRouterVitePlugin = () => {
2102
2843
  await typegenWatcher?.close();
2103
2844
  }
2104
2845
  },
2846
+ {
2847
+ name: "react-router:route-chunks-index",
2848
+ // This plugin provides the route module "index" since route modules can
2849
+ // be chunked and may be made up of multiple smaller modules. This plugin
2850
+ // primarily ensures code is never duplicated across a route module and
2851
+ // its chunks. If we didn't have this plugin, any app that explicitly
2852
+ // imports a route module would result in duplicate code since the app
2853
+ // would contain code for both the unprocessed route module as well as its
2854
+ // individual chunks. This is because, since they have different module
2855
+ // IDs, they are treated as completely separate modules even though they
2856
+ // all reference the same underlying file. This plugin addresses this by
2857
+ // ensuring that any explicit imports of a route module resolve to a
2858
+ // module that simply re-exports from its underlying chunks, if present.
2859
+ async transform(code, id, options) {
2860
+ if (viteCommand !== "build") return;
2861
+ if (options?.ssr) {
2862
+ return;
2863
+ }
2864
+ if (!isRoute(ctx.reactRouterConfig, id)) {
2865
+ return;
2866
+ }
2867
+ if (isRouteVirtualModule(id)) {
2868
+ return;
2869
+ }
2870
+ let { hasRouteChunks, chunkedExports } = await detectRouteChunksIfEnabled(cache, ctx, id, code);
2871
+ if (!hasRouteChunks) {
2872
+ return;
2873
+ }
2874
+ let sourceExports = await getRouteModuleExports(
2875
+ viteChildCompiler,
2876
+ ctx,
2877
+ id
2878
+ );
2879
+ let isMainChunkExport = (name) => !chunkedExports.includes(name);
2880
+ let mainChunkReexports = sourceExports.filter(isMainChunkExport).join(", ");
2881
+ let chunkBasePath = `./${path6.basename(id)}`;
2882
+ return [
2883
+ `export { ${mainChunkReexports} } from "${getRouteChunkModuleId(
2884
+ chunkBasePath,
2885
+ "main"
2886
+ )}";`,
2887
+ ...chunkedExports.map(
2888
+ (exportName) => `export { ${exportName} } from "${getRouteChunkModuleId(
2889
+ chunkBasePath,
2890
+ exportName
2891
+ )}";`
2892
+ )
2893
+ ].filter(Boolean).join("\n");
2894
+ }
2895
+ },
2105
2896
  {
2106
2897
  name: "react-router:build-client-route",
2107
- enforce: "pre",
2108
- async transform(_code, id, options) {
2898
+ async transform(code, id, options) {
2109
2899
  if (!id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING)) return;
2110
2900
  let routeModuleId = id.replace(BUILD_CLIENT_ROUTE_QUERY_STRING, "");
2111
2901
  let routeFileName = path6.basename(routeModuleId);
@@ -2114,12 +2904,59 @@ var reactRouterVitePlugin = () => {
2114
2904
  ctx,
2115
2905
  routeModuleId
2116
2906
  );
2117
- let reexports = sourceExports.filter(
2118
- (exportName) => options?.ssr && SERVER_ONLY_ROUTE_EXPORTS.includes(exportName) || CLIENT_ROUTE_EXPORTS.includes(exportName)
2119
- ).join(", ");
2907
+ let { chunkedExports = [] } = options?.ssr ? {} : await detectRouteChunksIfEnabled(cache, ctx, id, code);
2908
+ let reexports = sourceExports.filter((exportName) => {
2909
+ let isRouteEntryExport = options?.ssr && SERVER_ONLY_ROUTE_EXPORTS.includes(exportName) || CLIENT_ROUTE_EXPORTS.includes(exportName);
2910
+ let isChunkedExport = chunkedExports.includes(
2911
+ exportName
2912
+ );
2913
+ return isRouteEntryExport && !isChunkedExport;
2914
+ }).join(", ");
2120
2915
  return `export { ${reexports} } from "./${routeFileName}";`;
2121
2916
  }
2122
2917
  },
2918
+ {
2919
+ name: "react-router:split-route-modules",
2920
+ async transform(code, id, options) {
2921
+ if (options?.ssr) return;
2922
+ if (!isRouteChunkModuleId(id)) return;
2923
+ invariant(
2924
+ viteCommand === "build",
2925
+ "Route modules are only split in build mode"
2926
+ );
2927
+ let chunkName = getRouteChunkNameFromModuleId(id);
2928
+ if (!chunkName) {
2929
+ throw new Error(`Invalid route chunk name "${chunkName}" in "${id}"`);
2930
+ }
2931
+ let chunk = await getRouteChunkIfEnabled(
2932
+ cache,
2933
+ ctx,
2934
+ id,
2935
+ chunkName,
2936
+ code
2937
+ );
2938
+ let preventEmptyChunkSnippet = ({ reason }) => `Math.random()<0&&console.log(${JSON.stringify(reason)});`;
2939
+ if (chunk === null) {
2940
+ return preventEmptyChunkSnippet({
2941
+ reason: "Split round modules disabled"
2942
+ });
2943
+ }
2944
+ let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
2945
+ if (enforceSplitRouteModules && chunkName === "main" && chunk) {
2946
+ let exportNames = getExportNames(chunk.code);
2947
+ validateRouteChunks({
2948
+ ctx,
2949
+ id,
2950
+ valid: {
2951
+ clientAction: !exportNames.includes("clientAction"),
2952
+ clientLoader: !exportNames.includes("clientLoader"),
2953
+ HydrateFallback: !exportNames.includes("HydrateFallback")
2954
+ }
2955
+ });
2956
+ }
2957
+ return chunk ?? preventEmptyChunkSnippet({ reason: `No ${chunkName} chunk` });
2958
+ }
2959
+ },
2123
2960
  {
2124
2961
  name: "react-router:virtual-modules",
2125
2962
  enforce: "pre",
@@ -2174,8 +3011,7 @@ var reactRouterVitePlugin = () => {
2174
3011
  let importerShort = vite2.normalizePath(
2175
3012
  path6.relative(ctx.rootDirectory, importer)
2176
3013
  );
2177
- let isRoute = getRoute(ctx.reactRouterConfig, importer);
2178
- if (isRoute) {
3014
+ if (isRoute(ctx.reactRouterConfig, importer)) {
2179
3015
  let serverOnlyExports = SERVER_ONLY_ROUTE_EXPORTS.map(
2180
3016
  (xport) => `\`${xport}\``
2181
3017
  ).join(", ");
@@ -2214,10 +3050,10 @@ var reactRouterVitePlugin = () => {
2214
3050
  let clientFileRE = /\.client(\.[cm]?[jt]sx?)?$/;
2215
3051
  let clientDirRE = /\/\.client\//;
2216
3052
  if (clientFileRE.test(id) || clientDirRE.test(id)) {
2217
- let exports2 = (0, import_es_module_lexer.parse)(code)[1];
3053
+ let exports2 = getExportNames(code);
2218
3054
  return {
2219
3055
  code: exports2.map(
2220
- ({ n: name }) => name === "default" ? "export default undefined;" : `export const ${name} = undefined;`
3056
+ (name) => name === "default" ? "export default undefined;" : `export const ${name} = undefined;`
2221
3057
  ).join("\n"),
2222
3058
  map: null
2223
3059
  };
@@ -2228,17 +3064,25 @@ var reactRouterVitePlugin = () => {
2228
3064
  {
2229
3065
  name: "react-router:route-exports",
2230
3066
  async transform(code, id, options) {
3067
+ if (isRouteChunkModuleId(id)) {
3068
+ id = id.split("?")[0];
3069
+ }
2231
3070
  let route = getRoute(ctx.reactRouterConfig, id);
2232
3071
  if (!route) return;
2233
- if (!options?.ssr && !ctx.reactRouterConfig.ssr) {
2234
- let serverOnlyExports = (0, import_es_module_lexer.parse)(code)[1].map((exp) => exp.n).filter((exp) => SERVER_ONLY_ROUTE_EXPORTS.includes(exp));
3072
+ if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig)) {
3073
+ let exportNames = getExportNames(code);
3074
+ let serverOnlyExports = exportNames.filter(
3075
+ (exp) => SERVER_ONLY_ROUTE_EXPORTS.includes(exp)
3076
+ );
2235
3077
  if (serverOnlyExports.length > 0) {
2236
3078
  let str = serverOnlyExports.map((e) => `\`${e}\``).join(", ");
2237
3079
  let message = `SPA Mode: ${serverOnlyExports.length} invalid route export(s) in \`${route.file}\`: ${str}. See https://remix.run/guides/spa-mode for more information.`;
2238
3080
  throw Error(message);
2239
3081
  }
2240
3082
  if (route.id !== "root") {
2241
- let hasHydrateFallback = (0, import_es_module_lexer.parse)(code)[1].map((exp) => exp.n).some((exp) => exp === "HydrateFallback");
3083
+ let hasHydrateFallback = exportNames.some(
3084
+ (exp) => exp === "HydrateFallback"
3085
+ );
2242
3086
  if (hasHydrateFallback) {
2243
3087
  let message = `SPA Mode: Invalid \`HydrateFallback\` export found in \`${route.file}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://remix.run/guides/spa-mode for more information.`;
2244
3088
  throw Error(message);
@@ -2316,6 +3160,9 @@ var reactRouterVitePlugin = () => {
2316
3160
  let isJSX = filepath.endsWith("x");
2317
3161
  let useFastRefresh = !ssr && (isJSX || code.includes(devRuntime));
2318
3162
  if (!useFastRefresh) return;
3163
+ if (isRouteVirtualModule(id)) {
3164
+ return { code: addRefreshWrapper(ctx.reactRouterConfig, code, id) };
3165
+ }
2319
3166
  let result = await babel.transformAsync(code, {
2320
3167
  babelrc: false,
2321
3168
  configFile: false,
@@ -2346,6 +3193,7 @@ var reactRouterVitePlugin = () => {
2346
3193
  let serverManifest = (await server.ssrLoadModule(virtual.serverManifest.id)).default;
2347
3194
  let oldRouteMetadata = serverManifest.routes[route.id];
2348
3195
  let newRouteMetadata = await getRouteMetadata(
3196
+ cache,
2349
3197
  ctx,
2350
3198
  viteChildCompiler,
2351
3199
  route,
@@ -2355,9 +3203,12 @@ var reactRouterVitePlugin = () => {
2355
3203
  if (!oldRouteMetadata || [
2356
3204
  "hasLoader",
2357
3205
  "hasClientLoader",
3206
+ "clientLoaderModule",
2358
3207
  "hasAction",
2359
3208
  "hasClientAction",
2360
- "hasErrorBoundary"
3209
+ "clientActionModule",
3210
+ "hasErrorBoundary",
3211
+ "hydrateFallbackModule"
2361
3212
  ].some((key) => oldRouteMetadata[key] !== newRouteMetadata[key])) {
2362
3213
  invalidateVirtualModules(server);
2363
3214
  }
@@ -2420,15 +3271,7 @@ function uniqueNodes(nodes) {
2420
3271
  }
2421
3272
  function addRefreshWrapper(reactRouterConfig, code, id) {
2422
3273
  let route = getRoute(reactRouterConfig, id);
2423
- let acceptExports = route ? [
2424
- "clientAction",
2425
- "clientLoader",
2426
- "clientMiddleware",
2427
- "handle",
2428
- "meta",
2429
- "links",
2430
- "shouldRevalidate"
2431
- ] : [];
3274
+ let acceptExports = route ? CLIENT_ONLY_NON_COMPONENT_EXPORTS : [];
2432
3275
  return REACT_REFRESH_HEADER.replaceAll("__SOURCE__", JSON.stringify(id)) + code + REACT_REFRESH_FOOTER.replaceAll("__SOURCE__", JSON.stringify(id)).replaceAll("__ACCEPT_EXPORTS__", JSON.stringify(acceptExports)).replaceAll("__ROUTE_ID__", JSON.stringify(route?.id));
2433
3276
  }
2434
3277
  var REACT_REFRESH_HEADER = `
@@ -2476,13 +3319,30 @@ function getRoute(pluginConfig, file) {
2476
3319
  );
2477
3320
  return route;
2478
3321
  }
2479
- async function getRouteMetadata(ctx, viteChildCompiler, route, readRouteFile) {
3322
+ function isRoute(pluginConfig, file) {
3323
+ return Boolean(getRoute(pluginConfig, file));
3324
+ }
3325
+ async function getRouteMetadata(cache, ctx, viteChildCompiler, route, readRouteFile) {
3326
+ let routeFile = route.file;
2480
3327
  let sourceExports = await getRouteModuleExports(
2481
3328
  viteChildCompiler,
2482
3329
  ctx,
2483
3330
  route.file,
2484
3331
  readRouteFile
2485
3332
  );
3333
+ let { hasRouteChunkByExportName } = await detectRouteChunksIfEnabled(
3334
+ cache,
3335
+ ctx,
3336
+ routeFile,
3337
+ { routeFile, readRouteFile, viteChildCompiler }
3338
+ );
3339
+ let moduleUrl = combineURLs(
3340
+ ctx.publicPath,
3341
+ `${resolveFileUrl(
3342
+ ctx,
3343
+ resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
3344
+ )}`
3345
+ );
2486
3346
  let info = {
2487
3347
  id: route.id,
2488
3348
  parentId: route.parentId,
@@ -2496,14 +3356,11 @@ async function getRouteMetadata(ctx, viteChildCompiler, route, readRouteFile) {
2496
3356
  resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
2497
3357
  )
2498
3358
  ),
2499
- module: combineURLs(
2500
- ctx.publicPath,
2501
- `${resolveFileUrl(
2502
- ctx,
2503
- resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
2504
- )}?import`
2505
- ),
3359
+ module: `${moduleUrl}?import`,
2506
3360
  // Ensure the Vite dev server responds with a JS module
3361
+ clientActionModule: hasRouteChunkByExportName.clientAction ? `${getRouteChunkModuleId(moduleUrl, "clientAction")}` : void 0,
3362
+ clientLoaderModule: hasRouteChunkByExportName.clientLoader ? `${getRouteChunkModuleId(moduleUrl, "clientLoader")}` : void 0,
3363
+ hydrateFallbackModule: hasRouteChunkByExportName.HydrateFallback ? `${getRouteChunkModuleId(moduleUrl, "HydrateFallback")}` : void 0,
2507
3364
  hasAction: sourceExports.includes("action"),
2508
3365
  hasClientAction: sourceExports.includes("clientAction"),
2509
3366
  hasLoader: sourceExports.includes("loader"),
@@ -2513,6 +3370,9 @@ async function getRouteMetadata(ctx, viteChildCompiler, route, readRouteFile) {
2513
3370
  };
2514
3371
  return info;
2515
3372
  }
3373
+ function isSpaModeEnabled(reactRouterConfig) {
3374
+ return reactRouterConfig.ssr === false && (reactRouterConfig.prerender == null || reactRouterConfig.prerender === false || Array.isArray(reactRouterConfig.prerender) && reactRouterConfig.prerender.length === 1 && reactRouterConfig.prerender[0] === "/");
3375
+ }
2516
3376
  async function getPrerenderBuildAndHandler(viteConfig, serverBuildDirectory, serverBuildFile) {
2517
3377
  let serverBuildPath = path6.join(serverBuildDirectory, serverBuildFile);
2518
3378
  let build = await import(url.pathToFileURL(serverBuildPath).toString());
@@ -2607,12 +3467,6 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
2607
3467
  );
2608
3468
  }
2609
3469
  }
2610
- await prerenderManifest(
2611
- build,
2612
- clientBuildDirectory,
2613
- reactRouterConfig,
2614
- viteConfig
2615
- );
2616
3470
  }
2617
3471
  function determineStaticPrerenderRoutes(routes, viteConfig, isBooleanUsage = false) {
2618
3472
  let paths = ["/"];
@@ -2688,18 +3542,6 @@ async function prerenderResourceRoute(handler, prerenderPath, clientBuildDirecto
2688
3542
  await fse.outputFile(outfile, text);
2689
3543
  viteConfig.logger.info(`Prerender: Generated ${import_picocolors3.default.bold(outfile)}`);
2690
3544
  }
2691
- async function prerenderManifest(build, clientBuildDirectory, reactRouterConfig, viteConfig) {
2692
- let normalizedPath = `${reactRouterConfig.basename}/__manifest`.replace(
2693
- /\/\/+/g,
2694
- "/"
2695
- );
2696
- let outdir = path6.relative(process.cwd(), clientBuildDirectory);
2697
- let outfile = path6.join(outdir, ...normalizedPath.split("/"));
2698
- await fse.ensureDir(path6.dirname(outfile));
2699
- let manifestData = JSON.stringify(build.assets.routes);
2700
- await fse.outputFile(outfile, manifestData);
2701
- viteConfig.logger.info(`Prerender: Generated ${import_picocolors3.default.bold(outfile)}`);
2702
- }
2703
3545
  function validatePrerenderedResponse(response, html, prefix, path7) {
2704
3546
  if (response.status !== 200) {
2705
3547
  throw new Error(
@@ -2751,6 +3593,73 @@ function createPrerenderRoutes(manifest, parentId = "", routesByParentId = group
2751
3593
  };
2752
3594
  });
2753
3595
  }
3596
+ var resolveRouteFileCode = async (ctx, input) => {
3597
+ if (typeof input === "string") return input;
3598
+ invariant(input.viteChildCompiler);
3599
+ return await compileRouteFile(
3600
+ input.viteChildCompiler,
3601
+ ctx,
3602
+ input.routeFile,
3603
+ input.readRouteFile
3604
+ );
3605
+ };
3606
+ async function detectRouteChunksIfEnabled(cache, ctx, id, input) {
3607
+ function noRouteChunks() {
3608
+ return {
3609
+ chunkedExports: [],
3610
+ hasRouteChunks: false,
3611
+ hasRouteChunkByExportName: {
3612
+ clientAction: false,
3613
+ clientLoader: false,
3614
+ HydrateFallback: false
3615
+ }
3616
+ };
3617
+ }
3618
+ if (!ctx.reactRouterConfig.future.unstable_splitRouteModules) {
3619
+ return noRouteChunks();
3620
+ }
3621
+ if (normalizeRelativeFilePath(id, ctx.reactRouterConfig) === ctx.reactRouterConfig.routes.root.file) {
3622
+ return noRouteChunks();
3623
+ }
3624
+ let code = await resolveRouteFileCode(ctx, input);
3625
+ if (!routeChunkExportNames.some((exportName) => code.includes(exportName))) {
3626
+ return noRouteChunks();
3627
+ }
3628
+ let cacheKey = normalizeRelativeFilePath(id, ctx.reactRouterConfig) + (typeof input === "string" ? "" : "?read");
3629
+ return detectRouteChunks(code, cache, cacheKey);
3630
+ }
3631
+ async function getRouteChunkIfEnabled(cache, ctx, id, chunkName, input) {
3632
+ if (!ctx.reactRouterConfig.future.unstable_splitRouteModules) {
3633
+ return null;
3634
+ }
3635
+ let code = await resolveRouteFileCode(ctx, input);
3636
+ let cacheKey = normalizeRelativeFilePath(id, ctx.reactRouterConfig) + (typeof input === "string" ? "" : "?read");
3637
+ return getRouteChunkCode(code, chunkName, cache, cacheKey);
3638
+ }
3639
+ function validateRouteChunks({
3640
+ ctx,
3641
+ id,
3642
+ valid
3643
+ }) {
3644
+ let invalidChunks = Object.entries(valid).filter(([_, isValid]) => !isValid).map(([chunkName]) => chunkName);
3645
+ if (invalidChunks.length === 0) {
3646
+ return;
3647
+ }
3648
+ let plural = invalidChunks.length > 1;
3649
+ throw new Error(
3650
+ [
3651
+ `Error splitting route module: ${normalizeRelativeFilePath(
3652
+ id,
3653
+ ctx.reactRouterConfig
3654
+ )}`,
3655
+ invalidChunks.map((name) => `- ${name}`).join("\n"),
3656
+ `${plural ? "These exports" : "This export"} could not be split into ${plural ? "their own chunks" : "its own chunk"} because ${plural ? "they share" : "it shares"} code with other exports. You should extract any shared code into its own module and then import it within the route module.`
3657
+ ].join("\n\n")
3658
+ );
3659
+ }
3660
+ function isNonNullable(x) {
3661
+ return x != null;
3662
+ }
2754
3663
  // Annotate the CommonJS export names for ESM import in node:
2755
3664
  0 && (module.exports = {
2756
3665
  reactRouter