@react-router/dev 7.1.5 → 7.2.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -1
- package/bin.js +2 -2
- package/dist/cli/index.js +510 -188
- package/dist/config.d.ts +8 -0
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/static/refresh-utils.cjs +1 -1
- package/dist/vite/cloudflare.js +487 -3
- package/dist/vite.js +1609 -275
- package/package.json +6 -6
package/dist/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v7.
|
|
2
|
+
* @react-router/dev v7.2.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -52,8 +52,10 @@ var fse = __toESM(require("fs-extra"));
|
|
|
52
52
|
var babel = __toESM(require("@babel/core"));
|
|
53
53
|
var import_react_router2 = require("react-router");
|
|
54
54
|
var import_es_module_lexer = require("es-module-lexer");
|
|
55
|
+
var import_pick3 = __toESM(require("lodash/pick"));
|
|
55
56
|
var import_jsesc = __toESM(require("jsesc"));
|
|
56
57
|
var import_picocolors3 = __toESM(require("picocolors"));
|
|
58
|
+
var import_kebabCase = __toESM(require("lodash/kebabCase"));
|
|
57
59
|
|
|
58
60
|
// typegen/index.ts
|
|
59
61
|
var import_node_fs2 = __toESM(require("fs"));
|
|
@@ -270,6 +272,13 @@ var detectPackageManager = () => {
|
|
|
270
272
|
|
|
271
273
|
// config/config.ts
|
|
272
274
|
var excludedConfigPresetKeys = ["presets"];
|
|
275
|
+
var branchRouteProperties = [
|
|
276
|
+
"id",
|
|
277
|
+
"path",
|
|
278
|
+
"file",
|
|
279
|
+
"index"
|
|
280
|
+
];
|
|
281
|
+
var configRouteToBranchRoute = (configRoute) => (0, import_pick2.default)(configRoute, branchRouteProperties);
|
|
273
282
|
var mergeReactRouterConfig = (...configs) => {
|
|
274
283
|
let reducer = (configA, configB) => {
|
|
275
284
|
let mergeRequired = (key) => configA[key] !== void 0 && configB[key] !== void 0;
|
|
@@ -443,7 +452,9 @@ async function resolveConfig({
|
|
|
443
452
|
);
|
|
444
453
|
}
|
|
445
454
|
let future = {
|
|
446
|
-
unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false
|
|
455
|
+
unstable_optimizeDeps: reactRouterUserConfig.future?.unstable_optimizeDeps ?? false,
|
|
456
|
+
unstable_splitRouteModules: reactRouterUserConfig.future?.unstable_splitRouteModules ?? false,
|
|
457
|
+
unstable_viteEnvironmentApi: reactRouterUserConfig.future?.unstable_viteEnvironmentApi ?? false
|
|
447
458
|
};
|
|
448
459
|
let reactRouterConfig = deepFreeze({
|
|
449
460
|
appDirectory,
|
|
@@ -1159,6 +1170,611 @@ function invalidDestructureError(name) {
|
|
|
1159
1170
|
return new Error(`Cannot remove destructured export "${name}"`);
|
|
1160
1171
|
}
|
|
1161
1172
|
|
|
1173
|
+
// vite/cache.ts
|
|
1174
|
+
function getOrSetFromCache(cache, key, version, getValue) {
|
|
1175
|
+
if (!cache) {
|
|
1176
|
+
return getValue();
|
|
1177
|
+
}
|
|
1178
|
+
let entry = cache.get(key);
|
|
1179
|
+
if (entry?.version === version) {
|
|
1180
|
+
return entry.value;
|
|
1181
|
+
}
|
|
1182
|
+
let value = getValue();
|
|
1183
|
+
let newEntry = { value, version };
|
|
1184
|
+
cache.set(key, newEntry);
|
|
1185
|
+
return value;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
// vite/route-chunks.ts
|
|
1189
|
+
function codeToAst(code, cache, cacheKey) {
|
|
1190
|
+
return structuredClone(
|
|
1191
|
+
getOrSetFromCache(
|
|
1192
|
+
cache,
|
|
1193
|
+
`${cacheKey}::codeToAst`,
|
|
1194
|
+
code,
|
|
1195
|
+
() => (0, import_parser.parse)(code, { sourceType: "module" })
|
|
1196
|
+
)
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
function assertNodePath(path7) {
|
|
1200
|
+
invariant(
|
|
1201
|
+
path7 && !Array.isArray(path7),
|
|
1202
|
+
`Expected a Path, but got ${Array.isArray(path7) ? "an array" : path7}`
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
function assertNodePathIsStatement(path7) {
|
|
1206
|
+
invariant(
|
|
1207
|
+
path7 && !Array.isArray(path7) && t.isStatement(path7.node),
|
|
1208
|
+
`Expected a Statement path, but got ${Array.isArray(path7) ? "an array" : path7?.node?.type}`
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
function assertNodePathIsVariableDeclarator(path7) {
|
|
1212
|
+
invariant(
|
|
1213
|
+
path7 && !Array.isArray(path7) && t.isVariableDeclarator(path7.node),
|
|
1214
|
+
`Expected an Identifier path, but got ${Array.isArray(path7) ? "an array" : path7?.node?.type}`
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
function assertNodePathIsPattern(path7) {
|
|
1218
|
+
invariant(
|
|
1219
|
+
path7 && !Array.isArray(path7) && t.isPattern(path7.node),
|
|
1220
|
+
`Expected a Pattern path, but got ${Array.isArray(path7) ? "an array" : path7?.node?.type}`
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
function getExportDependencies(code, cache, cacheKey) {
|
|
1224
|
+
return getOrSetFromCache(
|
|
1225
|
+
cache,
|
|
1226
|
+
`${cacheKey}::getExportDependencies`,
|
|
1227
|
+
code,
|
|
1228
|
+
() => {
|
|
1229
|
+
let exportDependencies = /* @__PURE__ */ new Map();
|
|
1230
|
+
let ast = codeToAst(code, cache, cacheKey);
|
|
1231
|
+
function handleExport(exportName, exportPath, identifiersPath = exportPath) {
|
|
1232
|
+
let identifiers = getDependentIdentifiersForPath(identifiersPath);
|
|
1233
|
+
let topLevelStatements = /* @__PURE__ */ new Set([
|
|
1234
|
+
exportPath.node,
|
|
1235
|
+
...getTopLevelStatementsForPaths(identifiers)
|
|
1236
|
+
]);
|
|
1237
|
+
let topLevelNonModuleStatements = new Set(
|
|
1238
|
+
Array.from(topLevelStatements).filter(
|
|
1239
|
+
(statement) => !t.isImportDeclaration(statement) && !t.isExportDeclaration(statement)
|
|
1240
|
+
)
|
|
1241
|
+
);
|
|
1242
|
+
let importedIdentifierNames = /* @__PURE__ */ new Set();
|
|
1243
|
+
for (let identifier of identifiers) {
|
|
1244
|
+
if (identifier.parentPath.parentPath?.isImportDeclaration()) {
|
|
1245
|
+
importedIdentifierNames.add(identifier.node.name);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
let exportedVariableDeclarators = /* @__PURE__ */ new Set();
|
|
1249
|
+
for (let identifier of identifiers) {
|
|
1250
|
+
if (identifier.parentPath.isVariableDeclarator() && identifier.parentPath.parentPath.parentPath?.isExportNamedDeclaration()) {
|
|
1251
|
+
exportedVariableDeclarators.add(identifier.parentPath.node);
|
|
1252
|
+
continue;
|
|
1253
|
+
}
|
|
1254
|
+
let isWithinExportDestructuring = Boolean(
|
|
1255
|
+
identifier.findParent(
|
|
1256
|
+
(path7) => Boolean(
|
|
1257
|
+
path7.isPattern() && path7.parentPath?.isVariableDeclarator() && path7.parentPath.parentPath?.parentPath?.isExportNamedDeclaration()
|
|
1258
|
+
)
|
|
1259
|
+
)
|
|
1260
|
+
);
|
|
1261
|
+
if (isWithinExportDestructuring) {
|
|
1262
|
+
let currentPath = identifier;
|
|
1263
|
+
while (currentPath) {
|
|
1264
|
+
if (
|
|
1265
|
+
// Check the identifier is within a variable declaration, and if
|
|
1266
|
+
// so, ensure we're on the left-hand side of the expression
|
|
1267
|
+
// since these identifiers are what make up the export names,
|
|
1268
|
+
// e.g. export const { foo } = { foo: bar }; should pick up
|
|
1269
|
+
// `foo` but not `bar`.
|
|
1270
|
+
currentPath.parentPath?.isVariableDeclarator() && currentPath.parentKey === "id"
|
|
1271
|
+
) {
|
|
1272
|
+
exportedVariableDeclarators.add(currentPath.parentPath.node);
|
|
1273
|
+
break;
|
|
1274
|
+
}
|
|
1275
|
+
currentPath = currentPath.parentPath;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
let dependencies = {
|
|
1280
|
+
topLevelStatements,
|
|
1281
|
+
topLevelNonModuleStatements,
|
|
1282
|
+
importedIdentifierNames,
|
|
1283
|
+
exportedVariableDeclarators
|
|
1284
|
+
};
|
|
1285
|
+
exportDependencies.set(exportName, dependencies);
|
|
1286
|
+
}
|
|
1287
|
+
traverse(ast, {
|
|
1288
|
+
ExportDeclaration(exportPath) {
|
|
1289
|
+
let { node } = exportPath;
|
|
1290
|
+
if (t.isExportAllDeclaration(node)) {
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
if (t.isExportDefaultDeclaration(node)) {
|
|
1294
|
+
handleExport("default", exportPath);
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
let { declaration } = node;
|
|
1298
|
+
if (t.isVariableDeclaration(declaration)) {
|
|
1299
|
+
let { declarations } = declaration;
|
|
1300
|
+
for (let i = 0; i < declarations.length; i++) {
|
|
1301
|
+
let declarator = declarations[i];
|
|
1302
|
+
if (t.isIdentifier(declarator.id)) {
|
|
1303
|
+
let declaratorPath = exportPath.get(
|
|
1304
|
+
`declaration.declarations.${i}`
|
|
1305
|
+
);
|
|
1306
|
+
assertNodePathIsVariableDeclarator(declaratorPath);
|
|
1307
|
+
handleExport(declarator.id.name, exportPath, declaratorPath);
|
|
1308
|
+
continue;
|
|
1309
|
+
}
|
|
1310
|
+
if (t.isPattern(declarator.id)) {
|
|
1311
|
+
let exportedPatternPath = exportPath.get(
|
|
1312
|
+
`declaration.declarations.${i}.id`
|
|
1313
|
+
);
|
|
1314
|
+
assertNodePathIsPattern(exportedPatternPath);
|
|
1315
|
+
let identifiers = getIdentifiersForPatternPath(exportedPatternPath);
|
|
1316
|
+
for (let identifier of identifiers) {
|
|
1317
|
+
handleExport(identifier.node.name, exportPath, identifier);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
if (t.isFunctionDeclaration(declaration) || t.isClassDeclaration(declaration)) {
|
|
1324
|
+
invariant(
|
|
1325
|
+
declaration.id,
|
|
1326
|
+
"Expected exported function or class declaration to have a name when not the default export"
|
|
1327
|
+
);
|
|
1328
|
+
handleExport(declaration.id.name, exportPath);
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
if (t.isExportNamedDeclaration(node)) {
|
|
1332
|
+
for (let specifier of node.specifiers) {
|
|
1333
|
+
if (t.isIdentifier(specifier.exported)) {
|
|
1334
|
+
let name = specifier.exported.name;
|
|
1335
|
+
let specifierPath = exportPath.get("specifiers").find((path7) => path7.node === specifier);
|
|
1336
|
+
invariant(
|
|
1337
|
+
specifierPath,
|
|
1338
|
+
`Expected to find specifier path for ${name}`
|
|
1339
|
+
);
|
|
1340
|
+
handleExport(name, exportPath, specifierPath);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
throw new Error(`Unknown export node type: ${node.type}`);
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
return exportDependencies;
|
|
1349
|
+
}
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
function getDependentIdentifiersForPath(path7, state) {
|
|
1353
|
+
let { visited, identifiers } = state ?? {
|
|
1354
|
+
visited: /* @__PURE__ */ new Set(),
|
|
1355
|
+
identifiers: /* @__PURE__ */ new Set()
|
|
1356
|
+
};
|
|
1357
|
+
if (visited.has(path7)) {
|
|
1358
|
+
return identifiers;
|
|
1359
|
+
}
|
|
1360
|
+
visited.add(path7);
|
|
1361
|
+
path7.traverse({
|
|
1362
|
+
Identifier(path8) {
|
|
1363
|
+
if (identifiers.has(path8)) {
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
identifiers.add(path8);
|
|
1367
|
+
let binding = path8.scope.getBinding(path8.node.name);
|
|
1368
|
+
if (!binding) {
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
getDependentIdentifiersForPath(binding.path, { visited, identifiers });
|
|
1372
|
+
for (let reference of binding.referencePaths) {
|
|
1373
|
+
if (reference.isExportNamedDeclaration()) {
|
|
1374
|
+
continue;
|
|
1375
|
+
}
|
|
1376
|
+
getDependentIdentifiersForPath(reference, {
|
|
1377
|
+
visited,
|
|
1378
|
+
identifiers
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
for (let constantViolation of binding.constantViolations) {
|
|
1382
|
+
getDependentIdentifiersForPath(constantViolation, {
|
|
1383
|
+
visited,
|
|
1384
|
+
identifiers
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
});
|
|
1389
|
+
let topLevelStatement = getTopLevelStatementPathForPath(path7);
|
|
1390
|
+
let withinImportStatement = topLevelStatement.isImportDeclaration();
|
|
1391
|
+
let withinExportStatement = topLevelStatement.isExportDeclaration();
|
|
1392
|
+
if (!withinImportStatement && !withinExportStatement) {
|
|
1393
|
+
getDependentIdentifiersForPath(topLevelStatement, {
|
|
1394
|
+
visited,
|
|
1395
|
+
identifiers
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
if (withinExportStatement && path7.isIdentifier() && (t.isPattern(path7.parentPath.node) || // [foo]
|
|
1399
|
+
t.isPattern(path7.parentPath.parentPath?.node))) {
|
|
1400
|
+
let variableDeclarator = path7.findParent((p) => p.isVariableDeclarator());
|
|
1401
|
+
assertNodePath(variableDeclarator);
|
|
1402
|
+
getDependentIdentifiersForPath(variableDeclarator, {
|
|
1403
|
+
visited,
|
|
1404
|
+
identifiers
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
return identifiers;
|
|
1408
|
+
}
|
|
1409
|
+
function getTopLevelStatementPathForPath(path7) {
|
|
1410
|
+
let ancestry = path7.getAncestry();
|
|
1411
|
+
let topLevelStatement = ancestry[ancestry.length - 2];
|
|
1412
|
+
assertNodePathIsStatement(topLevelStatement);
|
|
1413
|
+
return topLevelStatement;
|
|
1414
|
+
}
|
|
1415
|
+
function getTopLevelStatementsForPaths(paths) {
|
|
1416
|
+
let topLevelStatements = /* @__PURE__ */ new Set();
|
|
1417
|
+
for (let path7 of paths) {
|
|
1418
|
+
let topLevelStatement = getTopLevelStatementPathForPath(path7);
|
|
1419
|
+
topLevelStatements.add(topLevelStatement.node);
|
|
1420
|
+
}
|
|
1421
|
+
return topLevelStatements;
|
|
1422
|
+
}
|
|
1423
|
+
function getIdentifiersForPatternPath(patternPath, identifiers = /* @__PURE__ */ new Set()) {
|
|
1424
|
+
function walk(currentPath) {
|
|
1425
|
+
if (currentPath.isIdentifier()) {
|
|
1426
|
+
identifiers.add(currentPath);
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
if (currentPath.isObjectPattern()) {
|
|
1430
|
+
let { properties } = currentPath.node;
|
|
1431
|
+
for (let i = 0; i < properties.length; i++) {
|
|
1432
|
+
const property = properties[i];
|
|
1433
|
+
if (t.isObjectProperty(property)) {
|
|
1434
|
+
let valuePath = currentPath.get(`properties.${i}.value`);
|
|
1435
|
+
assertNodePath(valuePath);
|
|
1436
|
+
walk(valuePath);
|
|
1437
|
+
} else if (t.isRestElement(property)) {
|
|
1438
|
+
let argumentPath = currentPath.get(`properties.${i}.argument`);
|
|
1439
|
+
assertNodePath(argumentPath);
|
|
1440
|
+
walk(argumentPath);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
} else if (currentPath.isArrayPattern()) {
|
|
1444
|
+
let { elements } = currentPath.node;
|
|
1445
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1446
|
+
const element = elements[i];
|
|
1447
|
+
if (element) {
|
|
1448
|
+
let elementPath = currentPath.get(`elements.${i}`);
|
|
1449
|
+
assertNodePath(elementPath);
|
|
1450
|
+
walk(elementPath);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
} else if (currentPath.isRestElement()) {
|
|
1454
|
+
let argumentPath = currentPath.get("argument");
|
|
1455
|
+
assertNodePath(argumentPath);
|
|
1456
|
+
walk(argumentPath);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
walk(patternPath);
|
|
1460
|
+
return identifiers;
|
|
1461
|
+
}
|
|
1462
|
+
var getExportedName = (exported) => {
|
|
1463
|
+
return t.isIdentifier(exported) ? exported.name : exported.value;
|
|
1464
|
+
};
|
|
1465
|
+
function setsIntersect(set1, set2) {
|
|
1466
|
+
let smallerSet = set1;
|
|
1467
|
+
let largerSet = set2;
|
|
1468
|
+
if (set1.size > set2.size) {
|
|
1469
|
+
smallerSet = set2;
|
|
1470
|
+
largerSet = set1;
|
|
1471
|
+
}
|
|
1472
|
+
for (let element of smallerSet) {
|
|
1473
|
+
if (largerSet.has(element)) {
|
|
1474
|
+
return true;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
function hasChunkableExport(code, exportName, cache, cacheKey) {
|
|
1480
|
+
return getOrSetFromCache(
|
|
1481
|
+
cache,
|
|
1482
|
+
`${cacheKey}::hasChunkableExport::${exportName}`,
|
|
1483
|
+
code,
|
|
1484
|
+
() => {
|
|
1485
|
+
let exportDependencies = getExportDependencies(code, cache, cacheKey);
|
|
1486
|
+
let dependencies = exportDependencies.get(exportName);
|
|
1487
|
+
if (!dependencies) {
|
|
1488
|
+
return false;
|
|
1489
|
+
}
|
|
1490
|
+
for (let [currentExportName, currentDependencies] of exportDependencies) {
|
|
1491
|
+
if (currentExportName === exportName) {
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
if (setsIntersect(
|
|
1495
|
+
currentDependencies.topLevelNonModuleStatements,
|
|
1496
|
+
dependencies.topLevelNonModuleStatements
|
|
1497
|
+
)) {
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
if (dependencies.exportedVariableDeclarators.size > 1) {
|
|
1502
|
+
return false;
|
|
1503
|
+
}
|
|
1504
|
+
if (dependencies.exportedVariableDeclarators.size > 0) {
|
|
1505
|
+
for (let [
|
|
1506
|
+
currentExportName,
|
|
1507
|
+
currentDependencies
|
|
1508
|
+
] of exportDependencies) {
|
|
1509
|
+
if (currentExportName === exportName) {
|
|
1510
|
+
continue;
|
|
1511
|
+
}
|
|
1512
|
+
if (setsIntersect(
|
|
1513
|
+
currentDependencies.exportedVariableDeclarators,
|
|
1514
|
+
dependencies.exportedVariableDeclarators
|
|
1515
|
+
)) {
|
|
1516
|
+
return false;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return true;
|
|
1521
|
+
}
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1524
|
+
function getChunkedExport(code, exportName, generateOptions = {}, cache, cacheKey) {
|
|
1525
|
+
return getOrSetFromCache(
|
|
1526
|
+
cache,
|
|
1527
|
+
`${cacheKey}::getChunkedExport::${exportName}::${JSON.stringify(
|
|
1528
|
+
generateOptions
|
|
1529
|
+
)}`,
|
|
1530
|
+
code,
|
|
1531
|
+
() => {
|
|
1532
|
+
if (!hasChunkableExport(code, exportName, cache, cacheKey)) {
|
|
1533
|
+
return void 0;
|
|
1534
|
+
}
|
|
1535
|
+
let exportDependencies = getExportDependencies(code, cache, cacheKey);
|
|
1536
|
+
let dependencies = exportDependencies.get(exportName);
|
|
1537
|
+
invariant(dependencies, "Expected export to have dependencies");
|
|
1538
|
+
let topLevelStatementsArray = Array.from(dependencies.topLevelStatements);
|
|
1539
|
+
let exportedVariableDeclaratorsArray = Array.from(
|
|
1540
|
+
dependencies.exportedVariableDeclarators
|
|
1541
|
+
);
|
|
1542
|
+
let ast = codeToAst(code, cache, cacheKey);
|
|
1543
|
+
ast.program.body = ast.program.body.filter(
|
|
1544
|
+
(node) => topLevelStatementsArray.some(
|
|
1545
|
+
(statement) => t.isNodesEquivalent(node, statement)
|
|
1546
|
+
)
|
|
1547
|
+
).map((node) => {
|
|
1548
|
+
if (!t.isImportDeclaration(node)) {
|
|
1549
|
+
return node;
|
|
1550
|
+
}
|
|
1551
|
+
if (dependencies.importedIdentifierNames.size === 0) {
|
|
1552
|
+
return null;
|
|
1553
|
+
}
|
|
1554
|
+
node.specifiers = node.specifiers.filter(
|
|
1555
|
+
(specifier) => dependencies.importedIdentifierNames.has(specifier.local.name)
|
|
1556
|
+
);
|
|
1557
|
+
invariant(
|
|
1558
|
+
node.specifiers.length > 0,
|
|
1559
|
+
"Expected import statement to have used specifiers"
|
|
1560
|
+
);
|
|
1561
|
+
return node;
|
|
1562
|
+
}).map((node) => {
|
|
1563
|
+
if (!t.isExportDeclaration(node)) {
|
|
1564
|
+
return node;
|
|
1565
|
+
}
|
|
1566
|
+
if (t.isExportAllDeclaration(node)) {
|
|
1567
|
+
return null;
|
|
1568
|
+
}
|
|
1569
|
+
if (t.isExportDefaultDeclaration(node)) {
|
|
1570
|
+
return exportName === "default" ? node : null;
|
|
1571
|
+
}
|
|
1572
|
+
let { declaration } = node;
|
|
1573
|
+
if (t.isVariableDeclaration(declaration)) {
|
|
1574
|
+
declaration.declarations = declaration.declarations.filter(
|
|
1575
|
+
(node2) => exportedVariableDeclaratorsArray.some(
|
|
1576
|
+
(declarator) => t.isNodesEquivalent(node2, declarator)
|
|
1577
|
+
)
|
|
1578
|
+
);
|
|
1579
|
+
if (declaration.declarations.length === 0) {
|
|
1580
|
+
return null;
|
|
1581
|
+
}
|
|
1582
|
+
return node;
|
|
1583
|
+
}
|
|
1584
|
+
if (t.isFunctionDeclaration(node.declaration) || t.isClassDeclaration(node.declaration)) {
|
|
1585
|
+
return node.declaration.id?.name === exportName ? node : null;
|
|
1586
|
+
}
|
|
1587
|
+
if (t.isExportNamedDeclaration(node)) {
|
|
1588
|
+
if (node.specifiers.length === 0) {
|
|
1589
|
+
return null;
|
|
1590
|
+
}
|
|
1591
|
+
node.specifiers = node.specifiers.filter(
|
|
1592
|
+
(specifier) => getExportedName(specifier.exported) === exportName
|
|
1593
|
+
);
|
|
1594
|
+
if (node.specifiers.length === 0) {
|
|
1595
|
+
return null;
|
|
1596
|
+
}
|
|
1597
|
+
return node;
|
|
1598
|
+
}
|
|
1599
|
+
throw new Error(`Unknown export node type: ${node.type}`);
|
|
1600
|
+
}).filter((node) => node !== null);
|
|
1601
|
+
return generate2(ast, generateOptions);
|
|
1602
|
+
}
|
|
1603
|
+
);
|
|
1604
|
+
}
|
|
1605
|
+
function omitChunkedExports(code, exportNames, generateOptions = {}, cache, cacheKey) {
|
|
1606
|
+
return getOrSetFromCache(
|
|
1607
|
+
cache,
|
|
1608
|
+
`${cacheKey}::omitChunkedExports::${exportNames.join(
|
|
1609
|
+
","
|
|
1610
|
+
)}::${JSON.stringify(generateOptions)}`,
|
|
1611
|
+
code,
|
|
1612
|
+
() => {
|
|
1613
|
+
const isChunkable = (exportName) => hasChunkableExport(code, exportName, cache, cacheKey);
|
|
1614
|
+
const isOmitted = (exportName) => exportNames.includes(exportName) && isChunkable(exportName);
|
|
1615
|
+
const isRetained = (exportName) => !isOmitted(exportName);
|
|
1616
|
+
let exportDependencies = getExportDependencies(code, cache, cacheKey);
|
|
1617
|
+
let allExportNames = Array.from(exportDependencies.keys());
|
|
1618
|
+
let omittedExportNames = allExportNames.filter(isOmitted);
|
|
1619
|
+
let retainedExportNames = allExportNames.filter(isRetained);
|
|
1620
|
+
let omittedStatements = /* @__PURE__ */ new Set();
|
|
1621
|
+
let omittedExportedVariableDeclarators = /* @__PURE__ */ new Set();
|
|
1622
|
+
for (let omittedExportName of omittedExportNames) {
|
|
1623
|
+
let dependencies = exportDependencies.get(omittedExportName);
|
|
1624
|
+
invariant(
|
|
1625
|
+
dependencies,
|
|
1626
|
+
`Expected dependencies for ${omittedExportName}`
|
|
1627
|
+
);
|
|
1628
|
+
for (let statement of dependencies.topLevelNonModuleStatements) {
|
|
1629
|
+
omittedStatements.add(statement);
|
|
1630
|
+
}
|
|
1631
|
+
for (let declarator of dependencies.exportedVariableDeclarators) {
|
|
1632
|
+
omittedExportedVariableDeclarators.add(declarator);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
let ast = codeToAst(code, cache, cacheKey);
|
|
1636
|
+
let omittedStatementsArray = Array.from(omittedStatements);
|
|
1637
|
+
let omittedExportedVariableDeclaratorsArray = Array.from(
|
|
1638
|
+
omittedExportedVariableDeclarators
|
|
1639
|
+
);
|
|
1640
|
+
ast.program.body = ast.program.body.filter(
|
|
1641
|
+
(node) => omittedStatementsArray.every(
|
|
1642
|
+
(statement) => !t.isNodesEquivalent(node, statement)
|
|
1643
|
+
)
|
|
1644
|
+
).map((node) => {
|
|
1645
|
+
if (!t.isImportDeclaration(node)) {
|
|
1646
|
+
return node;
|
|
1647
|
+
}
|
|
1648
|
+
if (node.specifiers.length === 0) {
|
|
1649
|
+
return node;
|
|
1650
|
+
}
|
|
1651
|
+
node.specifiers = node.specifiers.filter((specifier) => {
|
|
1652
|
+
let importedName = specifier.local.name;
|
|
1653
|
+
for (let retainedExportName of retainedExportNames) {
|
|
1654
|
+
let dependencies = exportDependencies.get(retainedExportName);
|
|
1655
|
+
if (dependencies?.importedIdentifierNames?.has(importedName)) {
|
|
1656
|
+
return true;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
for (let omittedExportName of omittedExportNames) {
|
|
1660
|
+
let dependencies = exportDependencies.get(omittedExportName);
|
|
1661
|
+
if (dependencies?.importedIdentifierNames?.has(importedName)) {
|
|
1662
|
+
return false;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
return true;
|
|
1666
|
+
});
|
|
1667
|
+
if (node.specifiers.length === 0) {
|
|
1668
|
+
return null;
|
|
1669
|
+
}
|
|
1670
|
+
return node;
|
|
1671
|
+
}).map((node) => {
|
|
1672
|
+
if (!t.isExportDeclaration(node)) {
|
|
1673
|
+
return node;
|
|
1674
|
+
}
|
|
1675
|
+
if (t.isExportAllDeclaration(node)) {
|
|
1676
|
+
return node;
|
|
1677
|
+
}
|
|
1678
|
+
if (t.isExportDefaultDeclaration(node)) {
|
|
1679
|
+
return isOmitted("default") ? null : node;
|
|
1680
|
+
}
|
|
1681
|
+
if (t.isVariableDeclaration(node.declaration)) {
|
|
1682
|
+
node.declaration.declarations = node.declaration.declarations.filter(
|
|
1683
|
+
(node2) => omittedExportedVariableDeclaratorsArray.every(
|
|
1684
|
+
(declarator) => !t.isNodesEquivalent(node2, declarator)
|
|
1685
|
+
)
|
|
1686
|
+
);
|
|
1687
|
+
if (node.declaration.declarations.length === 0) {
|
|
1688
|
+
return null;
|
|
1689
|
+
}
|
|
1690
|
+
return node;
|
|
1691
|
+
}
|
|
1692
|
+
if (t.isFunctionDeclaration(node.declaration) || t.isClassDeclaration(node.declaration)) {
|
|
1693
|
+
invariant(
|
|
1694
|
+
node.declaration.id,
|
|
1695
|
+
"Expected exported function or class declaration to have a name when not the default export"
|
|
1696
|
+
);
|
|
1697
|
+
return isOmitted(node.declaration.id.name) ? null : node;
|
|
1698
|
+
}
|
|
1699
|
+
if (t.isExportNamedDeclaration(node)) {
|
|
1700
|
+
if (node.specifiers.length === 0) {
|
|
1701
|
+
return node;
|
|
1702
|
+
}
|
|
1703
|
+
node.specifiers = node.specifiers.filter((specifier) => {
|
|
1704
|
+
const exportedName = getExportedName(specifier.exported);
|
|
1705
|
+
return !isOmitted(exportedName);
|
|
1706
|
+
});
|
|
1707
|
+
if (node.specifiers.length === 0) {
|
|
1708
|
+
return null;
|
|
1709
|
+
}
|
|
1710
|
+
return node;
|
|
1711
|
+
}
|
|
1712
|
+
throw new Error(`Unknown node type: ${node.type}`);
|
|
1713
|
+
}).filter((node) => node !== null);
|
|
1714
|
+
if (ast.program.body.length === 0) {
|
|
1715
|
+
return void 0;
|
|
1716
|
+
}
|
|
1717
|
+
return generate2(ast, generateOptions);
|
|
1718
|
+
}
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
function detectRouteChunks(code, cache, cacheKey) {
|
|
1722
|
+
const hasRouteChunkByExportName = Object.fromEntries(
|
|
1723
|
+
routeChunkExportNames.map((exportName) => [
|
|
1724
|
+
exportName,
|
|
1725
|
+
hasChunkableExport(code, exportName, cache, cacheKey)
|
|
1726
|
+
])
|
|
1727
|
+
);
|
|
1728
|
+
const chunkedExports = Object.entries(hasRouteChunkByExportName).filter(([, isChunked]) => isChunked).map(([exportName]) => exportName);
|
|
1729
|
+
const hasRouteChunks = chunkedExports.length > 0;
|
|
1730
|
+
return {
|
|
1731
|
+
hasRouteChunks,
|
|
1732
|
+
hasRouteChunkByExportName,
|
|
1733
|
+
chunkedExports
|
|
1734
|
+
};
|
|
1735
|
+
}
|
|
1736
|
+
var routeChunkExportNames = [
|
|
1737
|
+
"clientAction",
|
|
1738
|
+
"clientLoader",
|
|
1739
|
+
"HydrateFallback"
|
|
1740
|
+
];
|
|
1741
|
+
var mainChunkName = "main";
|
|
1742
|
+
var routeChunkNames = ["main", ...routeChunkExportNames];
|
|
1743
|
+
function getRouteChunkCode(code, chunkName, cache, cacheKey) {
|
|
1744
|
+
if (chunkName === mainChunkName) {
|
|
1745
|
+
return omitChunkedExports(code, routeChunkExportNames, {}, cache, cacheKey);
|
|
1746
|
+
}
|
|
1747
|
+
return getChunkedExport(code, chunkName, {}, cache, cacheKey);
|
|
1748
|
+
}
|
|
1749
|
+
var routeChunkQueryStringPrefix = "?route-chunk=";
|
|
1750
|
+
var routeChunkQueryStrings = {
|
|
1751
|
+
main: `${routeChunkQueryStringPrefix}main`,
|
|
1752
|
+
clientAction: `${routeChunkQueryStringPrefix}clientAction`,
|
|
1753
|
+
clientLoader: `${routeChunkQueryStringPrefix}clientLoader`,
|
|
1754
|
+
HydrateFallback: `${routeChunkQueryStringPrefix}HydrateFallback`
|
|
1755
|
+
};
|
|
1756
|
+
function getRouteChunkModuleId(filePath, chunkName) {
|
|
1757
|
+
return `${filePath}${routeChunkQueryStrings[chunkName]}`;
|
|
1758
|
+
}
|
|
1759
|
+
function isRouteChunkModuleId(id) {
|
|
1760
|
+
return Object.values(routeChunkQueryStrings).some(
|
|
1761
|
+
(queryString) => id.endsWith(queryString)
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
function isRouteChunkName(name) {
|
|
1765
|
+
return name === mainChunkName || routeChunkExportNames.includes(name);
|
|
1766
|
+
}
|
|
1767
|
+
function getRouteChunkNameFromModuleId(id) {
|
|
1768
|
+
if (!isRouteChunkModuleId(id)) {
|
|
1769
|
+
return null;
|
|
1770
|
+
}
|
|
1771
|
+
let chunkName = id.split(routeChunkQueryStringPrefix)[1].split("&")[0];
|
|
1772
|
+
if (!isRouteChunkName(chunkName)) {
|
|
1773
|
+
return null;
|
|
1774
|
+
}
|
|
1775
|
+
return chunkName;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1162
1778
|
// vite/with-props.ts
|
|
1163
1779
|
var import_dedent2 = __toESM(require("dedent"));
|
|
1164
1780
|
var vmod = create("with-props");
|
|
@@ -1191,6 +1807,8 @@ var plugin = {
|
|
|
1191
1807
|
return function Wrapped() {
|
|
1192
1808
|
const props = {
|
|
1193
1809
|
params: useParams(),
|
|
1810
|
+
loaderData: useLoaderData(),
|
|
1811
|
+
actionData: useActionData(),
|
|
1194
1812
|
};
|
|
1195
1813
|
return h(HydrateFallback, props);
|
|
1196
1814
|
};
|
|
@@ -1298,8 +1916,34 @@ var CLIENT_ROUTE_EXPORTS = [
|
|
|
1298
1916
|
"shouldRevalidate"
|
|
1299
1917
|
];
|
|
1300
1918
|
var BUILD_CLIENT_ROUTE_QUERY_STRING = "?__react-router-build-client-route";
|
|
1919
|
+
var SSR_BUNDLE_PREFIX = "ssrBundle_";
|
|
1920
|
+
function isSeverBundleEnvironmentName(name) {
|
|
1921
|
+
return name.startsWith(SSR_BUNDLE_PREFIX);
|
|
1922
|
+
}
|
|
1923
|
+
function getServerEnvironmentEntries(record, buildManifest) {
|
|
1924
|
+
return Object.entries(record).filter(
|
|
1925
|
+
([name]) => buildManifest.serverBundles ? isSeverBundleEnvironmentName(name) : name === "ssr"
|
|
1926
|
+
);
|
|
1927
|
+
}
|
|
1928
|
+
function getServerEnvironmentValues(record, buildManifest) {
|
|
1929
|
+
return getServerEnvironmentEntries(record, buildManifest).map(
|
|
1930
|
+
([, value]) => value
|
|
1931
|
+
);
|
|
1932
|
+
}
|
|
1933
|
+
var isRouteEntryModuleId = (id) => {
|
|
1934
|
+
return id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING);
|
|
1935
|
+
};
|
|
1936
|
+
var isRouteVirtualModule = (id) => {
|
|
1937
|
+
return isRouteEntryModuleId(id) || isRouteChunkModuleId(id);
|
|
1938
|
+
};
|
|
1301
1939
|
var virtualHmrRuntime = create("hmr-runtime");
|
|
1302
1940
|
var virtualInjectHmrRuntime = create("inject-hmr-runtime");
|
|
1941
|
+
var normalizeRelativeFilePath = (file, reactRouterConfig) => {
|
|
1942
|
+
let vite2 = getVite();
|
|
1943
|
+
let fullPath = path6.resolve(reactRouterConfig.appDirectory, file);
|
|
1944
|
+
let relativePath = path6.relative(reactRouterConfig.appDirectory, fullPath);
|
|
1945
|
+
return vite2.normalizePath(relativePath).split("?")[0];
|
|
1946
|
+
};
|
|
1303
1947
|
var resolveRelativeRouteFilePath = (route, reactRouterConfig) => {
|
|
1304
1948
|
let vite2 = getVite();
|
|
1305
1949
|
let file = route.file;
|
|
@@ -1328,23 +1972,35 @@ var resolveChunk = (ctx, viteManifest, absoluteFilePath) => {
|
|
|
1328
1972
|
let rootRelativeFilePath = vite2.normalizePath(
|
|
1329
1973
|
path6.relative(ctx.rootDirectory, absoluteFilePath)
|
|
1330
1974
|
);
|
|
1331
|
-
let entryChunk = viteManifest[rootRelativeFilePath
|
|
1975
|
+
let entryChunk = viteManifest[rootRelativeFilePath];
|
|
1332
1976
|
if (!entryChunk) {
|
|
1333
|
-
|
|
1334
|
-
throw new Error(
|
|
1335
|
-
`No manifest entry found for "${rootRelativeFilePath}". Known manifest keys: ${knownManifestKeys}`
|
|
1336
|
-
);
|
|
1977
|
+
return void 0;
|
|
1337
1978
|
}
|
|
1338
1979
|
return entryChunk;
|
|
1339
1980
|
};
|
|
1981
|
+
var getPublicModulePathForEntry = (ctx, viteManifest, entryFilePath) => {
|
|
1982
|
+
let entryChunk = resolveChunk(ctx, viteManifest, entryFilePath);
|
|
1983
|
+
return entryChunk ? `${ctx.publicPath}${entryChunk.file}` : void 0;
|
|
1984
|
+
};
|
|
1340
1985
|
var getReactRouterManifestBuildAssets = (ctx, viteManifest, entryFilePath, prependedAssetFilePaths = []) => {
|
|
1341
1986
|
let entryChunk = resolveChunk(ctx, viteManifest, entryFilePath);
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1987
|
+
invariant(entryChunk, "Chunk not found");
|
|
1988
|
+
let prependedAssetChunks = prependedAssetFilePaths.map((filePath) => {
|
|
1989
|
+
let chunk = resolveChunk(ctx, viteManifest, filePath);
|
|
1990
|
+
invariant(chunk, "Chunk not found");
|
|
1991
|
+
return chunk;
|
|
1992
|
+
});
|
|
1993
|
+
let routeModuleChunks = routeChunkNames.map(
|
|
1994
|
+
(routeChunkName) => resolveChunk(
|
|
1995
|
+
ctx,
|
|
1996
|
+
viteManifest,
|
|
1997
|
+
getRouteChunkModuleId(entryFilePath.split("?")[0], routeChunkName)
|
|
1998
|
+
)
|
|
1999
|
+
).filter(isNonNullable);
|
|
1345
2000
|
let chunks = resolveDependantChunks(viteManifest, [
|
|
1346
2001
|
...prependedAssetChunks,
|
|
1347
|
-
entryChunk
|
|
2002
|
+
entryChunk,
|
|
2003
|
+
...routeModuleChunks
|
|
1348
2004
|
]);
|
|
1349
2005
|
return {
|
|
1350
2006
|
module: `${ctx.publicPath}${entryChunk.file}`,
|
|
@@ -1381,6 +2037,10 @@ var writeFileSafe = async (file, contents) => {
|
|
|
1381
2037
|
await fse.ensureDir(path6.dirname(file));
|
|
1382
2038
|
await fse.writeFile(file, contents);
|
|
1383
2039
|
};
|
|
2040
|
+
var getExportNames = (code) => {
|
|
2041
|
+
let [, exportSpecifiers] = (0, import_es_module_lexer.parse)(code);
|
|
2042
|
+
return exportSpecifiers.map(({ n: name }) => name);
|
|
2043
|
+
};
|
|
1384
2044
|
var getRouteManifestModuleExports = async (viteChildCompiler, ctx) => {
|
|
1385
2045
|
let entries = await Promise.all(
|
|
1386
2046
|
Object.entries(ctx.reactRouterConfig.routes).map(async ([key, route]) => {
|
|
@@ -1394,7 +2054,7 @@ var getRouteManifestModuleExports = async (viteChildCompiler, ctx) => {
|
|
|
1394
2054
|
);
|
|
1395
2055
|
return Object.fromEntries(entries);
|
|
1396
2056
|
};
|
|
1397
|
-
var
|
|
2057
|
+
var compileRouteFile = async (viteChildCompiler, ctx, routeFile, readRouteFile) => {
|
|
1398
2058
|
if (!viteChildCompiler) {
|
|
1399
2059
|
throw new Error("Vite child compiler not found");
|
|
1400
2060
|
}
|
|
@@ -1414,20 +2074,38 @@ var getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRouteF
|
|
|
1414
2074
|
moduleGraph.ensureEntryFromUrl(url2, ssr)
|
|
1415
2075
|
]);
|
|
1416
2076
|
let transformed = await pluginContainer.transform(code, id, { ssr });
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
2077
|
+
return transformed.code;
|
|
2078
|
+
};
|
|
2079
|
+
var getRouteModuleExports = async (viteChildCompiler, ctx, routeFile, readRouteFile) => {
|
|
2080
|
+
if (!viteChildCompiler) {
|
|
2081
|
+
throw new Error("Vite child compiler not found");
|
|
2082
|
+
}
|
|
2083
|
+
let code = await compileRouteFile(
|
|
2084
|
+
viteChildCompiler,
|
|
2085
|
+
ctx,
|
|
2086
|
+
routeFile,
|
|
2087
|
+
readRouteFile
|
|
2088
|
+
);
|
|
2089
|
+
return getExportNames(code);
|
|
1420
2090
|
};
|
|
1421
|
-
var
|
|
1422
|
-
|
|
2091
|
+
var resolveEnvironmentBuildContext = ({
|
|
2092
|
+
viteCommand,
|
|
2093
|
+
viteUserConfig
|
|
2094
|
+
}) => {
|
|
2095
|
+
if (!("__reactRouterEnvironmentBuildContext" in viteUserConfig) || !viteUserConfig.__reactRouterEnvironmentBuildContext) {
|
|
1423
2096
|
return null;
|
|
1424
2097
|
}
|
|
1425
|
-
|
|
2098
|
+
let buildContext = viteUserConfig.__reactRouterEnvironmentBuildContext;
|
|
2099
|
+
let resolvedBuildContext = {
|
|
2100
|
+
name: buildContext.name,
|
|
2101
|
+
options: buildContext.resolveOptions({ viteUserConfig })
|
|
2102
|
+
};
|
|
2103
|
+
return resolvedBuildContext;
|
|
1426
2104
|
};
|
|
1427
|
-
var getServerBuildDirectory = (ctx) => path6.join(
|
|
2105
|
+
var getServerBuildDirectory = (ctx, { serverBundleId } = {}) => path6.join(
|
|
1428
2106
|
ctx.reactRouterConfig.buildDirectory,
|
|
1429
2107
|
"server",
|
|
1430
|
-
...
|
|
2108
|
+
...serverBundleId ? [serverBundleId] : []
|
|
1431
2109
|
);
|
|
1432
2110
|
var getClientBuildDirectory = (reactRouterConfig) => path6.join(reactRouterConfig.buildDirectory, "client");
|
|
1433
2111
|
var defaultEntriesDir = path6.resolve(
|
|
@@ -1445,8 +2123,10 @@ var reactRouterVitePlugin = () => {
|
|
|
1445
2123
|
let viteUserConfig;
|
|
1446
2124
|
let viteConfigEnv;
|
|
1447
2125
|
let viteConfig;
|
|
2126
|
+
let buildManifest;
|
|
1448
2127
|
let cssModulesManifest = {};
|
|
1449
2128
|
let viteChildCompiler = null;
|
|
2129
|
+
let cache = /* @__PURE__ */ new Map();
|
|
1450
2130
|
let reactRouterConfigLoader;
|
|
1451
2131
|
let typegenWatcherPromise;
|
|
1452
2132
|
let logger;
|
|
@@ -1478,36 +2158,37 @@ var reactRouterVitePlugin = () => {
|
|
|
1478
2158
|
process.exit(1);
|
|
1479
2159
|
}
|
|
1480
2160
|
let viteManifestEnabled = viteUserConfig.build?.manifest === true;
|
|
1481
|
-
let
|
|
1482
|
-
isSsrBuild: true,
|
|
1483
|
-
getReactRouterServerManifest: async () => (await generateReactRouterManifestsForBuild()).reactRouterServerManifest,
|
|
1484
|
-
serverBundleBuildConfig: getServerBundleBuildConfig(viteUserConfig)
|
|
1485
|
-
} : { isSsrBuild: false };
|
|
2161
|
+
let environmentBuildContext = viteCommand === "build" ? resolveEnvironmentBuildContext({ viteCommand, viteUserConfig }) : null;
|
|
1486
2162
|
firstLoad = false;
|
|
1487
2163
|
ctx = {
|
|
2164
|
+
environmentBuildContext,
|
|
1488
2165
|
reactRouterConfig,
|
|
1489
2166
|
rootDirectory,
|
|
1490
2167
|
entryClientFilePath,
|
|
1491
2168
|
entryServerFilePath,
|
|
1492
2169
|
publicPath,
|
|
1493
|
-
viteManifestEnabled
|
|
1494
|
-
...ssrBuildCtx
|
|
2170
|
+
viteManifestEnabled
|
|
1495
2171
|
};
|
|
1496
2172
|
};
|
|
1497
2173
|
let pluginIndex = (pluginName) => {
|
|
1498
2174
|
invariant(viteConfig);
|
|
1499
2175
|
return viteConfig.plugins.findIndex((plugin2) => plugin2.name === pluginName);
|
|
1500
2176
|
};
|
|
1501
|
-
let getServerEntry = async () => {
|
|
2177
|
+
let getServerEntry = async ({ routeIds }) => {
|
|
1502
2178
|
invariant(viteConfig, "viteconfig required to generate the server entry");
|
|
1503
|
-
let routes =
|
|
2179
|
+
let routes = routeIds ? (
|
|
1504
2180
|
// For server bundle builds, the server build should only import the
|
|
1505
2181
|
// routes for this bundle rather than importing all routes
|
|
1506
|
-
ctx.
|
|
2182
|
+
(0, import_pick3.default)(ctx.reactRouterConfig.routes, routeIds)
|
|
1507
2183
|
) : (
|
|
1508
2184
|
// Otherwise, all routes are imported as usual
|
|
1509
2185
|
ctx.reactRouterConfig.routes
|
|
1510
2186
|
);
|
|
2187
|
+
let prerenderPaths = await getPrerenderPaths(
|
|
2188
|
+
ctx.reactRouterConfig.prerender,
|
|
2189
|
+
ctx.reactRouterConfig.ssr,
|
|
2190
|
+
routes
|
|
2191
|
+
);
|
|
1511
2192
|
return `
|
|
1512
2193
|
import * as entryServer from ${JSON.stringify(
|
|
1513
2194
|
resolveFileUrl(ctx, ctx.entryServerFilePath)
|
|
@@ -1522,7 +2203,7 @@ var reactRouterVitePlugin = () => {
|
|
|
1522
2203
|
)};`;
|
|
1523
2204
|
}).join("\n")}
|
|
1524
2205
|
export { default as assets } from ${JSON.stringify(
|
|
1525
|
-
virtual.serverManifest.id
|
|
2206
|
+
`${virtual.serverManifest.id}${routeIds ? `?route-ids=${routeIds.join(",")}` : ""}`
|
|
1526
2207
|
)};
|
|
1527
2208
|
export const assetsBuildDirectory = ${JSON.stringify(
|
|
1528
2209
|
path6.relative(
|
|
@@ -1532,7 +2213,9 @@ var reactRouterVitePlugin = () => {
|
|
|
1532
2213
|
)};
|
|
1533
2214
|
export const basename = ${JSON.stringify(ctx.reactRouterConfig.basename)};
|
|
1534
2215
|
export const future = ${JSON.stringify(ctx.reactRouterConfig.future)};
|
|
1535
|
-
export const
|
|
2216
|
+
export const ssr = ${ctx.reactRouterConfig.ssr};
|
|
2217
|
+
export const isSpaMode = ${isSpaModeEnabled(ctx.reactRouterConfig)};
|
|
2218
|
+
export const prerender = ${JSON.stringify(prerenderPaths)};
|
|
1536
2219
|
export const publicPath = ${JSON.stringify(ctx.publicPath)};
|
|
1537
2220
|
export const entry = { module: entryServer };
|
|
1538
2221
|
export const routes = {
|
|
@@ -1570,7 +2253,9 @@ var reactRouterVitePlugin = () => {
|
|
|
1570
2253
|
);
|
|
1571
2254
|
return /* @__PURE__ */ new Set([...cssUrlPaths, ...chunkAssetPaths]);
|
|
1572
2255
|
};
|
|
1573
|
-
let generateReactRouterManifestsForBuild = async (
|
|
2256
|
+
let generateReactRouterManifestsForBuild = async ({
|
|
2257
|
+
routeIds
|
|
2258
|
+
}) => {
|
|
1574
2259
|
invariant(viteConfig);
|
|
1575
2260
|
let viteManifest = await loadViteManifest(
|
|
1576
2261
|
getClientBuildDirectory(ctx.reactRouterConfig)
|
|
@@ -1586,13 +2271,31 @@ var reactRouterVitePlugin = () => {
|
|
|
1586
2271
|
viteChildCompiler,
|
|
1587
2272
|
ctx
|
|
1588
2273
|
);
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
);
|
|
1594
|
-
let sourceExports = routeManifestExports[key];
|
|
2274
|
+
let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
|
|
2275
|
+
for (let route of Object.values(ctx.reactRouterConfig.routes)) {
|
|
2276
|
+
let routeFile = path6.join(ctx.reactRouterConfig.appDirectory, route.file);
|
|
2277
|
+
let sourceExports = routeManifestExports[route.id];
|
|
1595
2278
|
let isRootRoute = route.parentId === void 0;
|
|
2279
|
+
let hasClientAction = sourceExports.includes("clientAction");
|
|
2280
|
+
let hasClientLoader = sourceExports.includes("clientLoader");
|
|
2281
|
+
let hasHydrateFallback = sourceExports.includes("HydrateFallback");
|
|
2282
|
+
let { hasRouteChunkByExportName } = await detectRouteChunksIfEnabled(
|
|
2283
|
+
cache,
|
|
2284
|
+
ctx,
|
|
2285
|
+
routeFile,
|
|
2286
|
+
{ routeFile, viteChildCompiler }
|
|
2287
|
+
);
|
|
2288
|
+
if (enforceSplitRouteModules) {
|
|
2289
|
+
validateRouteChunks({
|
|
2290
|
+
ctx,
|
|
2291
|
+
id: route.file,
|
|
2292
|
+
valid: {
|
|
2293
|
+
clientAction: !hasClientAction || hasRouteChunkByExportName.clientAction,
|
|
2294
|
+
clientLoader: !hasClientLoader || hasRouteChunkByExportName.clientLoader,
|
|
2295
|
+
HydrateFallback: !hasHydrateFallback || hasRouteChunkByExportName.HydrateFallback
|
|
2296
|
+
}
|
|
2297
|
+
});
|
|
2298
|
+
}
|
|
1596
2299
|
let routeManifestEntry = {
|
|
1597
2300
|
id: route.id,
|
|
1598
2301
|
parentId: route.parentId,
|
|
@@ -1601,23 +2304,37 @@ var reactRouterVitePlugin = () => {
|
|
|
1601
2304
|
caseSensitive: route.caseSensitive,
|
|
1602
2305
|
hasAction: sourceExports.includes("action"),
|
|
1603
2306
|
hasLoader: sourceExports.includes("loader"),
|
|
1604
|
-
hasClientAction
|
|
1605
|
-
hasClientLoader
|
|
2307
|
+
hasClientAction,
|
|
2308
|
+
hasClientLoader,
|
|
1606
2309
|
hasErrorBoundary: sourceExports.includes("ErrorBoundary"),
|
|
1607
2310
|
...getReactRouterManifestBuildAssets(
|
|
1608
2311
|
ctx,
|
|
1609
2312
|
viteManifest,
|
|
1610
|
-
|
|
2313
|
+
`${routeFile}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
|
|
1611
2314
|
// If this is the root route, we also need to include assets from the
|
|
1612
2315
|
// client entry file as this is a common way for consumers to import
|
|
1613
2316
|
// global reset styles, etc.
|
|
1614
2317
|
isRootRoute ? [ctx.entryClientFilePath] : []
|
|
1615
|
-
)
|
|
2318
|
+
),
|
|
2319
|
+
clientActionModule: hasRouteChunkByExportName.clientAction ? getPublicModulePathForEntry(
|
|
2320
|
+
ctx,
|
|
2321
|
+
viteManifest,
|
|
2322
|
+
getRouteChunkModuleId(routeFile, "clientAction")
|
|
2323
|
+
) : void 0,
|
|
2324
|
+
clientLoaderModule: hasRouteChunkByExportName.clientLoader ? getPublicModulePathForEntry(
|
|
2325
|
+
ctx,
|
|
2326
|
+
viteManifest,
|
|
2327
|
+
getRouteChunkModuleId(routeFile, "clientLoader")
|
|
2328
|
+
) : void 0,
|
|
2329
|
+
hydrateFallbackModule: hasRouteChunkByExportName.HydrateFallback ? getPublicModulePathForEntry(
|
|
2330
|
+
ctx,
|
|
2331
|
+
viteManifest,
|
|
2332
|
+
getRouteChunkModuleId(routeFile, "HydrateFallback")
|
|
2333
|
+
) : void 0
|
|
1616
2334
|
};
|
|
1617
|
-
browserRoutes[
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
serverRoutes[key] = routeManifestEntry;
|
|
2335
|
+
browserRoutes[route.id] = routeManifestEntry;
|
|
2336
|
+
if (!routeIds || routeIds.includes(route.id)) {
|
|
2337
|
+
serverRoutes[route.id] = routeManifestEntry;
|
|
1621
2338
|
}
|
|
1622
2339
|
}
|
|
1623
2340
|
let fingerprintedValues = { entry, routes: browserRoutes };
|
|
@@ -1653,25 +2370,52 @@ var reactRouterVitePlugin = () => {
|
|
|
1653
2370
|
viteChildCompiler,
|
|
1654
2371
|
ctx
|
|
1655
2372
|
);
|
|
2373
|
+
let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
|
|
1656
2374
|
for (let [key, route] of Object.entries(ctx.reactRouterConfig.routes)) {
|
|
2375
|
+
let routeFile = route.file;
|
|
1657
2376
|
let sourceExports = routeManifestExports[key];
|
|
2377
|
+
let hasClientAction = sourceExports.includes("clientAction");
|
|
2378
|
+
let hasClientLoader = sourceExports.includes("clientLoader");
|
|
2379
|
+
let hasHydrateFallback = sourceExports.includes("HydrateFallback");
|
|
2380
|
+
let routeModulePath = combineURLs(
|
|
2381
|
+
ctx.publicPath,
|
|
2382
|
+
`${resolveFileUrl(
|
|
2383
|
+
ctx,
|
|
2384
|
+
resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
|
|
2385
|
+
)}`
|
|
2386
|
+
);
|
|
2387
|
+
if (enforceSplitRouteModules) {
|
|
2388
|
+
let { hasRouteChunkByExportName } = await detectRouteChunksIfEnabled(
|
|
2389
|
+
cache,
|
|
2390
|
+
ctx,
|
|
2391
|
+
routeFile,
|
|
2392
|
+
{ routeFile, viteChildCompiler }
|
|
2393
|
+
);
|
|
2394
|
+
validateRouteChunks({
|
|
2395
|
+
ctx,
|
|
2396
|
+
id: route.file,
|
|
2397
|
+
valid: {
|
|
2398
|
+
clientAction: !hasClientAction || hasRouteChunkByExportName.clientAction,
|
|
2399
|
+
clientLoader: !hasClientLoader || hasRouteChunkByExportName.clientLoader,
|
|
2400
|
+
HydrateFallback: !hasHydrateFallback || hasRouteChunkByExportName.HydrateFallback
|
|
2401
|
+
}
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
1658
2404
|
routes[key] = {
|
|
1659
2405
|
id: route.id,
|
|
1660
2406
|
parentId: route.parentId,
|
|
1661
2407
|
path: route.path,
|
|
1662
2408
|
index: route.index,
|
|
1663
2409
|
caseSensitive: route.caseSensitive,
|
|
1664
|
-
module:
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
)
|
|
1670
|
-
),
|
|
2410
|
+
module: routeModulePath,
|
|
2411
|
+
// Split route modules are a build-time optimization
|
|
2412
|
+
clientActionModule: void 0,
|
|
2413
|
+
clientLoaderModule: void 0,
|
|
2414
|
+
hydrateFallbackModule: void 0,
|
|
1671
2415
|
hasAction: sourceExports.includes("action"),
|
|
1672
2416
|
hasLoader: sourceExports.includes("loader"),
|
|
1673
|
-
hasClientAction
|
|
1674
|
-
hasClientLoader
|
|
2417
|
+
hasClientAction,
|
|
2418
|
+
hasClientLoader,
|
|
1675
2419
|
hasErrorBoundary: sourceExports.includes("ErrorBoundary"),
|
|
1676
2420
|
imports: []
|
|
1677
2421
|
};
|
|
@@ -1704,14 +2448,6 @@ var reactRouterVitePlugin = () => {
|
|
|
1704
2448
|
let viteClientConditions = [
|
|
1705
2449
|
...vite2.defaultClientConditions ?? []
|
|
1706
2450
|
];
|
|
1707
|
-
let packageRoot = path6.dirname(
|
|
1708
|
-
require.resolve("@react-router/dev/package.json")
|
|
1709
|
-
);
|
|
1710
|
-
let { moduleSyncEnabled } = await import(`file:///${path6.join(packageRoot, "module-sync-enabled/index.mjs")}`);
|
|
1711
|
-
let viteServerConditions = [
|
|
1712
|
-
...vite2.defaultServerConditions ?? [],
|
|
1713
|
-
...moduleSyncEnabled ? ["module-sync"] : []
|
|
1714
|
-
];
|
|
1715
2451
|
logger = vite2.createLogger(viteUserConfig.logLevel, {
|
|
1716
2452
|
prefix: "[react-router]"
|
|
1717
2453
|
});
|
|
@@ -1727,43 +2463,37 @@ var reactRouterVitePlugin = () => {
|
|
|
1727
2463
|
watch: viteCommand === "serve"
|
|
1728
2464
|
});
|
|
1729
2465
|
await updatePluginContext();
|
|
2466
|
+
buildManifest = await getBuildManifest(ctx);
|
|
1730
2467
|
Object.assign(
|
|
1731
2468
|
process.env,
|
|
1732
2469
|
vite2.loadEnv(
|
|
1733
2470
|
viteConfigEnv.mode,
|
|
1734
|
-
ctx.rootDirectory,
|
|
2471
|
+
viteUserConfig.envDir ?? ctx.rootDirectory,
|
|
1735
2472
|
// We override default prefix of "VITE_" with a blank string since
|
|
1736
2473
|
// we're targeting the server, so we want to load all environment
|
|
1737
2474
|
// variables, not just those explicitly marked for the client
|
|
1738
2475
|
""
|
|
1739
2476
|
)
|
|
1740
2477
|
);
|
|
1741
|
-
let
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
defaultHandler(warning);
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
};
|
|
2478
|
+
let environments = await getEnvironmentsOptions(
|
|
2479
|
+
ctx,
|
|
2480
|
+
buildManifest,
|
|
2481
|
+
viteCommand,
|
|
2482
|
+
{ viteUserConfig }
|
|
2483
|
+
);
|
|
2484
|
+
let serverEnvironment = getServerEnvironmentValues(
|
|
2485
|
+
environments,
|
|
2486
|
+
buildManifest
|
|
2487
|
+
)[0];
|
|
2488
|
+
invariant(serverEnvironment);
|
|
2489
|
+
let clientEnvironment = environments.client;
|
|
2490
|
+
invariant(clientEnvironment);
|
|
1758
2491
|
return {
|
|
1759
2492
|
__reactRouterPluginContext: ctx,
|
|
1760
2493
|
appType: viteCommand === "serve" && viteConfigEnv.mode === "production" && ctx.reactRouterConfig.ssr === false ? "spa" : "custom",
|
|
1761
2494
|
ssr: {
|
|
1762
|
-
external:
|
|
1763
|
-
resolve:
|
|
1764
|
-
conditions: viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions],
|
|
1765
|
-
externalConditions: viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions]
|
|
1766
|
-
}
|
|
2495
|
+
external: serverEnvironment.resolve?.external,
|
|
2496
|
+
resolve: serverEnvironment.resolve
|
|
1767
2497
|
},
|
|
1768
2498
|
optimizeDeps: {
|
|
1769
2499
|
entries: ctx.reactRouterConfig.future.unstable_optimizeDeps ? [
|
|
@@ -1812,57 +2542,41 @@ var reactRouterVitePlugin = () => {
|
|
|
1812
2542
|
// will throw an error that the file is not allowed to be read.
|
|
1813
2543
|
// https://vitejs.dev/config/server-options#server-fs-allow
|
|
1814
2544
|
server: viteUserConfig.server?.fs?.allow ? { fs: { allow: defaultEntries } } : void 0,
|
|
1815
|
-
|
|
1816
|
-
|
|
2545
|
+
...ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? {
|
|
2546
|
+
environments,
|
|
1817
2547
|
build: {
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
// We need the manifest to detect SSR-only assets
|
|
1846
|
-
outDir: getServerBuildDirectory(ctx),
|
|
1847
|
-
rollupOptions: {
|
|
1848
|
-
...baseRollupOptions,
|
|
1849
|
-
preserveEntrySignatures: "exports-only",
|
|
1850
|
-
input: viteUserConfig.build?.rollupOptions?.input ?? virtual.serverBuild.id,
|
|
1851
|
-
output: {
|
|
1852
|
-
entryFileNames: ctx.reactRouterConfig.serverBuildFile,
|
|
1853
|
-
format: ctx.reactRouterConfig.serverModuleFormat
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
2548
|
+
// This isn't honored by the SSR environment config (which seems
|
|
2549
|
+
// to be a Vite bug?) so we set it here too.
|
|
2550
|
+
ssrEmitAssets: true
|
|
2551
|
+
},
|
|
2552
|
+
builder: {
|
|
2553
|
+
sharedConfigBuild: true,
|
|
2554
|
+
sharedPlugins: true,
|
|
2555
|
+
async buildApp(builder) {
|
|
2556
|
+
invariant(viteConfig);
|
|
2557
|
+
invariant(buildManifest);
|
|
2558
|
+
viteConfig.logger.info(
|
|
2559
|
+
"Using Vite Environment API (experimental)"
|
|
2560
|
+
);
|
|
2561
|
+
let { reactRouterConfig } = ctx;
|
|
2562
|
+
await cleanBuildDirectory(viteConfig, ctx);
|
|
2563
|
+
await builder.build(builder.environments.client);
|
|
2564
|
+
let serverEnvironments = getServerEnvironmentValues(
|
|
2565
|
+
builder.environments,
|
|
2566
|
+
buildManifest
|
|
2567
|
+
);
|
|
2568
|
+
await Promise.all(serverEnvironments.map(builder.build));
|
|
2569
|
+
await cleanViteManifests(environments, ctx);
|
|
2570
|
+
await reactRouterConfig.buildEnd?.({
|
|
2571
|
+
buildManifest,
|
|
2572
|
+
reactRouterConfig,
|
|
2573
|
+
viteConfig
|
|
2574
|
+
});
|
|
1856
2575
|
}
|
|
1857
2576
|
}
|
|
1858
|
-
} :
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
build: {
|
|
1862
|
-
manifest: true,
|
|
1863
|
-
outDir: getClientBuildDirectory(ctx.reactRouterConfig)
|
|
1864
|
-
}
|
|
1865
|
-
} : void 0
|
|
2577
|
+
} : {
|
|
2578
|
+
build: ctx.environmentBuildContext?.options.build ?? (viteConfigEnv.isSsrBuild ? serverEnvironment.build : clientEnvironment.build)
|
|
2579
|
+
}
|
|
1866
2580
|
};
|
|
1867
2581
|
},
|
|
1868
2582
|
async configResolved(resolvedViteConfig) {
|
|
@@ -1878,8 +2592,7 @@ var reactRouterVitePlugin = () => {
|
|
|
1878
2592
|
let childCompilerConfigFile = await vite2.loadConfigFromFile(
|
|
1879
2593
|
{
|
|
1880
2594
|
command: viteConfig.command,
|
|
1881
|
-
mode: viteConfig.mode
|
|
1882
|
-
isSsrBuild: ctx.isSsrBuild
|
|
2595
|
+
mode: viteConfig.mode
|
|
1883
2596
|
},
|
|
1884
2597
|
viteConfig.configFile
|
|
1885
2598
|
);
|
|
@@ -2021,14 +2734,15 @@ var reactRouterVitePlugin = () => {
|
|
|
2021
2734
|
// After the SSR build is finished, we inspect the Vite manifest for
|
|
2022
2735
|
// the SSR build and move server-only assets to client assets directory
|
|
2023
2736
|
async handler() {
|
|
2024
|
-
|
|
2737
|
+
let { future } = ctx.reactRouterConfig;
|
|
2738
|
+
if (future.unstable_viteEnvironmentApi ? this.environment.name === "client" : !viteConfigEnv.isSsrBuild) {
|
|
2025
2739
|
return;
|
|
2026
2740
|
}
|
|
2027
2741
|
invariant(viteConfig);
|
|
2028
2742
|
let clientBuildDirectory = getClientBuildDirectory(
|
|
2029
2743
|
ctx.reactRouterConfig
|
|
2030
2744
|
);
|
|
2031
|
-
let serverBuildDirectory = getServerBuildDirectory(ctx);
|
|
2745
|
+
let serverBuildDirectory = future.unstable_viteEnvironmentApi ? this.environment.config?.build?.outDir : ctx.environmentBuildContext?.options.build?.outDir ?? getServerBuildDirectory(ctx);
|
|
2032
2746
|
let ssrViteManifest = await loadViteManifest(serverBuildDirectory);
|
|
2033
2747
|
let ssrAssetPaths = getViteManifestAssetPaths(ssrViteManifest);
|
|
2034
2748
|
let movedAssetPaths = [];
|
|
@@ -2062,7 +2776,7 @@ var reactRouterVitePlugin = () => {
|
|
|
2062
2776
|
].join("\n")
|
|
2063
2777
|
);
|
|
2064
2778
|
}
|
|
2065
|
-
if (ctx.reactRouterConfig
|
|
2779
|
+
if (isPrerenderingEnabled(ctx.reactRouterConfig)) {
|
|
2066
2780
|
await handlePrerender(
|
|
2067
2781
|
viteConfig,
|
|
2068
2782
|
ctx.reactRouterConfig,
|
|
@@ -2099,10 +2813,59 @@ var reactRouterVitePlugin = () => {
|
|
|
2099
2813
|
await typegenWatcher?.close();
|
|
2100
2814
|
}
|
|
2101
2815
|
},
|
|
2816
|
+
{
|
|
2817
|
+
name: "react-router:route-chunks-index",
|
|
2818
|
+
// This plugin provides the route module "index" since route modules can
|
|
2819
|
+
// be chunked and may be made up of multiple smaller modules. This plugin
|
|
2820
|
+
// primarily ensures code is never duplicated across a route module and
|
|
2821
|
+
// its chunks. If we didn't have this plugin, any app that explicitly
|
|
2822
|
+
// imports a route module would result in duplicate code since the app
|
|
2823
|
+
// would contain code for both the unprocessed route module as well as its
|
|
2824
|
+
// individual chunks. This is because, since they have different module
|
|
2825
|
+
// IDs, they are treated as completely separate modules even though they
|
|
2826
|
+
// all reference the same underlying file. This plugin addresses this by
|
|
2827
|
+
// ensuring that any explicit imports of a route module resolve to a
|
|
2828
|
+
// module that simply re-exports from its underlying chunks, if present.
|
|
2829
|
+
async transform(code, id, options) {
|
|
2830
|
+
if (viteCommand !== "build") return;
|
|
2831
|
+
if (options?.ssr) {
|
|
2832
|
+
return;
|
|
2833
|
+
}
|
|
2834
|
+
if (!isRoute(ctx.reactRouterConfig, id)) {
|
|
2835
|
+
return;
|
|
2836
|
+
}
|
|
2837
|
+
if (isRouteVirtualModule(id)) {
|
|
2838
|
+
return;
|
|
2839
|
+
}
|
|
2840
|
+
let { hasRouteChunks, chunkedExports } = await detectRouteChunksIfEnabled(cache, ctx, id, code);
|
|
2841
|
+
if (!hasRouteChunks) {
|
|
2842
|
+
return;
|
|
2843
|
+
}
|
|
2844
|
+
let sourceExports = await getRouteModuleExports(
|
|
2845
|
+
viteChildCompiler,
|
|
2846
|
+
ctx,
|
|
2847
|
+
id
|
|
2848
|
+
);
|
|
2849
|
+
let isMainChunkExport = (name) => !chunkedExports.includes(name);
|
|
2850
|
+
let mainChunkReexports = sourceExports.filter(isMainChunkExport).join(", ");
|
|
2851
|
+
let chunkBasePath = `./${path6.basename(id)}`;
|
|
2852
|
+
return [
|
|
2853
|
+
`export { ${mainChunkReexports} } from "${getRouteChunkModuleId(
|
|
2854
|
+
chunkBasePath,
|
|
2855
|
+
"main"
|
|
2856
|
+
)}";`,
|
|
2857
|
+
...chunkedExports.map(
|
|
2858
|
+
(exportName) => `export { ${exportName} } from "${getRouteChunkModuleId(
|
|
2859
|
+
chunkBasePath,
|
|
2860
|
+
exportName
|
|
2861
|
+
)}";`
|
|
2862
|
+
)
|
|
2863
|
+
].filter(Boolean).join("\n");
|
|
2864
|
+
}
|
|
2865
|
+
},
|
|
2102
2866
|
{
|
|
2103
2867
|
name: "react-router:build-client-route",
|
|
2104
|
-
|
|
2105
|
-
async transform(_code, id, options) {
|
|
2868
|
+
async transform(code, id, options) {
|
|
2106
2869
|
if (!id.endsWith(BUILD_CLIENT_ROUTE_QUERY_STRING)) return;
|
|
2107
2870
|
let routeModuleId = id.replace(BUILD_CLIENT_ROUTE_QUERY_STRING, "");
|
|
2108
2871
|
let routeFileName = path6.basename(routeModuleId);
|
|
@@ -2111,26 +2874,91 @@ var reactRouterVitePlugin = () => {
|
|
|
2111
2874
|
ctx,
|
|
2112
2875
|
routeModuleId
|
|
2113
2876
|
);
|
|
2114
|
-
let
|
|
2115
|
-
|
|
2116
|
-
|
|
2877
|
+
let { chunkedExports = [] } = options?.ssr ? {} : await detectRouteChunksIfEnabled(cache, ctx, id, code);
|
|
2878
|
+
let reexports = sourceExports.filter((exportName) => {
|
|
2879
|
+
let isRouteEntryExport = options?.ssr && SERVER_ONLY_ROUTE_EXPORTS.includes(exportName) || CLIENT_ROUTE_EXPORTS.includes(exportName);
|
|
2880
|
+
let isChunkedExport = chunkedExports.includes(
|
|
2881
|
+
exportName
|
|
2882
|
+
);
|
|
2883
|
+
return isRouteEntryExport && !isChunkedExport;
|
|
2884
|
+
}).join(", ");
|
|
2117
2885
|
return `export { ${reexports} } from "./${routeFileName}";`;
|
|
2118
2886
|
}
|
|
2119
2887
|
},
|
|
2888
|
+
{
|
|
2889
|
+
name: "react-router:split-route-modules",
|
|
2890
|
+
async transform(code, id, options) {
|
|
2891
|
+
if (options?.ssr) return;
|
|
2892
|
+
if (!isRouteChunkModuleId(id)) return;
|
|
2893
|
+
invariant(
|
|
2894
|
+
viteCommand === "build",
|
|
2895
|
+
"Route modules are only split in build mode"
|
|
2896
|
+
);
|
|
2897
|
+
let chunkName = getRouteChunkNameFromModuleId(id);
|
|
2898
|
+
if (!chunkName) {
|
|
2899
|
+
throw new Error(`Invalid route chunk name "${chunkName}" in "${id}"`);
|
|
2900
|
+
}
|
|
2901
|
+
let chunk = await getRouteChunkIfEnabled(
|
|
2902
|
+
cache,
|
|
2903
|
+
ctx,
|
|
2904
|
+
id,
|
|
2905
|
+
chunkName,
|
|
2906
|
+
code
|
|
2907
|
+
);
|
|
2908
|
+
let preventEmptyChunkSnippet = ({ reason }) => `Math.random()<0&&console.log(${JSON.stringify(reason)});`;
|
|
2909
|
+
if (chunk === null) {
|
|
2910
|
+
return preventEmptyChunkSnippet({
|
|
2911
|
+
reason: "Split round modules disabled"
|
|
2912
|
+
});
|
|
2913
|
+
}
|
|
2914
|
+
let enforceSplitRouteModules = ctx.reactRouterConfig.future.unstable_splitRouteModules === "enforce";
|
|
2915
|
+
if (enforceSplitRouteModules && chunkName === "main" && chunk) {
|
|
2916
|
+
let exportNames = getExportNames(chunk.code);
|
|
2917
|
+
validateRouteChunks({
|
|
2918
|
+
ctx,
|
|
2919
|
+
id,
|
|
2920
|
+
valid: {
|
|
2921
|
+
clientAction: !exportNames.includes("clientAction"),
|
|
2922
|
+
clientLoader: !exportNames.includes("clientLoader"),
|
|
2923
|
+
HydrateFallback: !exportNames.includes("HydrateFallback")
|
|
2924
|
+
}
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2927
|
+
return chunk ?? preventEmptyChunkSnippet({ reason: `No ${chunkName} chunk` });
|
|
2928
|
+
}
|
|
2929
|
+
},
|
|
2120
2930
|
{
|
|
2121
2931
|
name: "react-router:virtual-modules",
|
|
2122
2932
|
enforce: "pre",
|
|
2123
2933
|
resolveId(id) {
|
|
2124
|
-
|
|
2125
|
-
|
|
2934
|
+
let [baseId, queryString] = id.split("?");
|
|
2935
|
+
const vmod2 = Object.values(virtual).find((vmod3) => vmod3.id === baseId);
|
|
2936
|
+
if (vmod2)
|
|
2937
|
+
return vmod2.resolvedId + (queryString ? `?${queryString}` : "");
|
|
2126
2938
|
},
|
|
2127
2939
|
async load(id) {
|
|
2128
|
-
|
|
2940
|
+
let [baseId, queryString] = id.split("?");
|
|
2941
|
+
switch (baseId) {
|
|
2129
2942
|
case virtual.serverBuild.resolvedId: {
|
|
2130
|
-
|
|
2943
|
+
let searchParams = new URLSearchParams(queryString);
|
|
2944
|
+
let routeIds = searchParams.get("route-ids")?.split(",") || void 0;
|
|
2945
|
+
return await getServerEntry({ routeIds });
|
|
2131
2946
|
}
|
|
2132
2947
|
case virtual.serverManifest.resolvedId: {
|
|
2133
|
-
let
|
|
2948
|
+
let searchParams = new URLSearchParams(queryString);
|
|
2949
|
+
let routeIds = searchParams.get("route-ids")?.split(",") || void 0;
|
|
2950
|
+
let reactRouterManifest = viteCommand === "build" ? (await generateReactRouterManifestsForBuild({
|
|
2951
|
+
routeIds
|
|
2952
|
+
})).reactRouterServerManifest : await getReactRouterManifestForDev();
|
|
2953
|
+
if (!ctx.reactRouterConfig.ssr) {
|
|
2954
|
+
invariant(viteConfig);
|
|
2955
|
+
validateSsrFalsePrerenderExports(
|
|
2956
|
+
viteConfig,
|
|
2957
|
+
ctx,
|
|
2958
|
+
reactRouterManifest,
|
|
2959
|
+
viteChildCompiler
|
|
2960
|
+
);
|
|
2961
|
+
}
|
|
2134
2962
|
return `export default ${(0, import_jsesc.default)(reactRouterManifest, {
|
|
2135
2963
|
es6: true
|
|
2136
2964
|
})};`;
|
|
@@ -2171,8 +2999,7 @@ var reactRouterVitePlugin = () => {
|
|
|
2171
2999
|
let importerShort = vite2.normalizePath(
|
|
2172
3000
|
path6.relative(ctx.rootDirectory, importer)
|
|
2173
3001
|
);
|
|
2174
|
-
|
|
2175
|
-
if (isRoute) {
|
|
3002
|
+
if (isRoute(ctx.reactRouterConfig, importer)) {
|
|
2176
3003
|
let serverOnlyExports = SERVER_ONLY_ROUTE_EXPORTS.map(
|
|
2177
3004
|
(xport) => `\`${xport}\``
|
|
2178
3005
|
).join(", ");
|
|
@@ -2211,10 +3038,10 @@ var reactRouterVitePlugin = () => {
|
|
|
2211
3038
|
let clientFileRE = /\.client(\.[cm]?[jt]sx?)?$/;
|
|
2212
3039
|
let clientDirRE = /\/\.client\//;
|
|
2213
3040
|
if (clientFileRE.test(id) || clientDirRE.test(id)) {
|
|
2214
|
-
let exports2 = (
|
|
3041
|
+
let exports2 = getExportNames(code);
|
|
2215
3042
|
return {
|
|
2216
3043
|
code: exports2.map(
|
|
2217
|
-
(
|
|
3044
|
+
(name) => name === "default" ? "export default undefined;" : `export const ${name} = undefined;`
|
|
2218
3045
|
).join("\n"),
|
|
2219
3046
|
map: null
|
|
2220
3047
|
};
|
|
@@ -2225,19 +3052,30 @@ var reactRouterVitePlugin = () => {
|
|
|
2225
3052
|
{
|
|
2226
3053
|
name: "react-router:route-exports",
|
|
2227
3054
|
async transform(code, id, options) {
|
|
3055
|
+
if (isRouteChunkModuleId(id)) {
|
|
3056
|
+
id = id.split("?")[0];
|
|
3057
|
+
}
|
|
2228
3058
|
let route = getRoute(ctx.reactRouterConfig, id);
|
|
2229
3059
|
if (!route) return;
|
|
2230
|
-
if (!options?.ssr &&
|
|
2231
|
-
let
|
|
3060
|
+
if (!options?.ssr && isSpaModeEnabled(ctx.reactRouterConfig)) {
|
|
3061
|
+
let exportNames = getExportNames(code);
|
|
3062
|
+
let serverOnlyExports = exportNames.filter((exp) => {
|
|
3063
|
+
if (route.id === "root" && exp === "loader") {
|
|
3064
|
+
return false;
|
|
3065
|
+
}
|
|
3066
|
+
return SERVER_ONLY_ROUTE_EXPORTS.includes(exp);
|
|
3067
|
+
});
|
|
2232
3068
|
if (serverOnlyExports.length > 0) {
|
|
2233
3069
|
let str = serverOnlyExports.map((e) => `\`${e}\``).join(", ");
|
|
2234
|
-
let message = `SPA Mode: ${serverOnlyExports.length} invalid route export(s) in \`${route.file}\`: ${str}. See https://
|
|
3070
|
+
let message = `SPA Mode: ${serverOnlyExports.length} invalid route export(s) in \`${route.file}\`: ${str}. See https://reactrouter.com/how-to/spa for more information.`;
|
|
2235
3071
|
throw Error(message);
|
|
2236
3072
|
}
|
|
2237
3073
|
if (route.id !== "root") {
|
|
2238
|
-
let hasHydrateFallback =
|
|
3074
|
+
let hasHydrateFallback = exportNames.some(
|
|
3075
|
+
(exp) => exp === "HydrateFallback"
|
|
3076
|
+
);
|
|
2239
3077
|
if (hasHydrateFallback) {
|
|
2240
|
-
let message = `SPA Mode: Invalid \`HydrateFallback\` export found in \`${route.file}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://
|
|
3078
|
+
let message = `SPA Mode: Invalid \`HydrateFallback\` export found in \`${route.file}\`. \`HydrateFallback\` is only permitted on the root route in SPA Mode. See https://reactrouter.com/how-to/spa for more information.`;
|
|
2241
3079
|
throw Error(message);
|
|
2242
3080
|
}
|
|
2243
3081
|
}
|
|
@@ -2313,6 +3151,9 @@ var reactRouterVitePlugin = () => {
|
|
|
2313
3151
|
let isJSX = filepath.endsWith("x");
|
|
2314
3152
|
let useFastRefresh = !ssr && (isJSX || code.includes(devRuntime));
|
|
2315
3153
|
if (!useFastRefresh) return;
|
|
3154
|
+
if (isRouteVirtualModule(id)) {
|
|
3155
|
+
return { code: addRefreshWrapper(ctx.reactRouterConfig, code, id) };
|
|
3156
|
+
}
|
|
2316
3157
|
let result = await babel.transformAsync(code, {
|
|
2317
3158
|
babelrc: false,
|
|
2318
3159
|
configFile: false,
|
|
@@ -2343,6 +3184,7 @@ var reactRouterVitePlugin = () => {
|
|
|
2343
3184
|
let serverManifest = (await server.ssrLoadModule(virtual.serverManifest.id)).default;
|
|
2344
3185
|
let oldRouteMetadata = serverManifest.routes[route.id];
|
|
2345
3186
|
let newRouteMetadata = await getRouteMetadata(
|
|
3187
|
+
cache,
|
|
2346
3188
|
ctx,
|
|
2347
3189
|
viteChildCompiler,
|
|
2348
3190
|
route,
|
|
@@ -2352,9 +3194,12 @@ var reactRouterVitePlugin = () => {
|
|
|
2352
3194
|
if (!oldRouteMetadata || [
|
|
2353
3195
|
"hasLoader",
|
|
2354
3196
|
"hasClientLoader",
|
|
3197
|
+
"clientLoaderModule",
|
|
2355
3198
|
"hasAction",
|
|
2356
3199
|
"hasClientAction",
|
|
2357
|
-
"
|
|
3200
|
+
"clientActionModule",
|
|
3201
|
+
"hasErrorBoundary",
|
|
3202
|
+
"hydrateFallbackModule"
|
|
2358
3203
|
].some((key) => oldRouteMetadata[key] !== newRouteMetadata[key])) {
|
|
2359
3204
|
invalidateVirtualModules(server);
|
|
2360
3205
|
}
|
|
@@ -2472,13 +3317,30 @@ function getRoute(pluginConfig, file) {
|
|
|
2472
3317
|
);
|
|
2473
3318
|
return route;
|
|
2474
3319
|
}
|
|
2475
|
-
|
|
3320
|
+
function isRoute(pluginConfig, file) {
|
|
3321
|
+
return Boolean(getRoute(pluginConfig, file));
|
|
3322
|
+
}
|
|
3323
|
+
async function getRouteMetadata(cache, ctx, viteChildCompiler, route, readRouteFile) {
|
|
3324
|
+
let routeFile = route.file;
|
|
2476
3325
|
let sourceExports = await getRouteModuleExports(
|
|
2477
3326
|
viteChildCompiler,
|
|
2478
3327
|
ctx,
|
|
2479
3328
|
route.file,
|
|
2480
3329
|
readRouteFile
|
|
2481
3330
|
);
|
|
3331
|
+
let { hasRouteChunkByExportName } = await detectRouteChunksIfEnabled(
|
|
3332
|
+
cache,
|
|
3333
|
+
ctx,
|
|
3334
|
+
routeFile,
|
|
3335
|
+
{ routeFile, readRouteFile, viteChildCompiler }
|
|
3336
|
+
);
|
|
3337
|
+
let moduleUrl = combineURLs(
|
|
3338
|
+
ctx.publicPath,
|
|
3339
|
+
`${resolveFileUrl(
|
|
3340
|
+
ctx,
|
|
3341
|
+
resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
|
|
3342
|
+
)}`
|
|
3343
|
+
);
|
|
2482
3344
|
let info = {
|
|
2483
3345
|
id: route.id,
|
|
2484
3346
|
parentId: route.parentId,
|
|
@@ -2492,14 +3354,11 @@ async function getRouteMetadata(ctx, viteChildCompiler, route, readRouteFile) {
|
|
|
2492
3354
|
resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
|
|
2493
3355
|
)
|
|
2494
3356
|
),
|
|
2495
|
-
module:
|
|
2496
|
-
ctx.publicPath,
|
|
2497
|
-
`${resolveFileUrl(
|
|
2498
|
-
ctx,
|
|
2499
|
-
resolveRelativeRouteFilePath(route, ctx.reactRouterConfig)
|
|
2500
|
-
)}?import`
|
|
2501
|
-
),
|
|
3357
|
+
module: `${moduleUrl}?import`,
|
|
2502
3358
|
// Ensure the Vite dev server responds with a JS module
|
|
3359
|
+
clientActionModule: hasRouteChunkByExportName.clientAction ? `${getRouteChunkModuleId(moduleUrl, "clientAction")}` : void 0,
|
|
3360
|
+
clientLoaderModule: hasRouteChunkByExportName.clientLoader ? `${getRouteChunkModuleId(moduleUrl, "clientLoader")}` : void 0,
|
|
3361
|
+
hydrateFallbackModule: hasRouteChunkByExportName.HydrateFallback ? `${getRouteChunkModuleId(moduleUrl, "HydrateFallback")}` : void 0,
|
|
2503
3362
|
hasAction: sourceExports.includes("action"),
|
|
2504
3363
|
hasClientAction: sourceExports.includes("clientAction"),
|
|
2505
3364
|
hasLoader: sourceExports.includes("loader"),
|
|
@@ -2509,6 +3368,12 @@ async function getRouteMetadata(ctx, viteChildCompiler, route, readRouteFile) {
|
|
|
2509
3368
|
};
|
|
2510
3369
|
return info;
|
|
2511
3370
|
}
|
|
3371
|
+
function isPrerenderingEnabled(reactRouterConfig) {
|
|
3372
|
+
return reactRouterConfig.prerender != null && reactRouterConfig.prerender !== false;
|
|
3373
|
+
}
|
|
3374
|
+
function isSpaModeEnabled(reactRouterConfig) {
|
|
3375
|
+
return reactRouterConfig.ssr === false && !isPrerenderingEnabled(reactRouterConfig);
|
|
3376
|
+
}
|
|
2512
3377
|
async function getPrerenderBuildAndHandler(viteConfig, serverBuildDirectory, serverBuildFile) {
|
|
2513
3378
|
let serverBuildPath = path6.join(serverBuildDirectory, serverBuildFile);
|
|
2514
3379
|
let build = await import(url.pathToFileURL(serverBuildPath).toString());
|
|
@@ -2519,20 +3384,49 @@ async function getPrerenderBuildAndHandler(viteConfig, serverBuildDirectory, ser
|
|
|
2519
3384
|
};
|
|
2520
3385
|
}
|
|
2521
3386
|
async function handleSpaMode(viteConfig, reactRouterConfig, serverBuildDirectory, serverBuildFile, clientBuildDirectory) {
|
|
2522
|
-
let { handler } = await getPrerenderBuildAndHandler(
|
|
3387
|
+
let { build, handler } = await getPrerenderBuildAndHandler(
|
|
2523
3388
|
viteConfig,
|
|
2524
3389
|
serverBuildDirectory,
|
|
2525
3390
|
serverBuildFile
|
|
2526
3391
|
);
|
|
2527
|
-
let request = new Request(`http://localhost${reactRouterConfig.basename}
|
|
3392
|
+
let request = new Request(`http://localhost${reactRouterConfig.basename}`, {
|
|
3393
|
+
headers: {
|
|
3394
|
+
// Enable SPA mode in the server runtime and only render down to the root
|
|
3395
|
+
"X-React-Router-SPA-Mode": "yes"
|
|
3396
|
+
}
|
|
3397
|
+
});
|
|
2528
3398
|
let response = await handler(request);
|
|
2529
3399
|
let html = await response.text();
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
3400
|
+
let isPrerenderSpaFallback = build.prerender.includes("/");
|
|
3401
|
+
let filename3 = isPrerenderSpaFallback ? "__spa-fallback.html" : "index.html";
|
|
3402
|
+
if (response.status !== 200) {
|
|
3403
|
+
if (isPrerenderSpaFallback) {
|
|
3404
|
+
throw new Error(
|
|
3405
|
+
`Prerender: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename3}\` file.
|
|
3406
|
+
` + html
|
|
3407
|
+
);
|
|
3408
|
+
} else {
|
|
3409
|
+
throw new Error(
|
|
3410
|
+
`SPA Mode: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering your \`${filename3}\` file.
|
|
3411
|
+
` + html
|
|
3412
|
+
);
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
if (!html.includes("window.__reactRouterContext =") || !html.includes("window.__reactRouterRouteModules =")) {
|
|
3416
|
+
throw new Error(
|
|
3417
|
+
"SPA Mode: Did you forget to include `<Scripts/>` in your root route? Your pre-rendered HTML cannot hydrate without `<Scripts />`."
|
|
3418
|
+
);
|
|
3419
|
+
}
|
|
3420
|
+
await fse.writeFile(path6.join(clientBuildDirectory, filename3), html);
|
|
3421
|
+
let prettyDir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
3422
|
+
let prettyPath = path6.join(prettyDir, filename3);
|
|
3423
|
+
if (build.prerender.length > 0) {
|
|
3424
|
+
viteConfig.logger.info(
|
|
3425
|
+
`Prerender (html): SPA Fallback -> ${import_picocolors3.default.bold(prettyPath)}`
|
|
3426
|
+
);
|
|
3427
|
+
} else {
|
|
3428
|
+
viteConfig.logger.info(`SPA Mode: Generated ${import_picocolors3.default.bold(prettyPath)}`);
|
|
3429
|
+
}
|
|
2536
3430
|
}
|
|
2537
3431
|
async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirectory, serverBuildPath, clientBuildDirectory) {
|
|
2538
3432
|
let { build, handler } = await getPrerenderBuildAndHandler(
|
|
@@ -2541,53 +3435,62 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
|
|
|
2541
3435
|
serverBuildPath
|
|
2542
3436
|
);
|
|
2543
3437
|
let routes = createPrerenderRoutes(build.routes);
|
|
2544
|
-
let routesToPrerender;
|
|
2545
|
-
if (typeof reactRouterConfig.prerender === "boolean") {
|
|
2546
|
-
invariant(reactRouterConfig.prerender, "Expected prerender:true");
|
|
2547
|
-
routesToPrerender = determineStaticPrerenderRoutes(
|
|
2548
|
-
routes,
|
|
2549
|
-
viteConfig,
|
|
2550
|
-
true
|
|
2551
|
-
);
|
|
2552
|
-
} else if (typeof reactRouterConfig.prerender === "function") {
|
|
2553
|
-
routesToPrerender = await reactRouterConfig.prerender({
|
|
2554
|
-
getStaticPaths: () => determineStaticPrerenderRoutes(routes, viteConfig, false)
|
|
2555
|
-
});
|
|
2556
|
-
} else {
|
|
2557
|
-
routesToPrerender = reactRouterConfig.prerender || ["/"];
|
|
2558
|
-
}
|
|
2559
3438
|
let headers = {
|
|
2560
3439
|
// Header that can be used in the loader to know if you're running at
|
|
2561
3440
|
// build time or runtime
|
|
2562
3441
|
"X-React-Router-Prerender": "yes"
|
|
2563
3442
|
};
|
|
2564
|
-
for (let path7 of
|
|
3443
|
+
for (let path7 of build.prerender) {
|
|
2565
3444
|
let matches = (0, import_react_router2.matchRoutes)(routes, `/${path7}/`.replace(/^\/\/+/, "/"));
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
handler,
|
|
2571
|
-
path7,
|
|
2572
|
-
clientBuildDirectory,
|
|
2573
|
-
reactRouterConfig,
|
|
2574
|
-
viteConfig,
|
|
2575
|
-
{ headers }
|
|
2576
|
-
);
|
|
2577
|
-
}
|
|
3445
|
+
invariant(
|
|
3446
|
+
matches,
|
|
3447
|
+
`Unable to prerender path because it does not match any routes: ${path7}`
|
|
3448
|
+
);
|
|
2578
3449
|
let leafRoute = matches ? matches[matches.length - 1].route : null;
|
|
2579
3450
|
let manifestRoute = leafRoute ? build.routes[leafRoute.id]?.module : null;
|
|
2580
|
-
let isResourceRoute = manifestRoute && !manifestRoute.default && !manifestRoute.ErrorBoundary
|
|
3451
|
+
let isResourceRoute = manifestRoute && !manifestRoute.default && !manifestRoute.ErrorBoundary;
|
|
2581
3452
|
if (isResourceRoute) {
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
3453
|
+
invariant(leafRoute);
|
|
3454
|
+
invariant(manifestRoute);
|
|
3455
|
+
if (manifestRoute.loader) {
|
|
3456
|
+
await prerenderData(
|
|
3457
|
+
handler,
|
|
3458
|
+
path7,
|
|
3459
|
+
[leafRoute.id],
|
|
3460
|
+
clientBuildDirectory,
|
|
3461
|
+
reactRouterConfig,
|
|
3462
|
+
viteConfig,
|
|
3463
|
+
{ headers }
|
|
3464
|
+
);
|
|
3465
|
+
await prerenderResourceRoute(
|
|
3466
|
+
handler,
|
|
3467
|
+
path7,
|
|
3468
|
+
clientBuildDirectory,
|
|
3469
|
+
reactRouterConfig,
|
|
3470
|
+
viteConfig,
|
|
3471
|
+
{ headers }
|
|
3472
|
+
);
|
|
3473
|
+
} else {
|
|
3474
|
+
viteConfig.logger.warn(
|
|
3475
|
+
`\u26A0\uFE0F Skipping prerendering for resource route without a loader: ${leafRoute?.id}`
|
|
3476
|
+
);
|
|
3477
|
+
}
|
|
2590
3478
|
} else {
|
|
3479
|
+
let hasLoaders = matches.some(
|
|
3480
|
+
(m) => build.assets.routes[m.route.id]?.hasLoader
|
|
3481
|
+
);
|
|
3482
|
+
let data;
|
|
3483
|
+
if (!isResourceRoute && hasLoaders) {
|
|
3484
|
+
data = await prerenderData(
|
|
3485
|
+
handler,
|
|
3486
|
+
path7,
|
|
3487
|
+
null,
|
|
3488
|
+
clientBuildDirectory,
|
|
3489
|
+
reactRouterConfig,
|
|
3490
|
+
viteConfig,
|
|
3491
|
+
{ headers }
|
|
3492
|
+
);
|
|
3493
|
+
}
|
|
2591
3494
|
await prerenderRoute(
|
|
2592
3495
|
handler,
|
|
2593
3496
|
path7,
|
|
@@ -2603,14 +3506,8 @@ async function handlePrerender(viteConfig, reactRouterConfig, serverBuildDirecto
|
|
|
2603
3506
|
);
|
|
2604
3507
|
}
|
|
2605
3508
|
}
|
|
2606
|
-
await prerenderManifest(
|
|
2607
|
-
build,
|
|
2608
|
-
clientBuildDirectory,
|
|
2609
|
-
reactRouterConfig,
|
|
2610
|
-
viteConfig
|
|
2611
|
-
);
|
|
2612
3509
|
}
|
|
2613
|
-
function
|
|
3510
|
+
function getStaticPrerenderPaths(routes) {
|
|
2614
3511
|
let paths = ["/"];
|
|
2615
3512
|
let paramRoutes = [];
|
|
2616
3513
|
function recurse(subtree, prefix = "") {
|
|
@@ -2630,28 +3527,33 @@ function determineStaticPrerenderRoutes(routes, viteConfig, isBooleanUsage = fal
|
|
|
2630
3527
|
}
|
|
2631
3528
|
}
|
|
2632
3529
|
recurse(routes);
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
"You may want to use the `prerender()` API to prerender the following paths:",
|
|
2638
|
-
...paramRoutes.map((p) => " - " + p)
|
|
2639
|
-
].join("\n")
|
|
2640
|
-
);
|
|
2641
|
-
}
|
|
2642
|
-
return paths.map((p) => p.replace(/\/\/+/g, "/").replace(/(.+)\/$/, "$1"));
|
|
3530
|
+
return {
|
|
3531
|
+
paths: paths.map((p) => p.replace(/\/\/+/g, "/").replace(/(.+)\/$/, "$1")),
|
|
3532
|
+
paramRoutes
|
|
3533
|
+
};
|
|
2643
3534
|
}
|
|
2644
|
-
async function prerenderData(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
3535
|
+
async function prerenderData(handler, prerenderPath, onlyRoutes, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
2645
3536
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath === "/" ? "/_root.data" : `${prerenderPath.replace(/\/$/, "")}.data`}`.replace(/\/\/+/g, "/");
|
|
2646
|
-
let
|
|
3537
|
+
let url2 = new URL(`http://localhost${normalizedPath}`);
|
|
3538
|
+
if (onlyRoutes?.length) {
|
|
3539
|
+
url2.searchParams.set("_routes", onlyRoutes.join(","));
|
|
3540
|
+
}
|
|
3541
|
+
let request = new Request(url2, requestInit);
|
|
2647
3542
|
let response = await handler(request);
|
|
2648
3543
|
let data = await response.text();
|
|
2649
|
-
|
|
3544
|
+
if (response.status !== 200) {
|
|
3545
|
+
throw new Error(
|
|
3546
|
+
`Prerender (data): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${path6}\` path.
|
|
3547
|
+
${normalizedPath}`
|
|
3548
|
+
);
|
|
3549
|
+
}
|
|
2650
3550
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
2651
3551
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
2652
3552
|
await fse.ensureDir(path6.dirname(outfile));
|
|
2653
3553
|
await fse.outputFile(outfile, data);
|
|
2654
|
-
viteConfig.logger.info(
|
|
3554
|
+
viteConfig.logger.info(
|
|
3555
|
+
`Prerender (data): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3556
|
+
);
|
|
2655
3557
|
return data;
|
|
2656
3558
|
}
|
|
2657
3559
|
async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
@@ -2662,54 +3564,65 @@ async function prerenderRoute(handler, prerenderPath, clientBuildDirectory, reac
|
|
|
2662
3564
|
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
2663
3565
|
let response = await handler(request);
|
|
2664
3566
|
let html = await response.text();
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
3567
|
+
if (response.status !== 200) {
|
|
3568
|
+
throw new Error(
|
|
3569
|
+
`Prerender (html): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.
|
|
3570
|
+
${html}`
|
|
3571
|
+
);
|
|
2668
3572
|
}
|
|
2669
3573
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
2670
3574
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"), "index.html");
|
|
2671
3575
|
await fse.ensureDir(path6.dirname(outfile));
|
|
2672
3576
|
await fse.outputFile(outfile, html);
|
|
2673
|
-
viteConfig.logger.info(
|
|
3577
|
+
viteConfig.logger.info(
|
|
3578
|
+
`Prerender (html): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
3579
|
+
);
|
|
2674
3580
|
}
|
|
2675
3581
|
async function prerenderResourceRoute(handler, prerenderPath, clientBuildDirectory, reactRouterConfig, viteConfig, requestInit) {
|
|
2676
3582
|
let normalizedPath = `${reactRouterConfig.basename}${prerenderPath}/`.replace(/\/\/+/g, "/").replace(/\/$/g, "");
|
|
2677
3583
|
let request = new Request(`http://localhost${normalizedPath}`, requestInit);
|
|
2678
3584
|
let response = await handler(request);
|
|
2679
3585
|
let text = await response.text();
|
|
2680
|
-
|
|
3586
|
+
if (response.status !== 200) {
|
|
3587
|
+
throw new Error(
|
|
3588
|
+
`Prerender (resource): Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${normalizedPath}\` path.
|
|
3589
|
+
${text}`
|
|
3590
|
+
);
|
|
3591
|
+
}
|
|
2681
3592
|
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
2682
3593
|
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
2683
3594
|
await fse.ensureDir(path6.dirname(outfile));
|
|
2684
3595
|
await fse.outputFile(outfile, text);
|
|
2685
|
-
viteConfig.logger.info(
|
|
2686
|
-
}
|
|
2687
|
-
async function prerenderManifest(build, clientBuildDirectory, reactRouterConfig, viteConfig) {
|
|
2688
|
-
let normalizedPath = `${reactRouterConfig.basename}/__manifest`.replace(
|
|
2689
|
-
/\/\/+/g,
|
|
2690
|
-
"/"
|
|
3596
|
+
viteConfig.logger.info(
|
|
3597
|
+
`Prerender (resource): ${prerenderPath} -> ${import_picocolors3.default.bold(outfile)}`
|
|
2691
3598
|
);
|
|
2692
|
-
let outdir = path6.relative(process.cwd(), clientBuildDirectory);
|
|
2693
|
-
let outfile = path6.join(outdir, ...normalizedPath.split("/"));
|
|
2694
|
-
await fse.ensureDir(path6.dirname(outfile));
|
|
2695
|
-
let manifestData = JSON.stringify(build.assets.routes);
|
|
2696
|
-
await fse.outputFile(outfile, manifestData);
|
|
2697
|
-
viteConfig.logger.info(`Prerender: Generated ${import_picocolors3.default.bold(outfile)}`);
|
|
2698
|
-
}
|
|
2699
|
-
function validatePrerenderedResponse(response, html, prefix, path7) {
|
|
2700
|
-
if (response.status !== 200) {
|
|
2701
|
-
throw new Error(
|
|
2702
|
-
`${prefix}: Received a ${response.status} status code from \`entry.server.tsx\` while prerendering the \`${path7}\` path.
|
|
2703
|
-
${html}`
|
|
2704
|
-
);
|
|
2705
|
-
}
|
|
2706
3599
|
}
|
|
2707
|
-
function
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
)
|
|
3600
|
+
async function getPrerenderPaths(prerender, ssr, routes, logWarning = false) {
|
|
3601
|
+
let prerenderPaths = [];
|
|
3602
|
+
if (prerender != null && prerender !== false) {
|
|
3603
|
+
let prerenderRoutes = createPrerenderRoutes(routes);
|
|
3604
|
+
if (prerender === true) {
|
|
3605
|
+
let { paths, paramRoutes } = getStaticPrerenderPaths(prerenderRoutes);
|
|
3606
|
+
if (logWarning && !ssr && paramRoutes.length > 0) {
|
|
3607
|
+
console.warn(
|
|
3608
|
+
import_picocolors3.default.yellow(
|
|
3609
|
+
[
|
|
3610
|
+
"\u26A0\uFE0F Paths with dynamic/splat params cannot be prerendered when using `prerender: true`. You may want to use the `prerender()` API to prerender the following paths:",
|
|
3611
|
+
...paramRoutes.map((p) => " - " + p)
|
|
3612
|
+
].join("\n")
|
|
3613
|
+
)
|
|
3614
|
+
);
|
|
3615
|
+
}
|
|
3616
|
+
prerenderPaths = paths;
|
|
3617
|
+
} else if (typeof prerender === "function") {
|
|
3618
|
+
prerenderPaths = await prerender({
|
|
3619
|
+
getStaticPaths: () => getStaticPrerenderPaths(prerenderRoutes).paths
|
|
3620
|
+
});
|
|
3621
|
+
} else {
|
|
3622
|
+
prerenderPaths = prerender || ["/"];
|
|
3623
|
+
}
|
|
2712
3624
|
}
|
|
3625
|
+
return prerenderPaths;
|
|
2713
3626
|
}
|
|
2714
3627
|
function groupRoutesByParentId2(manifest) {
|
|
2715
3628
|
let routes = {};
|
|
@@ -2727,24 +3640,445 @@ function groupRoutesByParentId2(manifest) {
|
|
|
2727
3640
|
function createPrerenderRoutes(manifest, parentId = "", routesByParentId = groupRoutesByParentId2(manifest)) {
|
|
2728
3641
|
return (routesByParentId[parentId] || []).map((route) => {
|
|
2729
3642
|
let commonRoute = {
|
|
2730
|
-
// Always include root due to default boundaries
|
|
2731
|
-
hasErrorBoundary: route.id === "root" || route.module.ErrorBoundary != null,
|
|
2732
3643
|
id: route.id,
|
|
2733
|
-
path: route.path
|
|
2734
|
-
loader: route.module.loader ? () => null : void 0,
|
|
2735
|
-
action: void 0,
|
|
2736
|
-
handle: route.module.handle
|
|
3644
|
+
path: route.path
|
|
2737
3645
|
};
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
3646
|
+
if (route.index) {
|
|
3647
|
+
return {
|
|
3648
|
+
index: true,
|
|
3649
|
+
...commonRoute
|
|
3650
|
+
};
|
|
3651
|
+
}
|
|
3652
|
+
return {
|
|
2743
3653
|
children: createPrerenderRoutes(manifest, route.id, routesByParentId),
|
|
2744
3654
|
...commonRoute
|
|
2745
3655
|
};
|
|
2746
3656
|
});
|
|
2747
3657
|
}
|
|
3658
|
+
async function validateSsrFalsePrerenderExports(viteConfig, ctx, manifest, viteChildCompiler) {
|
|
3659
|
+
let prerenderPaths = await getPrerenderPaths(
|
|
3660
|
+
ctx.reactRouterConfig.prerender,
|
|
3661
|
+
ctx.reactRouterConfig.ssr,
|
|
3662
|
+
manifest.routes,
|
|
3663
|
+
true
|
|
3664
|
+
);
|
|
3665
|
+
if (prerenderPaths.length === 0) {
|
|
3666
|
+
return;
|
|
3667
|
+
}
|
|
3668
|
+
let prerenderRoutes = createPrerenderRoutes(manifest.routes);
|
|
3669
|
+
let prerenderedRoutes = /* @__PURE__ */ new Set();
|
|
3670
|
+
for (let path7 of prerenderPaths) {
|
|
3671
|
+
let matches = (0, import_react_router2.matchRoutes)(
|
|
3672
|
+
prerenderRoutes,
|
|
3673
|
+
`/${path7}/`.replace(/^\/\/+/, "/")
|
|
3674
|
+
);
|
|
3675
|
+
invariant(
|
|
3676
|
+
matches,
|
|
3677
|
+
`Unable to prerender path because it does not match any routes: ${path7}`
|
|
3678
|
+
);
|
|
3679
|
+
matches.forEach((m) => prerenderedRoutes.add(m.route.id));
|
|
3680
|
+
}
|
|
3681
|
+
let errors = [];
|
|
3682
|
+
let routeExports = await getRouteManifestModuleExports(
|
|
3683
|
+
viteChildCompiler,
|
|
3684
|
+
ctx
|
|
3685
|
+
);
|
|
3686
|
+
for (let [routeId, route] of Object.entries(manifest.routes)) {
|
|
3687
|
+
let invalidApis = [];
|
|
3688
|
+
invariant(route, "Expected a route object in validateSsrFalseExports");
|
|
3689
|
+
let exports2 = routeExports[route.id];
|
|
3690
|
+
if (exports2.includes("headers")) invalidApis.push("headers");
|
|
3691
|
+
if (exports2.includes("action")) invalidApis.push("action");
|
|
3692
|
+
if (invalidApis.length > 0) {
|
|
3693
|
+
errors.push(
|
|
3694
|
+
`Prerender: ${invalidApis.length} invalid route export(s) in \`${route.id}\` when prerendering with \`ssr:false\`: ${invalidApis.join(", ")}. See https://reactrouter.com/how-to/pre-rendering for more information.`
|
|
3695
|
+
);
|
|
3696
|
+
}
|
|
3697
|
+
if (exports2.includes("loader") && !prerenderedRoutes.has(routeId)) {
|
|
3698
|
+
errors.push(
|
|
3699
|
+
`Prerender: 1 invalid route export in \`${route.id}\` when using \`ssr:false\` with \`prerender\` because the route is never prerendered so the loader will never be called. See https://reactrouter.com/how-to/pre-rendering for more information.`
|
|
3700
|
+
);
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
if (errors.length > 0) {
|
|
3704
|
+
viteConfig.logger.error(import_picocolors3.default.red(errors.join("\n")));
|
|
3705
|
+
throw new Error(
|
|
3706
|
+
"Invalid route exports found when prerendering with `ssr:false`"
|
|
3707
|
+
);
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3710
|
+
function getAddressableRoutes(routes) {
|
|
3711
|
+
let nonAddressableIds = /* @__PURE__ */ new Set();
|
|
3712
|
+
for (let id in routes) {
|
|
3713
|
+
let route = routes[id];
|
|
3714
|
+
if (route.index) {
|
|
3715
|
+
invariant(
|
|
3716
|
+
route.parentId,
|
|
3717
|
+
`Expected index route "${route.id}" to have "parentId" set`
|
|
3718
|
+
);
|
|
3719
|
+
nonAddressableIds.add(route.parentId);
|
|
3720
|
+
}
|
|
3721
|
+
if (typeof route.path !== "string" && !route.index) {
|
|
3722
|
+
nonAddressableIds.add(id);
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
return Object.values(routes).filter(
|
|
3726
|
+
(route) => !nonAddressableIds.has(route.id)
|
|
3727
|
+
);
|
|
3728
|
+
}
|
|
3729
|
+
function getRouteBranch(routes, routeId) {
|
|
3730
|
+
let branch = [];
|
|
3731
|
+
let currentRouteId = routeId;
|
|
3732
|
+
while (currentRouteId) {
|
|
3733
|
+
let route = routes[currentRouteId];
|
|
3734
|
+
invariant(route, `Missing route for ${currentRouteId}`);
|
|
3735
|
+
branch.push(route);
|
|
3736
|
+
currentRouteId = route.parentId;
|
|
3737
|
+
}
|
|
3738
|
+
return branch.reverse();
|
|
3739
|
+
}
|
|
3740
|
+
function hasServerBundles(buildManifest) {
|
|
3741
|
+
return Object.keys(buildManifest.serverBundles ?? {}).length > 0;
|
|
3742
|
+
}
|
|
3743
|
+
function getRoutesByServerBundleId(buildManifest) {
|
|
3744
|
+
if (!buildManifest.routeIdToServerBundleId) {
|
|
3745
|
+
return {};
|
|
3746
|
+
}
|
|
3747
|
+
let routesByServerBundleId = {};
|
|
3748
|
+
for (let [routeId, serverBundleId] of Object.entries(
|
|
3749
|
+
buildManifest.routeIdToServerBundleId
|
|
3750
|
+
)) {
|
|
3751
|
+
routesByServerBundleId[serverBundleId] ??= {};
|
|
3752
|
+
let branch = getRouteBranch(buildManifest.routes, routeId);
|
|
3753
|
+
for (let route of branch) {
|
|
3754
|
+
routesByServerBundleId[serverBundleId][route.id] = route;
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
return routesByServerBundleId;
|
|
3758
|
+
}
|
|
3759
|
+
var resolveRouteFileCode = async (ctx, input) => {
|
|
3760
|
+
if (typeof input === "string") return input;
|
|
3761
|
+
invariant(input.viteChildCompiler);
|
|
3762
|
+
return await compileRouteFile(
|
|
3763
|
+
input.viteChildCompiler,
|
|
3764
|
+
ctx,
|
|
3765
|
+
input.routeFile,
|
|
3766
|
+
input.readRouteFile
|
|
3767
|
+
);
|
|
3768
|
+
};
|
|
3769
|
+
async function detectRouteChunksIfEnabled(cache, ctx, id, input) {
|
|
3770
|
+
function noRouteChunks() {
|
|
3771
|
+
return {
|
|
3772
|
+
chunkedExports: [],
|
|
3773
|
+
hasRouteChunks: false,
|
|
3774
|
+
hasRouteChunkByExportName: {
|
|
3775
|
+
clientAction: false,
|
|
3776
|
+
clientLoader: false,
|
|
3777
|
+
HydrateFallback: false
|
|
3778
|
+
}
|
|
3779
|
+
};
|
|
3780
|
+
}
|
|
3781
|
+
if (!ctx.reactRouterConfig.future.unstable_splitRouteModules) {
|
|
3782
|
+
return noRouteChunks();
|
|
3783
|
+
}
|
|
3784
|
+
if (normalizeRelativeFilePath(id, ctx.reactRouterConfig) === ctx.reactRouterConfig.routes.root.file) {
|
|
3785
|
+
return noRouteChunks();
|
|
3786
|
+
}
|
|
3787
|
+
let code = await resolveRouteFileCode(ctx, input);
|
|
3788
|
+
if (!routeChunkExportNames.some((exportName) => code.includes(exportName))) {
|
|
3789
|
+
return noRouteChunks();
|
|
3790
|
+
}
|
|
3791
|
+
let cacheKey = normalizeRelativeFilePath(id, ctx.reactRouterConfig) + (typeof input === "string" ? "" : "?read");
|
|
3792
|
+
return detectRouteChunks(code, cache, cacheKey);
|
|
3793
|
+
}
|
|
3794
|
+
async function getRouteChunkIfEnabled(cache, ctx, id, chunkName, input) {
|
|
3795
|
+
if (!ctx.reactRouterConfig.future.unstable_splitRouteModules) {
|
|
3796
|
+
return null;
|
|
3797
|
+
}
|
|
3798
|
+
let code = await resolveRouteFileCode(ctx, input);
|
|
3799
|
+
let cacheKey = normalizeRelativeFilePath(id, ctx.reactRouterConfig) + (typeof input === "string" ? "" : "?read");
|
|
3800
|
+
return getRouteChunkCode(code, chunkName, cache, cacheKey);
|
|
3801
|
+
}
|
|
3802
|
+
function validateRouteChunks({
|
|
3803
|
+
ctx,
|
|
3804
|
+
id,
|
|
3805
|
+
valid
|
|
3806
|
+
}) {
|
|
3807
|
+
let invalidChunks = Object.entries(valid).filter(([_, isValid]) => !isValid).map(([chunkName]) => chunkName);
|
|
3808
|
+
if (invalidChunks.length === 0) {
|
|
3809
|
+
return;
|
|
3810
|
+
}
|
|
3811
|
+
let plural = invalidChunks.length > 1;
|
|
3812
|
+
throw new Error(
|
|
3813
|
+
[
|
|
3814
|
+
`Error splitting route module: ${normalizeRelativeFilePath(
|
|
3815
|
+
id,
|
|
3816
|
+
ctx.reactRouterConfig
|
|
3817
|
+
)}`,
|
|
3818
|
+
invalidChunks.map((name) => `- ${name}`).join("\n"),
|
|
3819
|
+
`${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.`
|
|
3820
|
+
].join("\n\n")
|
|
3821
|
+
);
|
|
3822
|
+
}
|
|
3823
|
+
async function cleanBuildDirectory(viteConfig, ctx) {
|
|
3824
|
+
let buildDirectory = ctx.reactRouterConfig.buildDirectory;
|
|
3825
|
+
let isWithinRoot = () => {
|
|
3826
|
+
let relativePath = path6.relative(ctx.rootDirectory, buildDirectory);
|
|
3827
|
+
return !relativePath.startsWith("..") && !path6.isAbsolute(relativePath);
|
|
3828
|
+
};
|
|
3829
|
+
if (viteConfig.build.emptyOutDir ?? isWithinRoot()) {
|
|
3830
|
+
await fse.remove(buildDirectory);
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
async function cleanViteManifests(environmentsOptions, ctx) {
|
|
3834
|
+
let viteManifestPaths = Object.entries(environmentsOptions).map(
|
|
3835
|
+
([environmentName, options]) => {
|
|
3836
|
+
let outDir = options.build?.outDir;
|
|
3837
|
+
invariant(outDir, `Expected build.outDir for ${environmentName}`);
|
|
3838
|
+
return path6.join(outDir, ".vite/manifest.json");
|
|
3839
|
+
}
|
|
3840
|
+
);
|
|
3841
|
+
await Promise.all(
|
|
3842
|
+
viteManifestPaths.map(async (viteManifestPath) => {
|
|
3843
|
+
let manifestExists = await fse.pathExists(viteManifestPath);
|
|
3844
|
+
if (!manifestExists) return;
|
|
3845
|
+
if (!ctx.viteManifestEnabled) {
|
|
3846
|
+
await fse.remove(viteManifestPath);
|
|
3847
|
+
}
|
|
3848
|
+
let viteDir = path6.dirname(viteManifestPath);
|
|
3849
|
+
let viteDirFiles = await fse.readdir(viteDir);
|
|
3850
|
+
if (viteDirFiles.length === 0) {
|
|
3851
|
+
await fse.remove(viteDir);
|
|
3852
|
+
}
|
|
3853
|
+
})
|
|
3854
|
+
);
|
|
3855
|
+
}
|
|
3856
|
+
async function getBuildManifest(ctx) {
|
|
3857
|
+
let { routes, serverBundles, appDirectory } = ctx.reactRouterConfig;
|
|
3858
|
+
if (!serverBundles) {
|
|
3859
|
+
return { routes };
|
|
3860
|
+
}
|
|
3861
|
+
let { normalizePath } = await import("vite");
|
|
3862
|
+
let serverBuildDirectory = getServerBuildDirectory(ctx);
|
|
3863
|
+
let resolvedAppDirectory = path6.resolve(ctx.rootDirectory, appDirectory);
|
|
3864
|
+
let rootRelativeRoutes = Object.fromEntries(
|
|
3865
|
+
Object.entries(routes).map(([id, route]) => {
|
|
3866
|
+
let filePath = path6.join(resolvedAppDirectory, route.file);
|
|
3867
|
+
let rootRelativeFilePath = normalizePath(
|
|
3868
|
+
path6.relative(ctx.rootDirectory, filePath)
|
|
3869
|
+
);
|
|
3870
|
+
return [id, { ...route, file: rootRelativeFilePath }];
|
|
3871
|
+
})
|
|
3872
|
+
);
|
|
3873
|
+
let buildManifest = {
|
|
3874
|
+
serverBundles: {},
|
|
3875
|
+
routeIdToServerBundleId: {},
|
|
3876
|
+
routes: rootRelativeRoutes
|
|
3877
|
+
};
|
|
3878
|
+
await Promise.all(
|
|
3879
|
+
getAddressableRoutes(routes).map(async (route) => {
|
|
3880
|
+
let branch = getRouteBranch(routes, route.id);
|
|
3881
|
+
let serverBundleId = await serverBundles({
|
|
3882
|
+
branch: branch.map(
|
|
3883
|
+
(route2) => configRouteToBranchRoute({
|
|
3884
|
+
...route2,
|
|
3885
|
+
// Ensure absolute paths are passed to the serverBundles function
|
|
3886
|
+
file: path6.join(resolvedAppDirectory, route2.file)
|
|
3887
|
+
})
|
|
3888
|
+
)
|
|
3889
|
+
});
|
|
3890
|
+
if (typeof serverBundleId !== "string") {
|
|
3891
|
+
throw new Error(`The "serverBundles" function must return a string`);
|
|
3892
|
+
}
|
|
3893
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(serverBundleId)) {
|
|
3894
|
+
throw new Error(
|
|
3895
|
+
`The "serverBundles" function must only return strings containing alphanumeric characters, hyphens and underscores.`
|
|
3896
|
+
);
|
|
3897
|
+
}
|
|
3898
|
+
buildManifest.routeIdToServerBundleId[route.id] = serverBundleId;
|
|
3899
|
+
buildManifest.serverBundles[serverBundleId] ??= {
|
|
3900
|
+
id: serverBundleId,
|
|
3901
|
+
file: normalizePath(
|
|
3902
|
+
path6.join(
|
|
3903
|
+
path6.relative(
|
|
3904
|
+
ctx.rootDirectory,
|
|
3905
|
+
path6.join(serverBuildDirectory, serverBundleId)
|
|
3906
|
+
),
|
|
3907
|
+
ctx.reactRouterConfig.serverBuildFile
|
|
3908
|
+
)
|
|
3909
|
+
)
|
|
3910
|
+
};
|
|
3911
|
+
})
|
|
3912
|
+
);
|
|
3913
|
+
return buildManifest;
|
|
3914
|
+
}
|
|
3915
|
+
function mergeEnvironmentOptions(base, ...overrides) {
|
|
3916
|
+
let vite2 = getVite();
|
|
3917
|
+
return overrides.reduce(
|
|
3918
|
+
(merged, override) => vite2.mergeConfig(merged, override, false),
|
|
3919
|
+
base
|
|
3920
|
+
);
|
|
3921
|
+
}
|
|
3922
|
+
async function getEnvironmentOptionsResolvers(ctx, buildManifest, viteCommand) {
|
|
3923
|
+
let { serverBuildFile, serverModuleFormat } = ctx.reactRouterConfig;
|
|
3924
|
+
let packageRoot = path6.dirname(
|
|
3925
|
+
require.resolve("@react-router/dev/package.json")
|
|
3926
|
+
);
|
|
3927
|
+
let { moduleSyncEnabled } = await import(`file:///${path6.join(packageRoot, "module-sync-enabled/index.mjs")}`);
|
|
3928
|
+
let vite2 = getVite();
|
|
3929
|
+
let viteServerConditions = [
|
|
3930
|
+
...vite2.defaultServerConditions ?? [],
|
|
3931
|
+
...moduleSyncEnabled ? ["module-sync"] : []
|
|
3932
|
+
];
|
|
3933
|
+
function getBaseOptions({
|
|
3934
|
+
viteUserConfig
|
|
3935
|
+
}) {
|
|
3936
|
+
return {
|
|
3937
|
+
build: {
|
|
3938
|
+
cssMinify: viteUserConfig.build?.cssMinify ?? true,
|
|
3939
|
+
manifest: true,
|
|
3940
|
+
// The manifest is enabled for all builds to detect SSR-only assets
|
|
3941
|
+
rollupOptions: {
|
|
3942
|
+
preserveEntrySignatures: "exports-only",
|
|
3943
|
+
// Silence Rollup "use client" warnings
|
|
3944
|
+
// Adapted from https://github.com/vitejs/vite-plugin-react/pull/144
|
|
3945
|
+
onwarn(warning, defaultHandler) {
|
|
3946
|
+
if (warning.code === "MODULE_LEVEL_DIRECTIVE" && warning.message.includes("use client")) {
|
|
3947
|
+
return;
|
|
3948
|
+
}
|
|
3949
|
+
let userHandler = viteUserConfig.build?.rollupOptions?.onwarn;
|
|
3950
|
+
if (userHandler) {
|
|
3951
|
+
userHandler(warning, defaultHandler);
|
|
3952
|
+
} else {
|
|
3953
|
+
defaultHandler(warning);
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3958
|
+
};
|
|
3959
|
+
}
|
|
3960
|
+
function getBaseServerOptions({
|
|
3961
|
+
viteUserConfig
|
|
3962
|
+
}) {
|
|
3963
|
+
let conditions = viteCommand === "build" ? viteServerConditions : ["development", ...viteServerConditions];
|
|
3964
|
+
return mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
|
|
3965
|
+
resolve: {
|
|
3966
|
+
external: ssrExternals,
|
|
3967
|
+
conditions,
|
|
3968
|
+
externalConditions: conditions
|
|
3969
|
+
},
|
|
3970
|
+
build: {
|
|
3971
|
+
// We move SSR-only assets to client assets. Note that the
|
|
3972
|
+
// SSR build can also emit code-split JS files (e.g. by
|
|
3973
|
+
// dynamic import) under the same assets directory
|
|
3974
|
+
// regardless of "ssrEmitAssets" option, so we also need to
|
|
3975
|
+
// keep these JS files have to be kept as-is.
|
|
3976
|
+
ssrEmitAssets: true,
|
|
3977
|
+
copyPublicDir: false,
|
|
3978
|
+
// Assets in the public directory are only used by the client
|
|
3979
|
+
rollupOptions: {
|
|
3980
|
+
output: {
|
|
3981
|
+
entryFileNames: serverBuildFile,
|
|
3982
|
+
format: serverModuleFormat
|
|
3983
|
+
}
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
});
|
|
3987
|
+
}
|
|
3988
|
+
let environmentOptionsResolvers = {
|
|
3989
|
+
client: ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseOptions({ viteUserConfig }), {
|
|
3990
|
+
build: {
|
|
3991
|
+
rollupOptions: {
|
|
3992
|
+
input: [
|
|
3993
|
+
ctx.entryClientFilePath,
|
|
3994
|
+
...Object.values(ctx.reactRouterConfig.routes).flatMap(
|
|
3995
|
+
(route) => {
|
|
3996
|
+
let routeFilePath = path6.resolve(
|
|
3997
|
+
ctx.reactRouterConfig.appDirectory,
|
|
3998
|
+
route.file
|
|
3999
|
+
);
|
|
4000
|
+
let isRootRoute = route.file === ctx.reactRouterConfig.routes.root.file;
|
|
4001
|
+
let code = fse.readFileSync(routeFilePath, "utf-8");
|
|
4002
|
+
return [
|
|
4003
|
+
`${routeFilePath}${BUILD_CLIENT_ROUTE_QUERY_STRING}`,
|
|
4004
|
+
...ctx.reactRouterConfig.future.unstable_splitRouteModules && !isRootRoute ? routeChunkExportNames.map(
|
|
4005
|
+
(exportName) => code.includes(exportName) ? getRouteChunkModuleId(routeFilePath, exportName) : null
|
|
4006
|
+
) : []
|
|
4007
|
+
].filter(isNonNullable);
|
|
4008
|
+
}
|
|
4009
|
+
)
|
|
4010
|
+
],
|
|
4011
|
+
output: {
|
|
4012
|
+
entryFileNames({ moduleIds }) {
|
|
4013
|
+
let routeChunkModuleId = moduleIds.find(isRouteChunkModuleId);
|
|
4014
|
+
let routeChunkName = routeChunkModuleId ? getRouteChunkNameFromModuleId(routeChunkModuleId) : null;
|
|
4015
|
+
let routeChunkSuffix = routeChunkName ? `-${(0, import_kebabCase.default)(routeChunkName)}` : "";
|
|
4016
|
+
return `assets/[name]${routeChunkSuffix}-[hash].js`;
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
},
|
|
4020
|
+
outDir: getClientBuildDirectory(ctx.reactRouterConfig)
|
|
4021
|
+
}
|
|
4022
|
+
})
|
|
4023
|
+
};
|
|
4024
|
+
if (hasServerBundles(buildManifest)) {
|
|
4025
|
+
for (let [serverBundleId, routes] of Object.entries(
|
|
4026
|
+
getRoutesByServerBundleId(buildManifest)
|
|
4027
|
+
)) {
|
|
4028
|
+
const serverBundleEnvironmentId = serverBundleId.replaceAll("-", "_");
|
|
4029
|
+
const environmentName = `${SSR_BUNDLE_PREFIX}${serverBundleEnvironmentId}`;
|
|
4030
|
+
environmentOptionsResolvers[environmentName] = ({ viteUserConfig }) => mergeEnvironmentOptions(
|
|
4031
|
+
getBaseServerOptions({ viteUserConfig }),
|
|
4032
|
+
{
|
|
4033
|
+
build: {
|
|
4034
|
+
outDir: getServerBuildDirectory(ctx, { serverBundleId }),
|
|
4035
|
+
rollupOptions: {
|
|
4036
|
+
input: `${virtual.serverBuild.id}?route-ids=${Object.keys(
|
|
4037
|
+
routes
|
|
4038
|
+
).join(",")}`
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
4041
|
+
},
|
|
4042
|
+
// Ensure server bundle environments extend the user's SSR
|
|
4043
|
+
// environment config if it exists
|
|
4044
|
+
viteUserConfig.environments?.ssr ?? {}
|
|
4045
|
+
);
|
|
4046
|
+
}
|
|
4047
|
+
} else {
|
|
4048
|
+
environmentOptionsResolvers.ssr = ({ viteUserConfig }) => mergeEnvironmentOptions(getBaseServerOptions({ viteUserConfig }), {
|
|
4049
|
+
build: {
|
|
4050
|
+
outDir: getServerBuildDirectory(ctx),
|
|
4051
|
+
rollupOptions: {
|
|
4052
|
+
input: (ctx.reactRouterConfig.future.unstable_viteEnvironmentApi ? viteUserConfig.environments?.ssr?.build?.rollupOptions?.input : viteUserConfig.build?.rollupOptions?.input) ?? virtual.serverBuild.id
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
});
|
|
4056
|
+
}
|
|
4057
|
+
return environmentOptionsResolvers;
|
|
4058
|
+
}
|
|
4059
|
+
function resolveEnvironmentsOptions(environmentResolvers, resolverOptions) {
|
|
4060
|
+
let environmentOptions = {};
|
|
4061
|
+
for (let [environmentName, resolver] of Object.entries(
|
|
4062
|
+
environmentResolvers
|
|
4063
|
+
)) {
|
|
4064
|
+
environmentOptions[environmentName] = resolver(resolverOptions);
|
|
4065
|
+
}
|
|
4066
|
+
return environmentOptions;
|
|
4067
|
+
}
|
|
4068
|
+
async function getEnvironmentsOptions(ctx, buildManifest, viteCommand, resolverOptions) {
|
|
4069
|
+
let environmentOptionsResolvers = await getEnvironmentOptionsResolvers(
|
|
4070
|
+
ctx,
|
|
4071
|
+
buildManifest,
|
|
4072
|
+
viteCommand
|
|
4073
|
+
);
|
|
4074
|
+
return resolveEnvironmentsOptions(
|
|
4075
|
+
environmentOptionsResolvers,
|
|
4076
|
+
resolverOptions
|
|
4077
|
+
);
|
|
4078
|
+
}
|
|
4079
|
+
function isNonNullable(x) {
|
|
4080
|
+
return x != null;
|
|
4081
|
+
}
|
|
2748
4082
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2749
4083
|
0 && (module.exports = {
|
|
2750
4084
|
reactRouter
|