@angular/ssr 19.0.0-rc.0 → 19.0.0-rc.1

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/fesm2022/ssr.mjs CHANGED
@@ -21,22 +21,31 @@ class ServerAssets {
21
21
  /**
22
22
  * Retrieves the content of a server-side asset using its path.
23
23
  *
24
- * @param path - The path to the server asset.
25
- * @returns A promise that resolves to the asset content as a string.
26
- * @throws Error If the asset path is not found in the manifest, an error is thrown.
24
+ * @param path - The path to the server asset within the manifest.
25
+ * @returns The server asset associated with the provided path, as a `ServerAsset` object.
26
+ * @throws Error - Throws an error if the asset does not exist.
27
27
  */
28
- async getServerAsset(path) {
28
+ getServerAsset(path) {
29
29
  const asset = this.manifest.assets.get(path);
30
30
  if (!asset) {
31
31
  throw new Error(`Server asset '${path}' does not exist.`);
32
32
  }
33
- return asset();
33
+ return asset;
34
34
  }
35
35
  /**
36
- * Retrieves and caches the content of 'index.server.html'.
36
+ * Checks if a specific server-side asset exists.
37
37
  *
38
- * @returns A promise that resolves to the content of 'index.server.html'.
39
- * @throws Error If there is an issue retrieving the asset.
38
+ * @param path - The path to the server asset.
39
+ * @returns A boolean indicating whether the asset exists.
40
+ */
41
+ hasServerAsset(path) {
42
+ return this.manifest.assets.has(path);
43
+ }
44
+ /**
45
+ * Retrieves the asset for 'index.server.html'.
46
+ *
47
+ * @returns The `ServerAsset` object for 'index.server.html'.
48
+ * @throws Error - Throws an error if 'index.server.html' does not exist.
40
49
  */
41
50
  getIndexServerHtml() {
42
51
  return this.getServerAsset('index.server.html');
@@ -300,6 +309,8 @@ function isNgModule(value) {
300
309
 
301
310
  /**
302
311
  * Different rendering modes for server routes.
312
+ * @see {@link provideServerRoutesConfig}
313
+ * @see {@link ServerRoute}
303
314
  * @developerPreview
304
315
  */
305
316
  var RenderMode;
@@ -316,7 +327,7 @@ var RenderMode;
316
327
  /**
317
328
  * Defines the fallback strategies for Static Site Generation (SSG) routes when a pre-rendered path is not available.
318
329
  * This is particularly relevant for routes with parameterized URLs where some paths might not be pre-rendered at build time.
319
- *
330
+ * @see {@link ServerRoutePrerenderWithParams}
320
331
  * @developerPreview
321
332
  */
322
333
  var PrerenderFallback;
@@ -347,9 +358,13 @@ const SERVER_ROUTES_CONFIG = new InjectionToken('SERVER_ROUTES_CONFIG');
347
358
  *
348
359
  * @param routes - An array of server routes to be provided.
349
360
  * @returns An `EnvironmentProviders` object that contains the server routes configuration.
361
+ * @see {@link ServerRoute}
350
362
  * @developerPreview
351
363
  */
352
364
  function provideServerRoutesConfig(routes) {
365
+ if (typeof ngServerMode === 'undefined' || !ngServerMode) {
366
+ throw new Error(`The 'provideServerRoutesConfig' function should not be invoked within the browser portion of the application.`);
367
+ }
353
368
  return makeEnvironmentProviders([
354
369
  {
355
370
  provide: SERVER_ROUTES_CONFIG,
@@ -578,6 +593,7 @@ async function* traverseRoutesConfig(options) {
578
593
  matchedMetaData.presentInClientRouter = true;
579
594
  }
580
595
  const metadata = {
596
+ renderMode: RenderMode.Prerender,
581
597
  ...matchedMetaData,
582
598
  route: currentRoutePath,
583
599
  };
@@ -883,7 +899,7 @@ async function getRoutesFromAngularRouterConfig(bootstrap, document, url, invoke
883
899
  */
884
900
  async function extractRoutesAndCreateRouteTree(url, manifest = getAngularAppManifest(), invokeGetPrerenderParams = false, includePrerenderFallbackRoutes = true) {
885
901
  const routeTree = new RouteTree();
886
- const document = await new ServerAssets(manifest).getIndexServerHtml();
902
+ const document = await new ServerAssets(manifest).getIndexServerHtml().text();
887
903
  const bootstrap = await manifest.bootstrap();
888
904
  const { baseHref, routes, errors } = await getRoutesFromAngularRouterConfig(bootstrap, document, url, invokeGetPrerenderParams, includePrerenderFallbackRoutes);
889
905
  for (const { route, ...metadata } of routes) {
@@ -1391,11 +1407,29 @@ const SERVER_CONTEXT_VALUE = {
1391
1407
  * The `AngularServerApp` class handles server-side rendering and asset management for a specific locale.
1392
1408
  */
1393
1409
  class AngularServerApp {
1410
+ options;
1394
1411
  /**
1395
- * Hooks for extending or modifying the behavior of the server application.
1396
- * This instance can be used to attach custom functionality to various events in the server application lifecycle.
1412
+ * Whether prerendered routes should be rendered on demand or served directly.
1413
+ *
1414
+ * @see {@link AngularServerAppOptions.allowStaticRouteRender} for more details.
1397
1415
  */
1398
- hooks = new Hooks();
1416
+ allowStaticRouteRender;
1417
+ /**
1418
+ * Hooks for extending or modifying server behavior.
1419
+ *
1420
+ * @see {@link AngularServerAppOptions.hooks} for more details.
1421
+ */
1422
+ hooks;
1423
+ /**
1424
+ * Constructs an instance of `AngularServerApp`.
1425
+ *
1426
+ * @param options Optional configuration options for the server application.
1427
+ */
1428
+ constructor(options = {}) {
1429
+ this.options = options;
1430
+ this.allowStaticRouteRender = this.options.allowStaticRouteRender ?? false;
1431
+ this.hooks = options.hooks ?? new Hooks();
1432
+ }
1399
1433
  /**
1400
1434
  * The manifest associated with this server application.
1401
1435
  */
@@ -1425,71 +1459,86 @@ class AngularServerApp {
1425
1459
  */
1426
1460
  criticalCssLRUCache = new LRUCache(MAX_INLINE_CSS_CACHE_ENTRIES);
1427
1461
  /**
1428
- * Renders a response for the given HTTP request using the server application.
1462
+ * Handles an incoming HTTP request by serving prerendered content, performing server-side rendering,
1463
+ * or delivering a static file for client-side rendered routes based on the `RenderMode` setting.
1429
1464
  *
1430
- * This method processes the request and returns a response based on the specified rendering context.
1465
+ * @param request - The HTTP request to handle.
1466
+ * @param requestContext - Optional context for rendering, such as metadata associated with the request.
1467
+ * @returns A promise that resolves to the resulting HTTP response object, or `null` if no matching Angular route is found.
1431
1468
  *
1432
- * @param request - The incoming HTTP request to be rendered.
1433
- * @param requestContext - Optional additional context for rendering, such as request metadata.
1434
- *
1435
- * @returns A promise that resolves to the HTTP response object resulting from the rendering, or null if no match is found.
1469
+ * @remarks A request to `https://www.example.com/page/index.html` will serve or render the Angular route
1470
+ * corresponding to `https://www.example.com/page`.
1436
1471
  */
1437
- render(request, requestContext) {
1472
+ async handle(request, requestContext) {
1473
+ const url = new URL(request.url);
1474
+ this.router ??= await ServerRouter.from(this.manifest, url);
1475
+ const matchedRoute = this.router.match(url);
1476
+ if (!matchedRoute) {
1477
+ // Not a known Angular route.
1478
+ return null;
1479
+ }
1480
+ if (matchedRoute.renderMode === RenderMode.Prerender) {
1481
+ const response = await this.handleServe(request, matchedRoute);
1482
+ if (response) {
1483
+ return response;
1484
+ }
1485
+ }
1438
1486
  return Promise.race([
1439
- this.createAbortPromise(request),
1440
- this.handleRendering(request, /** isSsrMode */ true, requestContext),
1487
+ this.waitForRequestAbort(request),
1488
+ this.handleRendering(request, matchedRoute, requestContext),
1441
1489
  ]);
1442
1490
  }
1443
1491
  /**
1444
- * Renders a page based on the provided URL via server-side rendering and returns the corresponding HTTP response.
1445
- * The rendering process can be interrupted by an abort signal, where the first resolved promise (either from the abort
1446
- * or the render process) will dictate the outcome.
1492
+ * Handles serving a prerendered static asset if available for the matched route.
1447
1493
  *
1448
- * @param url - The full URL to be processed and rendered by the server.
1449
- * @param signal - (Optional) An `AbortSignal` object that allows for the cancellation of the rendering process.
1450
- * @returns A promise that resolves to the generated HTTP response object, or `null` if no matching route is found.
1451
- */
1452
- renderStatic(url, signal) {
1453
- const request = new Request(url, { signal });
1454
- return Promise.race([
1455
- this.createAbortPromise(request),
1456
- this.handleRendering(request, /** isSsrMode */ false),
1457
- ]);
1458
- }
1459
- /**
1460
- * Creates a promise that rejects when the request is aborted.
1494
+ * This method only supports `GET` and `HEAD` requests.
1461
1495
  *
1462
- * @param request - The HTTP request to monitor for abortion.
1463
- * @returns A promise that never resolves but rejects with an `AbortError` if the request is aborted.
1496
+ * @param request - The incoming HTTP request for serving a static page.
1497
+ * @param matchedRoute - The metadata of the matched route for rendering.
1498
+ * If not provided, the method attempts to find a matching route based on the request URL.
1499
+ * @returns A promise that resolves to a `Response` object if the prerendered page is found, or `null`.
1464
1500
  */
1465
- createAbortPromise(request) {
1466
- return new Promise((_, reject) => {
1467
- request.signal.addEventListener('abort', () => {
1468
- const abortError = new Error(`Request for: ${request.url} was aborted.\n${request.signal.reason}`);
1469
- abortError.name = 'AbortError';
1470
- reject(abortError);
1471
- }, { once: true });
1472
- });
1501
+ async handleServe(request, matchedRoute) {
1502
+ const { headers, renderMode } = matchedRoute;
1503
+ if (renderMode !== RenderMode.Prerender) {
1504
+ return null;
1505
+ }
1506
+ const { url, method } = request;
1507
+ if (method !== 'GET' && method !== 'HEAD') {
1508
+ return null;
1509
+ }
1510
+ const { pathname } = stripIndexHtmlFromURL(new URL(request.url));
1511
+ const assetPath = stripLeadingSlash(joinUrlParts(pathname, 'index.html'));
1512
+ if (!this.assets.hasServerAsset(assetPath)) {
1513
+ return null;
1514
+ }
1515
+ const { text, hash, size } = this.assets.getServerAsset(assetPath);
1516
+ const etag = `"${hash}"`;
1517
+ return request.headers.get('if-none-match') === etag
1518
+ ? new Response(undefined, { status: 304, statusText: 'Not Modified' })
1519
+ : new Response(await text(), {
1520
+ headers: {
1521
+ 'Content-Length': size.toString(),
1522
+ 'ETag': etag,
1523
+ 'Content-Type': 'text/html;charset=UTF-8',
1524
+ ...headers,
1525
+ },
1526
+ });
1473
1527
  }
1474
1528
  /**
1475
1529
  * Handles the server-side rendering process for the given HTTP request.
1476
1530
  * This method matches the request URL to a route and performs rendering if a matching route is found.
1477
1531
  *
1478
1532
  * @param request - The incoming HTTP request to be processed.
1479
- * @param isSsrMode - A boolean indicating whether the rendering is performed in server-side rendering (SSR) mode.
1533
+ * @param matchedRoute - The metadata of the matched route for rendering.
1534
+ * If not provided, the method attempts to find a matching route based on the request URL.
1480
1535
  * @param requestContext - Optional additional context for rendering, such as request metadata.
1481
1536
  *
1482
1537
  * @returns A promise that resolves to the rendered response, or null if no matching route is found.
1483
1538
  */
1484
- async handleRendering(request, isSsrMode, requestContext) {
1485
- const url = new URL(request.url);
1486
- this.router ??= await ServerRouter.from(this.manifest, url);
1487
- const matchedRoute = this.router.match(url);
1488
- if (!matchedRoute) {
1489
- // Not a known Angular route.
1490
- return null;
1491
- }
1539
+ async handleRendering(request, matchedRoute, requestContext) {
1492
1540
  const { redirectTo, status } = matchedRoute;
1541
+ const url = new URL(request.url);
1493
1542
  if (redirectTo !== undefined) {
1494
1543
  // Note: The status code is validated during route extraction.
1495
1544
  // 302 Found is used by default for redirections
@@ -1497,35 +1546,36 @@ class AngularServerApp {
1497
1546
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1498
1547
  return Response.redirect(new URL(redirectTo, url), status ?? 302);
1499
1548
  }
1500
- const { renderMode = isSsrMode ? RenderMode.Server : RenderMode.Prerender, headers } = matchedRoute;
1549
+ const { renderMode, headers } = matchedRoute;
1550
+ if (!this.allowStaticRouteRender &&
1551
+ (renderMode === RenderMode.Prerender || renderMode === RenderMode.AppShell)) {
1552
+ return null;
1553
+ }
1501
1554
  const platformProviders = [];
1502
- let responseInit;
1503
- if (isSsrMode) {
1504
- // Initialize the response with status and headers if available.
1505
- responseInit = {
1506
- status,
1507
- headers: new Headers({
1508
- 'Content-Type': 'text/html;charset=UTF-8',
1509
- ...headers,
1510
- }),
1511
- };
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) {
1526
- // Serve the client-side rendered version if the route is configured for CSR.
1527
- return new Response(await this.assets.getServerAsset('index.csr.html'), responseInit);
1528
- }
1555
+ // Initialize the response with status and headers if available.
1556
+ const responseInit = {
1557
+ status,
1558
+ headers: new Headers({
1559
+ 'Content-Type': 'text/html;charset=UTF-8',
1560
+ ...headers,
1561
+ }),
1562
+ };
1563
+ if (renderMode === RenderMode.Server) {
1564
+ // Configure platform providers for request and response only for SSR.
1565
+ platformProviders.push({
1566
+ provide: REQUEST,
1567
+ useValue: request,
1568
+ }, {
1569
+ provide: REQUEST_CONTEXT,
1570
+ useValue: requestContext,
1571
+ }, {
1572
+ provide: RESPONSE_INIT,
1573
+ useValue: responseInit,
1574
+ });
1575
+ }
1576
+ else if (renderMode === RenderMode.Client) {
1577
+ // Serve the client-side rendered version if the route is configured for CSR.
1578
+ return new Response(await this.assets.getServerAsset('index.csr.html').text(), responseInit);
1529
1579
  }
1530
1580
  const { manifest: { bootstrap, inlineCriticalCss, locale }, hooks, assets, } = this;
1531
1581
  if (locale !== undefined) {
@@ -1534,7 +1584,7 @@ class AngularServerApp {
1534
1584
  useValue: locale,
1535
1585
  });
1536
1586
  }
1537
- let html = await assets.getIndexServerHtml();
1587
+ let html = await assets.getIndexServerHtml().text();
1538
1588
  // Skip extra microtask if there are no pre hooks.
1539
1589
  if (hooks.has('html:transform:pre')) {
1540
1590
  html = await hooks.run('html:transform:pre', { html, url });
@@ -1545,16 +1595,16 @@ class AngularServerApp {
1545
1595
  // Optionally inline critical CSS.
1546
1596
  this.inlineCriticalCssProcessor ??= new InlineCriticalCssProcessor((path) => {
1547
1597
  const fileName = path.split('/').pop() ?? path;
1548
- return this.assets.getServerAsset(fileName);
1598
+ return this.assets.getServerAsset(fileName).text();
1549
1599
  });
1550
1600
  // TODO(alanagius): remove once Node.js version 18 is no longer supported.
1551
- if (isSsrMode && typeof crypto === 'undefined') {
1601
+ if (renderMode === RenderMode.Server && typeof crypto === 'undefined') {
1552
1602
  // eslint-disable-next-line no-console
1553
1603
  console.error(`The global 'crypto' module is unavailable. ` +
1554
1604
  `If you are running on Node.js, please ensure you are using version 20 or later, ` +
1555
1605
  `which includes built-in support for the Web Crypto module.`);
1556
1606
  }
1557
- if (isSsrMode && typeof crypto !== 'undefined') {
1607
+ if (renderMode === RenderMode.Server && typeof crypto !== 'undefined') {
1558
1608
  // Only cache if we are running in SSR Mode.
1559
1609
  const cacheKey = await sha256(html);
1560
1610
  let htmlWithCriticalCss = this.criticalCssLRUCache.get(cacheKey);
@@ -1570,16 +1620,35 @@ class AngularServerApp {
1570
1620
  }
1571
1621
  return new Response(html, responseInit);
1572
1622
  }
1623
+ /**
1624
+ * Returns a promise that rejects if the request is aborted.
1625
+ *
1626
+ * @param request - The HTTP request object being monitored for abortion.
1627
+ * @returns A promise that never resolves and rejects with an `AbortError`
1628
+ * if the request is aborted.
1629
+ */
1630
+ waitForRequestAbort(request) {
1631
+ return new Promise((_, reject) => {
1632
+ request.signal.addEventListener('abort', () => {
1633
+ const abortError = new Error(`Request for: ${request.url} was aborted.\n${request.signal.reason}`);
1634
+ abortError.name = 'AbortError';
1635
+ reject(abortError);
1636
+ }, { once: true });
1637
+ });
1638
+ }
1573
1639
  }
1574
1640
  let angularServerApp;
1575
1641
  /**
1576
1642
  * Retrieves or creates an instance of `AngularServerApp`.
1577
1643
  * - If an instance of `AngularServerApp` already exists, it will return the existing one.
1578
1644
  * - If no instance exists, it will create a new one with the provided options.
1645
+ *
1646
+ * @param options Optional configuration options for the server application.
1647
+ *
1579
1648
  * @returns The existing or newly created instance of `AngularServerApp`.
1580
1649
  */
1581
- function getOrCreateAngularServerApp() {
1582
- return (angularServerApp ??= new AngularServerApp());
1650
+ function getOrCreateAngularServerApp(options) {
1651
+ return (angularServerApp ??= new AngularServerApp(options));
1583
1652
  }
1584
1653
  /**
1585
1654
  * Destroys the existing `AngularServerApp` instance, releasing associated resources and resetting the
@@ -1640,12 +1709,21 @@ function getPotentialLocaleIdFromUrl(url, basePath) {
1640
1709
  * Manages Angular server applications (including localized ones), handles rendering requests,
1641
1710
  * and optionally transforms index HTML before rendering.
1642
1711
  *
1643
- * @note This class should be instantiated once and used as a singleton across the server-side
1712
+ * @remarks This class should be instantiated once and used as a singleton across the server-side
1644
1713
  * application to ensure consistent handling of rendering requests and resource management.
1645
1714
  *
1646
1715
  * @developerPreview
1647
1716
  */
1648
1717
  class AngularAppEngine {
1718
+ /**
1719
+ * A flag to enable or disable the rendering of prerendered routes.
1720
+ *
1721
+ * Typically used during development to avoid prerendering all routes ahead of time,
1722
+ * allowing them to be rendered on the fly as requested.
1723
+ *
1724
+ * @private
1725
+ */
1726
+ static ɵallowStaticRouteRender = false;
1649
1727
  /**
1650
1728
  * Hooks for extending or modifying the behavior of the server application.
1651
1729
  * These hooks are used by the Angular CLI when running the development server and
@@ -1654,15 +1732,6 @@ class AngularAppEngine {
1654
1732
  * @private
1655
1733
  */
1656
1734
  static ɵhooks = /* #__PURE__*/ new Hooks();
1657
- /**
1658
- * Provides access to the hooks for extending or modifying the server application's behavior.
1659
- * This allows attaching custom functionality to various server application lifecycle events.
1660
- *
1661
- * @internal
1662
- */
1663
- get hooks() {
1664
- return AngularAppEngine.ɵhooks;
1665
- }
1666
1735
  /**
1667
1736
  * The manifest for the server application.
1668
1737
  */
@@ -1672,50 +1741,46 @@ class AngularAppEngine {
1672
1741
  */
1673
1742
  entryPointsCache = new Map();
1674
1743
  /**
1675
- * Renders a response for the given HTTP request using the server application.
1744
+ * Handles an incoming HTTP request by serving prerendered content, performing server-side rendering,
1745
+ * or delivering a static file for client-side rendered routes based on the `RenderMode` setting.
1676
1746
  *
1677
- * This method processes the request, determines the appropriate route and rendering context,
1678
- * and returns an HTTP response.
1747
+ * @param request - The HTTP request to handle.
1748
+ * @param requestContext - Optional context for rendering, such as metadata associated with the request.
1749
+ * @returns A promise that resolves to the resulting HTTP response object, or `null` if no matching Angular route is found.
1679
1750
  *
1680
- * If the request URL appears to be for a file (excluding `/index.html`), the method returns `null`.
1681
- * A request to `https://www.example.com/page/index.html` will render the Angular route
1751
+ * @remarks A request to `https://www.example.com/page/index.html` will serve or render the Angular route
1682
1752
  * corresponding to `https://www.example.com/page`.
1753
+ */
1754
+ async handle(request, requestContext) {
1755
+ const serverApp = await this.getAngularServerAppForRequest(request);
1756
+ return serverApp ? serverApp.handle(request, requestContext) : null;
1757
+ }
1758
+ /**
1759
+ * Retrieves the Angular server application instance for a given request.
1760
+ *
1761
+ * This method checks if the request URL corresponds to an Angular application entry point.
1762
+ * If so, it initializes or retrieves an instance of the Angular server application for that entry point.
1763
+ * Requests that resemble file requests (except for `/index.html`) are skipped.
1683
1764
  *
1684
- * @param request - The incoming HTTP request object to be rendered.
1685
- * @param requestContext - Optional additional context for the request, such as metadata.
1686
- * @returns A promise that resolves to a Response object, or `null` if the request URL represents a file (e.g., `./logo.png`)
1687
- * rather than an application route.
1765
+ * @param request - The incoming HTTP request object.
1766
+ * @returns A promise that resolves to an `AngularServerApp` instance if a valid entry point is found,
1767
+ * or `null` if no entry point matches the request URL.
1688
1768
  */
1689
- async render(request, requestContext) {
1769
+ async getAngularServerAppForRequest(request) {
1690
1770
  // Skip if the request looks like a file but not `/index.html`.
1691
1771
  const url = new URL(request.url);
1692
1772
  const entryPoint = await this.getEntryPointExportsForUrl(url);
1693
1773
  if (!entryPoint) {
1694
1774
  return null;
1695
1775
  }
1696
- const { ɵgetOrCreateAngularServerApp: getOrCreateAngularServerApp } = entryPoint;
1697
1776
  // Note: Using `instanceof` is not feasible here because `AngularServerApp` will
1698
1777
  // be located in separate bundles, making `instanceof` checks unreliable.
1699
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
1700
- const serverApp = getOrCreateAngularServerApp();
1701
- serverApp.hooks = this.hooks;
1702
- return serverApp.render(request, requestContext);
1703
- }
1704
- /**
1705
- * Retrieves HTTP headers for a request associated with statically generated (SSG) pages,
1706
- * based on the URL pathname.
1707
- *
1708
- * @param request - The incoming request object.
1709
- * @returns A `Map` containing the HTTP headers as key-value pairs.
1710
- * @note This function should be used exclusively for retrieving headers of SSG pages.
1711
- */
1712
- getPrerenderHeaders(request) {
1713
- if (this.manifest.staticPathsHeaders.size === 0) {
1714
- return new Map();
1715
- }
1716
- const { pathname } = stripIndexHtmlFromURL(new URL(request.url));
1717
- const headers = this.manifest.staticPathsHeaders.get(stripTrailingSlash(pathname));
1718
- return new Map(headers);
1778
+ const ɵgetOrCreateAngularServerApp = entryPoint.ɵgetOrCreateAngularServerApp;
1779
+ const serverApp = ɵgetOrCreateAngularServerApp({
1780
+ allowStaticRouteRender: AngularAppEngine.ɵallowStaticRouteRender,
1781
+ hooks: AngularAppEngine.ɵhooks,
1782
+ });
1783
+ return serverApp;
1719
1784
  }
1720
1785
  /**
1721
1786
  * Retrieves the exports for a specific entry point, caching the result.