@angular/ssr 19.0.0-next.7 → 19.0.0-next.9
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/LICENSE +21 -0
- package/fesm2022/node.mjs +50 -1
- package/fesm2022/node.mjs.map +1 -1
- package/fesm2022/ssr.mjs +299 -45
- package/fesm2022/ssr.mjs.map +1 -1
- package/index.d.ts +125 -17
- package/node/index.d.ts +57 -0
- package/package.json +7 -7
package/fesm2022/ssr.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APP_BASE_HREF, PlatformLocation } from '@angular/common';
|
|
2
|
-
import { ɵConsole as _Console, InjectionToken, makeEnvironmentProviders, runInInjectionContext, createPlatformFactory, platformCore, ApplicationRef, ɵwhenStable as _whenStable, Compiler, ɵresetCompiledComponents as _resetCompiledComponents } from '@angular/core';
|
|
2
|
+
import { ɵConsole as _Console, InjectionToken, makeEnvironmentProviders, runInInjectionContext, createPlatformFactory, platformCore, ApplicationRef, ɵwhenStable as _whenStable, Compiler, LOCALE_ID, ɵresetCompiledComponents as _resetCompiledComponents } from '@angular/core';
|
|
3
3
|
import { ɵSERVER_CONTEXT as _SERVER_CONTEXT, renderModule, renderApplication, INITIAL_CONFIG, ɵINTERNAL_SERVER_PLATFORM_PROVIDERS as _INTERNAL_SERVER_PLATFORM_PROVIDERS } from '@angular/platform-server';
|
|
4
4
|
import { ɵloadChildren as _loadChildren, Router } from '@angular/router';
|
|
5
5
|
import Critters from '../third_party/critters/index.js';
|
|
@@ -573,16 +573,18 @@ async function* traverseRoutesConfig(options) {
|
|
|
573
573
|
matchedMetaData = serverConfigRouteTree.match(currentRoutePath);
|
|
574
574
|
if (!matchedMetaData) {
|
|
575
575
|
yield {
|
|
576
|
-
error: `The '${currentRoutePath}' route does not match any route defined in the server routing configuration. ` +
|
|
576
|
+
error: `The '${stripLeadingSlash(currentRoutePath)}' route does not match any route defined in the server routing configuration. ` +
|
|
577
577
|
'Please ensure this route is added to the server routing configuration.',
|
|
578
578
|
};
|
|
579
579
|
continue;
|
|
580
580
|
}
|
|
581
|
+
matchedMetaData.presentInClientRouter = true;
|
|
581
582
|
}
|
|
582
583
|
const metadata = {
|
|
583
584
|
...matchedMetaData,
|
|
584
585
|
route: currentRoutePath,
|
|
585
586
|
};
|
|
587
|
+
delete metadata.presentInClientRouter;
|
|
586
588
|
// Handle redirects
|
|
587
589
|
if (typeof redirectTo === 'string') {
|
|
588
590
|
const redirectToResolved = resolveRedirectTo(currentRoutePath, redirectTo);
|
|
@@ -625,7 +627,9 @@ async function* traverseRoutesConfig(options) {
|
|
|
625
627
|
}
|
|
626
628
|
}
|
|
627
629
|
catch (error) {
|
|
628
|
-
yield {
|
|
630
|
+
yield {
|
|
631
|
+
error: `Error processing route '${stripLeadingSlash(route.path ?? '')}': ${error.message}`,
|
|
632
|
+
};
|
|
629
633
|
}
|
|
630
634
|
}
|
|
631
635
|
}
|
|
@@ -659,8 +663,8 @@ async function* handleSSGRoute(metadata, parentInjector, invokeGetPrerenderParam
|
|
|
659
663
|
if (invokeGetPrerenderParams) {
|
|
660
664
|
if (!getPrerenderParams) {
|
|
661
665
|
yield {
|
|
662
|
-
error: `The '${currentRoutePath}' route uses prerendering and includes parameters, but 'getPrerenderParams'
|
|
663
|
-
`Please define 'getPrerenderParams' function for this route in your server routing configuration ` +
|
|
666
|
+
error: `The '${stripLeadingSlash(currentRoutePath)}' route uses prerendering and includes parameters, but 'getPrerenderParams' ` +
|
|
667
|
+
`is missing. Please define 'getPrerenderParams' function for this route in your server routing configuration ` +
|
|
664
668
|
`or specify a different 'renderMode'.`,
|
|
665
669
|
};
|
|
666
670
|
return;
|
|
@@ -672,7 +676,7 @@ async function* handleSSGRoute(metadata, parentInjector, invokeGetPrerenderParam
|
|
|
672
676
|
const parameterName = match.slice(1);
|
|
673
677
|
const value = params[parameterName];
|
|
674
678
|
if (typeof value !== 'string') {
|
|
675
|
-
throw new Error(`The 'getPrerenderParams' function defined for the '${currentRoutePath}' route ` +
|
|
679
|
+
throw new Error(`The 'getPrerenderParams' function defined for the '${stripLeadingSlash(currentRoutePath)}' route ` +
|
|
676
680
|
`returned a non-string value for parameter '${parameterName}'. ` +
|
|
677
681
|
`Please make sure the 'getPrerenderParams' function returns values for all parameters ` +
|
|
678
682
|
'specified in this route.');
|
|
@@ -816,14 +820,34 @@ async function getRoutesFromAngularRouterConfig(bootstrap, document, url, invoke
|
|
|
816
820
|
invokeGetPrerenderParams,
|
|
817
821
|
includePrerenderFallbackRoutes,
|
|
818
822
|
});
|
|
823
|
+
let seenAppShellRoute;
|
|
819
824
|
for await (const result of traverseRoutes) {
|
|
820
825
|
if ('error' in result) {
|
|
821
826
|
errors.push(result.error);
|
|
822
827
|
}
|
|
823
828
|
else {
|
|
829
|
+
if (result.renderMode === RenderMode.AppShell) {
|
|
830
|
+
if (seenAppShellRoute !== undefined) {
|
|
831
|
+
errors.push(`Error: Both '${seenAppShellRoute}' and '${stripLeadingSlash(result.route)}' routes have ` +
|
|
832
|
+
`their 'renderMode' set to 'AppShell'. AppShell renderMode should only be assigned to one route. ` +
|
|
833
|
+
`Please review your route configurations to ensure that only one route is set to 'RenderMode.AppShell'.`);
|
|
834
|
+
}
|
|
835
|
+
seenAppShellRoute = stripLeadingSlash(result.route);
|
|
836
|
+
}
|
|
824
837
|
routesResults.push(result);
|
|
825
838
|
}
|
|
826
839
|
}
|
|
840
|
+
if (serverConfigRouteTree) {
|
|
841
|
+
for (const { route, presentInClientRouter } of serverConfigRouteTree.traverse()) {
|
|
842
|
+
if (presentInClientRouter || route === '**') {
|
|
843
|
+
// Skip if matched or it's the catch-all route.
|
|
844
|
+
continue;
|
|
845
|
+
}
|
|
846
|
+
errors.push(`The '${route}' server route does not match any routes defined in the Angular ` +
|
|
847
|
+
`routing configuration (typically provided as a part of the 'provideRouter' call). ` +
|
|
848
|
+
'Please make sure that the mentioned server route is present in the Angular routing configuration.');
|
|
849
|
+
}
|
|
850
|
+
}
|
|
827
851
|
}
|
|
828
852
|
else {
|
|
829
853
|
routesResults.push({ route: '', renderMode: RenderMode.Prerender });
|
|
@@ -1039,17 +1063,43 @@ class ServerRouter {
|
|
|
1039
1063
|
|
|
1040
1064
|
/**
|
|
1041
1065
|
* Injection token for the current request.
|
|
1066
|
+
* @developerPreview
|
|
1042
1067
|
*/
|
|
1043
1068
|
const REQUEST = new InjectionToken('REQUEST');
|
|
1044
1069
|
/**
|
|
1045
1070
|
* Injection token for the response initialization options.
|
|
1071
|
+
* @developerPreview
|
|
1046
1072
|
*/
|
|
1047
1073
|
const RESPONSE_INIT = new InjectionToken('RESPONSE_INIT');
|
|
1048
1074
|
/**
|
|
1049
1075
|
* Injection token for additional request context.
|
|
1076
|
+
* @developerPreview
|
|
1050
1077
|
*/
|
|
1051
1078
|
const REQUEST_CONTEXT = new InjectionToken('REQUEST_CONTEXT');
|
|
1052
1079
|
|
|
1080
|
+
/**
|
|
1081
|
+
* Generates a SHA-256 hash of the provided string.
|
|
1082
|
+
*
|
|
1083
|
+
* @param data - The input string to be hashed.
|
|
1084
|
+
* @returns A promise that resolves to the SHA-256 hash of the input,
|
|
1085
|
+
* represented as a hexadecimal string.
|
|
1086
|
+
*/
|
|
1087
|
+
async function sha256(data) {
|
|
1088
|
+
if (typeof crypto === 'undefined') {
|
|
1089
|
+
// TODO(alanagius): remove once Node.js version 18 is no longer supported.
|
|
1090
|
+
throw new Error(`The global 'crypto' module is unavailable. ` +
|
|
1091
|
+
`If you are running on Node.js, please ensure you are using version 20 or later, ` +
|
|
1092
|
+
`which includes built-in support for the Web Crypto module.`);
|
|
1093
|
+
}
|
|
1094
|
+
const encodedData = new TextEncoder().encode(data);
|
|
1095
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', encodedData);
|
|
1096
|
+
const hashParts = [];
|
|
1097
|
+
for (const h of new Uint8Array(hashBuffer)) {
|
|
1098
|
+
hashParts.push(h.toString(16).padStart(2, '0'));
|
|
1099
|
+
}
|
|
1100
|
+
return hashParts.join('');
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1053
1103
|
/**
|
|
1054
1104
|
* Pattern used to extract the media query set by Critters in an `onload` handler.
|
|
1055
1105
|
*/
|
|
@@ -1207,6 +1257,126 @@ class InlineCriticalCssProcessor extends CrittersBase {
|
|
|
1207
1257
|
}
|
|
1208
1258
|
}
|
|
1209
1259
|
|
|
1260
|
+
/**
|
|
1261
|
+
* A Least Recently Used (LRU) cache implementation.
|
|
1262
|
+
*
|
|
1263
|
+
* This cache stores a fixed number of key-value pairs, and when the cache exceeds its capacity,
|
|
1264
|
+
* the least recently accessed items are evicted.
|
|
1265
|
+
*
|
|
1266
|
+
* @template Key - The type of the cache keys.
|
|
1267
|
+
* @template Value - The type of the cache values.
|
|
1268
|
+
*/
|
|
1269
|
+
class LRUCache {
|
|
1270
|
+
/**
|
|
1271
|
+
* Creates a new LRUCache instance.
|
|
1272
|
+
* @param capacity The maximum number of items the cache can hold.
|
|
1273
|
+
*/
|
|
1274
|
+
constructor(capacity) {
|
|
1275
|
+
/**
|
|
1276
|
+
* Internal storage for the cache, mapping keys to their associated nodes in the linked list.
|
|
1277
|
+
*/
|
|
1278
|
+
this.cache = new Map();
|
|
1279
|
+
this.capacity = capacity;
|
|
1280
|
+
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Gets the value associated with the given key.
|
|
1283
|
+
* @param key The key to retrieve the value for.
|
|
1284
|
+
* @returns The value associated with the key, or undefined if the key is not found.
|
|
1285
|
+
*/
|
|
1286
|
+
get(key) {
|
|
1287
|
+
const node = this.cache.get(key);
|
|
1288
|
+
if (node) {
|
|
1289
|
+
this.moveToHead(node);
|
|
1290
|
+
return node.value;
|
|
1291
|
+
}
|
|
1292
|
+
return undefined;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Puts a key-value pair into the cache.
|
|
1296
|
+
* If the key already exists, the value is updated.
|
|
1297
|
+
* If the cache is full, the least recently used item is evicted.
|
|
1298
|
+
* @param key The key to insert or update.
|
|
1299
|
+
* @param value The value to associate with the key.
|
|
1300
|
+
*/
|
|
1301
|
+
put(key, value) {
|
|
1302
|
+
const cachedNode = this.cache.get(key);
|
|
1303
|
+
if (cachedNode) {
|
|
1304
|
+
// Update existing node
|
|
1305
|
+
cachedNode.value = value;
|
|
1306
|
+
this.moveToHead(cachedNode);
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
// Create a new node
|
|
1310
|
+
const newNode = { key, value, prev: undefined, next: undefined };
|
|
1311
|
+
this.cache.set(key, newNode);
|
|
1312
|
+
this.addToHead(newNode);
|
|
1313
|
+
if (this.cache.size > this.capacity) {
|
|
1314
|
+
// Evict the LRU item
|
|
1315
|
+
const tail = this.removeTail();
|
|
1316
|
+
if (tail) {
|
|
1317
|
+
this.cache.delete(tail.key);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Adds a node to the head of the linked list.
|
|
1323
|
+
* @param node The node to add.
|
|
1324
|
+
*/
|
|
1325
|
+
addToHead(node) {
|
|
1326
|
+
node.next = this.head;
|
|
1327
|
+
node.prev = undefined;
|
|
1328
|
+
if (this.head) {
|
|
1329
|
+
this.head.prev = node;
|
|
1330
|
+
}
|
|
1331
|
+
this.head = node;
|
|
1332
|
+
if (!this.tail) {
|
|
1333
|
+
this.tail = node;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
/**
|
|
1337
|
+
* Removes a node from the linked list.
|
|
1338
|
+
* @param node The node to remove.
|
|
1339
|
+
*/
|
|
1340
|
+
removeNode(node) {
|
|
1341
|
+
if (node.prev) {
|
|
1342
|
+
node.prev.next = node.next;
|
|
1343
|
+
}
|
|
1344
|
+
else {
|
|
1345
|
+
this.head = node.next;
|
|
1346
|
+
}
|
|
1347
|
+
if (node.next) {
|
|
1348
|
+
node.next.prev = node.prev;
|
|
1349
|
+
}
|
|
1350
|
+
else {
|
|
1351
|
+
this.tail = node.prev;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Moves a node to the head of the linked list.
|
|
1356
|
+
* @param node The node to move.
|
|
1357
|
+
*/
|
|
1358
|
+
moveToHead(node) {
|
|
1359
|
+
this.removeNode(node);
|
|
1360
|
+
this.addToHead(node);
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* Removes the tail node from the linked list.
|
|
1364
|
+
* @returns The removed tail node, or undefined if the list is empty.
|
|
1365
|
+
*/
|
|
1366
|
+
removeTail() {
|
|
1367
|
+
const node = this.tail;
|
|
1368
|
+
if (node) {
|
|
1369
|
+
this.removeNode(node);
|
|
1370
|
+
}
|
|
1371
|
+
return node;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
/**
|
|
1376
|
+
* Maximum number of critical CSS entries the cache can store.
|
|
1377
|
+
* This value determines the capacity of the LRU (Least Recently Used) cache, which stores critical CSS for pages.
|
|
1378
|
+
*/
|
|
1379
|
+
const MAX_INLINE_CSS_CACHE_ENTRIES = 50;
|
|
1210
1380
|
/**
|
|
1211
1381
|
* A mapping of `RenderMode` enum values to corresponding string representations.
|
|
1212
1382
|
*
|
|
@@ -1245,6 +1415,14 @@ class AngularServerApp {
|
|
|
1245
1415
|
* An instance of ServerAsset that handles server-side asset.
|
|
1246
1416
|
*/
|
|
1247
1417
|
this.assets = new ServerAssets(this.manifest);
|
|
1418
|
+
/**
|
|
1419
|
+
* Cache for storing critical CSS for pages.
|
|
1420
|
+
* Stores a maximum of MAX_INLINE_CSS_CACHE_ENTRIES entries.
|
|
1421
|
+
*
|
|
1422
|
+
* Uses an LRU (Least Recently Used) eviction policy, meaning that when the cache is full,
|
|
1423
|
+
* the least recently accessed page's critical CSS will be removed to make space for new entries.
|
|
1424
|
+
*/
|
|
1425
|
+
this.criticalCssLRUCache = new LRUCache(MAX_INLINE_CSS_CACHE_ENTRIES);
|
|
1248
1426
|
}
|
|
1249
1427
|
/**
|
|
1250
1428
|
* Renders a response for the given HTTP request using the server application.
|
|
@@ -1326,38 +1504,62 @@ class AngularServerApp {
|
|
|
1326
1504
|
// Initialize the response with status and headers if available.
|
|
1327
1505
|
responseInit = {
|
|
1328
1506
|
status,
|
|
1329
|
-
headers:
|
|
1507
|
+
headers: new Headers({
|
|
1508
|
+
'Content-Type': 'text/html;charset=UTF-8',
|
|
1509
|
+
...headers,
|
|
1510
|
+
}),
|
|
1330
1511
|
};
|
|
1331
|
-
if (renderMode === RenderMode.
|
|
1512
|
+
if (renderMode === RenderMode.Server) {
|
|
1513
|
+
// Configure platform providers for request and response only for SSR.
|
|
1514
|
+
platformProviders.push({
|
|
1515
|
+
provide: REQUEST,
|
|
1516
|
+
useValue: request,
|
|
1517
|
+
}, {
|
|
1518
|
+
provide: REQUEST_CONTEXT,
|
|
1519
|
+
useValue: requestContext,
|
|
1520
|
+
}, {
|
|
1521
|
+
provide: RESPONSE_INIT,
|
|
1522
|
+
useValue: responseInit,
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
else if (renderMode === RenderMode.Client) {
|
|
1332
1526
|
// Serve the client-side rendered version if the route is configured for CSR.
|
|
1333
1527
|
return new Response(await this.assets.getServerAsset('index.csr.html'), responseInit);
|
|
1334
1528
|
}
|
|
1529
|
+
}
|
|
1530
|
+
const { manifest: { bootstrap, inlineCriticalCss, locale }, hooks, assets, } = this;
|
|
1531
|
+
if (locale !== undefined) {
|
|
1335
1532
|
platformProviders.push({
|
|
1336
|
-
provide:
|
|
1337
|
-
useValue:
|
|
1338
|
-
}, {
|
|
1339
|
-
provide: REQUEST_CONTEXT,
|
|
1340
|
-
useValue: requestContext,
|
|
1341
|
-
}, {
|
|
1342
|
-
provide: RESPONSE_INIT,
|
|
1343
|
-
useValue: responseInit,
|
|
1533
|
+
provide: LOCALE_ID,
|
|
1534
|
+
useValue: locale,
|
|
1344
1535
|
});
|
|
1345
1536
|
}
|
|
1346
|
-
const { manifest, hooks, assets } = this;
|
|
1347
1537
|
let html = await assets.getIndexServerHtml();
|
|
1348
1538
|
// Skip extra microtask if there are no pre hooks.
|
|
1349
1539
|
if (hooks.has('html:transform:pre')) {
|
|
1350
|
-
html = await hooks.run('html:transform:pre', { html });
|
|
1540
|
+
html = await hooks.run('html:transform:pre', { html, url });
|
|
1351
1541
|
}
|
|
1352
|
-
this.boostrap ??= await
|
|
1353
|
-
html = await renderAngular(html, this.boostrap,
|
|
1354
|
-
if (
|
|
1542
|
+
this.boostrap ??= await bootstrap();
|
|
1543
|
+
html = await renderAngular(html, this.boostrap, url, platformProviders, SERVER_CONTEXT_VALUE[renderMode]);
|
|
1544
|
+
if (inlineCriticalCss) {
|
|
1355
1545
|
// Optionally inline critical CSS.
|
|
1356
1546
|
this.inlineCriticalCssProcessor ??= new InlineCriticalCssProcessor((path) => {
|
|
1357
1547
|
const fileName = path.split('/').pop() ?? path;
|
|
1358
1548
|
return this.assets.getServerAsset(fileName);
|
|
1359
1549
|
});
|
|
1360
|
-
|
|
1550
|
+
if (isSsrMode) {
|
|
1551
|
+
// Only cache if we are running in SSR Mode.
|
|
1552
|
+
const cacheKey = await sha256(html);
|
|
1553
|
+
let htmlWithCriticalCss = this.criticalCssLRUCache.get(cacheKey);
|
|
1554
|
+
if (htmlWithCriticalCss === undefined) {
|
|
1555
|
+
htmlWithCriticalCss = await this.inlineCriticalCssProcessor.process(html);
|
|
1556
|
+
this.criticalCssLRUCache.put(cacheKey, htmlWithCriticalCss);
|
|
1557
|
+
}
|
|
1558
|
+
html = htmlWithCriticalCss;
|
|
1559
|
+
}
|
|
1560
|
+
else {
|
|
1561
|
+
html = await this.inlineCriticalCssProcessor.process(html);
|
|
1562
|
+
}
|
|
1361
1563
|
}
|
|
1362
1564
|
return new Response(html, responseInit);
|
|
1363
1565
|
}
|
|
@@ -1442,6 +1644,10 @@ class AngularAppEngine {
|
|
|
1442
1644
|
* The manifest for the server application.
|
|
1443
1645
|
*/
|
|
1444
1646
|
this.manifest = getAngularAppEngineManifest();
|
|
1647
|
+
/**
|
|
1648
|
+
* A cache that holds entry points, keyed by their potential locale string.
|
|
1649
|
+
*/
|
|
1650
|
+
this.entryPointsCache = new Map();
|
|
1445
1651
|
}
|
|
1446
1652
|
/**
|
|
1447
1653
|
* Hooks for extending or modifying the behavior of the server application.
|
|
@@ -1478,11 +1684,11 @@ class AngularAppEngine {
|
|
|
1478
1684
|
async render(request, requestContext) {
|
|
1479
1685
|
// Skip if the request looks like a file but not `/index.html`.
|
|
1480
1686
|
const url = new URL(request.url);
|
|
1481
|
-
const entryPoint = this.
|
|
1687
|
+
const entryPoint = await this.getEntryPointExportsForUrl(url);
|
|
1482
1688
|
if (!entryPoint) {
|
|
1483
1689
|
return null;
|
|
1484
1690
|
}
|
|
1485
|
-
const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } =
|
|
1691
|
+
const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = entryPoint;
|
|
1486
1692
|
// Note: Using `instanceof` is not feasible here because `AngularServerApp` will
|
|
1487
1693
|
// be located in separate bundles, making `instanceof` checks unreliable.
|
|
1488
1694
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
@@ -1490,25 +1696,6 @@ class AngularAppEngine {
|
|
|
1490
1696
|
serverApp.hooks = this.hooks;
|
|
1491
1697
|
return serverApp.render(request, requestContext);
|
|
1492
1698
|
}
|
|
1493
|
-
/**
|
|
1494
|
-
* Retrieves the entry point path and locale for the Angular server application based on the provided URL.
|
|
1495
|
-
*
|
|
1496
|
-
* This method determines the appropriate entry point and locale for rendering the application by examining the URL.
|
|
1497
|
-
* If there is only one entry point available, it is returned regardless of the URL.
|
|
1498
|
-
* Otherwise, the method extracts a potential locale identifier from the URL and looks up the corresponding entry point.
|
|
1499
|
-
*
|
|
1500
|
-
* @param url - The URL used to derive the locale and determine the appropriate entry point.
|
|
1501
|
-
* @returns A function that returns a promise resolving to an object with the `EntryPointExports` type,
|
|
1502
|
-
* or `undefined` if no matching entry point is found for the extracted locale.
|
|
1503
|
-
*/
|
|
1504
|
-
getEntryPointFromUrl(url) {
|
|
1505
|
-
const { entryPoints, basePath } = this.manifest;
|
|
1506
|
-
if (entryPoints.size === 1) {
|
|
1507
|
-
return entryPoints.values().next().value;
|
|
1508
|
-
}
|
|
1509
|
-
const potentialLocale = getPotentialLocaleIdFromUrl(url, basePath);
|
|
1510
|
-
return entryPoints.get(potentialLocale);
|
|
1511
|
-
}
|
|
1512
1699
|
/**
|
|
1513
1700
|
* Retrieves HTTP headers for a request associated with statically generated (SSG) pages,
|
|
1514
1701
|
* based on the URL pathname.
|
|
@@ -1522,10 +1709,77 @@ class AngularAppEngine {
|
|
|
1522
1709
|
return new Map();
|
|
1523
1710
|
}
|
|
1524
1711
|
const { pathname } = stripIndexHtmlFromURL(new URL(request.url));
|
|
1525
|
-
const headers = this.manifest.staticPathsHeaders.get(pathname);
|
|
1712
|
+
const headers = this.manifest.staticPathsHeaders.get(stripTrailingSlash(pathname));
|
|
1526
1713
|
return new Map(headers);
|
|
1527
1714
|
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Retrieves the exports for a specific entry point, caching the result.
|
|
1717
|
+
*
|
|
1718
|
+
* @param potentialLocale - The locale string used to find the corresponding entry point.
|
|
1719
|
+
* @returns A promise that resolves to the entry point exports or `undefined` if not found.
|
|
1720
|
+
*/
|
|
1721
|
+
getEntryPointExports(potentialLocale) {
|
|
1722
|
+
const cachedEntryPoint = this.entryPointsCache.get(potentialLocale);
|
|
1723
|
+
if (cachedEntryPoint) {
|
|
1724
|
+
return cachedEntryPoint;
|
|
1725
|
+
}
|
|
1726
|
+
const { entryPoints } = this.manifest;
|
|
1727
|
+
const entryPoint = entryPoints.get(potentialLocale);
|
|
1728
|
+
if (!entryPoint) {
|
|
1729
|
+
return undefined;
|
|
1730
|
+
}
|
|
1731
|
+
const entryPointExports = entryPoint();
|
|
1732
|
+
this.entryPointsCache.set(potentialLocale, entryPointExports);
|
|
1733
|
+
return entryPointExports;
|
|
1734
|
+
}
|
|
1735
|
+
/**
|
|
1736
|
+
* Retrieves the entry point for a given URL by determining the locale and mapping it to
|
|
1737
|
+
* the appropriate application bundle.
|
|
1738
|
+
*
|
|
1739
|
+
* This method determines the appropriate entry point and locale for rendering the application by examining the URL.
|
|
1740
|
+
* If there is only one entry point available, it is returned regardless of the URL.
|
|
1741
|
+
* Otherwise, the method extracts a potential locale identifier from the URL and looks up the corresponding entry point.
|
|
1742
|
+
*
|
|
1743
|
+
* @param url - The URL of the request.
|
|
1744
|
+
* @returns A promise that resolves to the entry point exports or `undefined` if not found.
|
|
1745
|
+
*/
|
|
1746
|
+
getEntryPointExportsForUrl(url) {
|
|
1747
|
+
const { entryPoints, basePath } = this.manifest;
|
|
1748
|
+
if (entryPoints.size === 1) {
|
|
1749
|
+
return this.getEntryPointExports('');
|
|
1750
|
+
}
|
|
1751
|
+
const potentialLocale = getPotentialLocaleIdFromUrl(url, basePath);
|
|
1752
|
+
return this.getEntryPointExports(potentialLocale);
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* Annotates a request handler function with metadata, marking it as a special
|
|
1758
|
+
* handler.
|
|
1759
|
+
*
|
|
1760
|
+
* @param handler - The request handler function to be annotated.
|
|
1761
|
+
* @returns The same handler function passed in, with metadata attached.
|
|
1762
|
+
*
|
|
1763
|
+
* @example
|
|
1764
|
+
* Example usage in a Hono application:
|
|
1765
|
+
* ```ts
|
|
1766
|
+
* const app = new Hono();
|
|
1767
|
+
* export default createRequestHandler(app.fetch);
|
|
1768
|
+
* ```
|
|
1769
|
+
*
|
|
1770
|
+
* @example
|
|
1771
|
+
* Example usage in a H3 application:
|
|
1772
|
+
* ```ts
|
|
1773
|
+
* const app = createApp();
|
|
1774
|
+
* const handler = toWebHandler(app);
|
|
1775
|
+
* export default createRequestHandler(handler);
|
|
1776
|
+
* ```
|
|
1777
|
+
* @developerPreview
|
|
1778
|
+
*/
|
|
1779
|
+
function createRequestHandler(handler) {
|
|
1780
|
+
handler['__ng_request_handler__'] = true;
|
|
1781
|
+
return handler;
|
|
1528
1782
|
}
|
|
1529
1783
|
|
|
1530
|
-
export { AngularAppEngine, provideServerRoutesConfig, InlineCriticalCssProcessor as ɵInlineCriticalCssProcessor, destroyAngularServerApp as ɵdestroyAngularServerApp, extractRoutesAndCreateRouteTree as ɵextractRoutesAndCreateRouteTree, getOrCreateAngularServerApp as ɵgetOrCreateAngularServerApp, getRoutesFromAngularRouterConfig as ɵgetRoutesFromAngularRouterConfig, setAngularAppEngineManifest as ɵsetAngularAppEngineManifest, setAngularAppManifest as ɵsetAngularAppManifest };
|
|
1784
|
+
export { AngularAppEngine, REQUEST, REQUEST_CONTEXT, RESPONSE_INIT, RenderMode, createRequestHandler, provideServerRoutesConfig, InlineCriticalCssProcessor as ɵInlineCriticalCssProcessor, destroyAngularServerApp as ɵdestroyAngularServerApp, extractRoutesAndCreateRouteTree as ɵextractRoutesAndCreateRouteTree, getOrCreateAngularServerApp as ɵgetOrCreateAngularServerApp, getRoutesFromAngularRouterConfig as ɵgetRoutesFromAngularRouterConfig, setAngularAppEngineManifest as ɵsetAngularAppEngineManifest, setAngularAppManifest as ɵsetAngularAppManifest };
|
|
1531
1785
|
//# sourceMappingURL=ssr.mjs.map
|