* build: disconnect `@npm` workspace from main project
This will speed up significantly as we don't need to fetch all
dependencies again just for the `@npm` repository that is at this point
only leveraged by the `ng_package` rule for some of its dependencies.
This commit allows us to drop the `yarn.lock` and Aspect lock files, and
allows us to independently migrate `ng_package` to `rules_js`.
It also allows us to drop the `_rjs` TS interop layer in follow-up commits.
* build: drop `_rjs` suffix from `ts_project` targets
We don't need the `ts_project` interop in principle
at this point. We only have one remaining instance left for the SSR
`ng_package` integration. This commit cleans up all usages.
* build: remove yarn
* build: avoid duplicated dependencies at top-level
`rules_js` seems to be sensitive if there are similar versions of the same
package installed, but with differently matched peer dependencies. This
is fine because we can (and should long-term) move those dependencies to
their package-local `package.json` files. This commit unblocks the
migration and highlights how we can move deps to the individual packages
in the future.
* build: update checkout github action
This will allow us to use pnpm.
* build: update node to avoid strict-engines error caused by `npm`
Avoids:
```
Lockfile is up to date, resolution step is skipped
ERR_PNPM_UNSUPPORTED_ENGINE Unsupported environment (bad pnpm and/or Node.js version)
Your Node version is incompatible with "npm@11.2.0".
Expected version: ^20.17.0 || >=22.9.0
Got: v20.11.1
```
Note that we won't update the WORKSPACE test version as that would mean
we need to update the Node engines for shipped packages; and we can't do
this right now without introducing a breaking change.
* build: fix missing dependency for spec bundling
The beasties JS sources weren't available for bundling in the
`bazel-bin`, and this surfaced in RBE. This commit fixes this.
As part of go/ng:windows-dev-future, we are changing how our
infrastructure supports Windows build & testing. Clearly:
- we will still support contributors on Windows, and we believe we will
be improving and streamlining the experience here
- we will continue testing the Angular CLI for our Windows users. We are
aware of the many Windows users using the `ng` CLI.
What is changing? We are no longer actively working towards a Bazel infrastructure
that supports native Windows building and testing. There are currently
two ways to contribute to Angular on Windows. That is via WSL, or via
e.g. native Windows cmd.exe, with Git Bash on top. We acknowledge that
the latter worked sometimes, but we also realize it very often breaks as
nobody on our team uses, verifies it, and it introduces extra complexity
because Bazel on Windows is quite disconnected from Linux/Mac (e.g. no
sandboxing). Going forward, to improve our team's effectiveness, and
improve our stability guarantees for Windows (and Windows contributors),
we are actively discouraging the use of Git Bash for contributing to
Angular; but instead ask for WSL to be used. I can speak as one of the
few long-term team members that have worked on Windows (without WSL) most
of my time, that WSL is great and the contributing experience is much
smoother and also easier to "guide". It's a positive change because we
won't be suggesting "two ways to contribute on Windows", where in
reality one is very brittle and can break at any time!
---
For testing of the Angular CLI: We will continue to maintain the
capability to cross-compile via Bazel with Windows as the target
platform. This allows us to build the e2e tests for Windows, and run
them natively outside WSL to ensure native Windows `ng` CLI testing!
This is what this change mostly does.
Notably, two things are missing here and will be followed up:
- caching of the e2e tests on Windows is not properly functioning yet.
- caching of the WSL node modules + nvm is not working properly yet.
Other than that, we are seeing very similar timing and results of the
Windows tests, so this change unblocks our `rules_js` migration.
Ensures that the SSR router gives precedence to the first matching route, addressing the issue where later conflicting routes.
This change prevents the incorrect prioritization of routes and ensures the intended route is matched first, aligning routing behavior.
Closes: #29539
This commit adds support for custom route matchers in Angular SSR, allowing fine-grained control over the `renderMode` (Server, Client) for individual routes, including those defined with matchers.
Routes with custom matchers are **not** supported during prerendering and must explicitly define a `renderMode` of either server or client.
The following configuration demonstrates how to use glob patterns (including recursive `**`) to define server-side rendering (SSR) or client-side rendering (CSR) for specific parts of the 'product' route and its child routes.
```typescript
// app.routes.ts
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: '',
component: DummyComponent,
},
{
path: 'product',
component: DummyComponent,
children: [
{
path: '',
component: DummyComponent,
},
{
path: 'list',
component: DummyComponent,
},
{
matcher: () => null, // Example custom matcher (always returns null)
component: DummyComponent,
},
],
},
];
```
```typescript
// app.routes.server.ts
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{ path: '**', renderMode: RenderMode.Client },
{ path: 'product', renderMode: RenderMode.Prerender },
{ path: 'product/list', renderMode: RenderMode.Prerender },
{ path: 'product/**/overview/details', renderMode: RenderMode.Server },
];
```
Closes#29284
When redirecting to the preferred locale, the previous implementation used the full URL for the 302 redirect to i18n subpaths based on the user's preferred locale. This update ensures that the redirect now uses the locale-specific pathname instead of the full URL.
Closes#29514
This commit renames `provideServerRoutesConfig` to `provideServerRouting` and updates the second parameter to use the `ServerRoutes` features.
This change improves alignment with the framework's API conventions and the way features are integrated.
### Example Usage:
Before:
```typescript
provideServerRoutesConfig(serverRoutes, { appShellRoute: 'shell' })
```
After:
```typescript
provideServerRouting(serverRoutes, withAppShell(AppShellComponent))
```
Updated route matching logic to prioritize closest matches, improving the accuracy of dynamic route resolution. Also we optimized performance by eliminating unnecessary recursive checks, reducing overhead during route matching.
Closes#29452
Migrates the SSR tesst to run natively via `rules_js`. Notably, we still
need the bundling in between as the tests and SSR plain code is not
valid ESM technically; due to lack of extensions.
We'll need to revisit this in the future, or at the very least come up
with a `rules_js`-variant of the `spec_bundle`; but for this is
sufficient and unblocks other packages.
This fix ensures that catch-all routes (e.g., wildcard routes like `**`) are handled correctly when a base href is configured in an Angular SSR application.
Closes#29397
This is necessary as `rules_js` requires this "common name" when dealing
with Yarn workspaces, linking first party dependencies automatically.
In the future, we may be able to send a PR to `rules_js` to support a
custom name somehow.
Previously, when the application was served behind a proxy, server-side redirects generated an incorrect Location header, causing navigation issues. This fix updates `createRequestUrl` to use the port from the Host header, ensuring accurate in proxy environments. Additionally, the Location header now only contains the pathname, improving compliance with redirect handling in such setups.
Closes#29151
When users access the root route `/` without providing a locale, the application now redirects them to their preferred locale based on the `Accept-Language` header.
This enhancement leverages the user's browser preferences to determine the most appropriate locale, providing a seamless and personalized experience without requiring manual locale selection.
Enhance performance when using SSR by adding `modulepreload` links to lazy-loaded routes. This ensures that the required modules are preloaded in the background, improving the user experience and reducing the time to interactive.
Closes#26484
This update addresses excessive log noise caused by the following warning:
`NG0912: Component ID generation collision detected. Components 'AppComponent' and 'AppComponent' with selector 'app-root' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID. Find more at https://angular.dev/errors/NG0912`.
This commit ensures proper handling of nested redirects that are implicitly structured but not explicitly defined in the router configuration.
Closes#28903
This commit removes the `RenderMode.AppShell` option. Instead, a new configuration parameter, `{ appShellRoute: 'shell' }`, is introduced to the `provideServerRoutesConfig` method.
```ts
provideServerRoutesConfig(serverRoutes, { appShellRoute: 'shell' })
```
This commit cleans up duplicate code left from the previous implementations of process, serve, and render. Additionally, prerender serve now exclusively handles HEAD and GET requests, aligning with updated handling requirements. The private `renderStatic` method has been removed in favor of the `handle` method for improved maintainability.
When using the new developer preview API to serve prerendered pages, ETags are added automatically, enabling efficient caching and content validation for improved performance.
This commit implements the capability for the App Engine to serve prerendered pages directly. Previously, we relied on frameworks like Express for this functionality, which resulted in inconsistent redirects for directories where in some cases a trailing slash was added to the route.
**Note:** This change applies only when using the new SSR APIs. When using the `CommonEngine`, a 3rd party static serve middleware is still required.
Esbuild exhibits issues when handling code that is generated and then reprocessed by itself, creating challenges when using it to bundle libraries or library components.
To remove these issues, we've replaced Esbuild with Rollup for bundling `beasties`.
See: https://github.com/evanw/esbuild/issues/3723
The Critters project has been transferred to the Nuxt team, who will now manage its development and has been renamed to Beasties.
See: https://github.com/danielroe/beasties
Implement LRU cache for inlined CSS in server-side rendered HTML.
This optimization significantly improves server-side rendering performance by reusing previously inlined styles and reducing the overhead of repeated CSS inlining.
Performance improvements observed:
Performance improvements observed:
* **Latency:** Reduced by ~18.1% (from 1.01s to 827.47ms)
* **Requests per Second:** Increased by ~24.1% (from 381.16 to 472.85)
* **Transfer per Second:** Increased by ~24.1% (from 0.87MB to 1.08MB)
These gains demonstrate the effectiveness of caching inlined CSS for frequently accessed pages, resulting in a faster and more efficient user experience.
This change introduces error handling to ensure that when multiple routes are configured with `RenderMode.AppShell`, an error message is displayed. This prevents misconfiguration and enhances clarity in route management.
This commit resolves an issue where routes defined in the Angular server routing configuration did not match those in the Angular router. Previously, discrepancies between these routes went unnoticed by users. With this update, appropriate error messages are now displayed when mismatches occur, enhancing the developer experience and facilitating easier troubleshooting.
Modified the `HtmlTransformHandler` type to accept a context object containing a URL and HTML content. This change supports the `html:transform:pre` hook, enhancing the handler's capability to process transformations based on the request URL.
The `outputMode` option accepts two values:
- **`static`:** Generates a static output (HTML, CSS, JavaScript) suitable for deployment on static hosting services or CDNs. This mode supports both client-side rendering (CSR) and static site generation (SSG).
- **`server`:** Generates a server bundle in addition to static assets, enabling server-side rendering (SSR) and hybrid rendering strategies. This output is intended for deployment on a Node.js server or serverless environment.
- **Replaces `appShell` and `prerender`:** The `outputMode` option simplifies the CLI by replacing the `appShell` and `prerender` options when server-side routing is configured.
- **Controls Server API Usage:** `outputMode` determines whether the new server API is utilized. In `server` mode, `server.ts` is bundled as a separate entry point, preventing direct references to `main.server.ts` and excluding it from localization.
Closes#27356, closes#27403, closes#25726, closes#25718 and closes#27196
This option allows validation during the build process to ensure that, when the output mode is set to static, no routes requiring server-side rendering are included.
This commit introduces the following changes:
- Disallows paths starting with a slash to match Angular router behavior.
- Errors are now stored and displayed at a later stage, improving UX by avoiding unnecessary stack traces that are not useful in this context.
This commit introduces a new `getHeaders` method to the `AngularAppEngine` and `AngularNodeAppEngine` classes, designed to facilitate the retrieval of HTTP headers based on URL pathnames for statically generated (SSG) pages.
```typescript
const angularAppEngine = new AngularNodeAppEngine();
app.use(express.static('dist/browser', {
setHeaders: (res, path) => {
// Retrieve headers for the current request
const headers = angularAppEngine.getHeaders(res.req);
// Apply the retrieved headers to the response
for (const { key, value } of headers) {
res.setHeader(key, value);
}
}
}));
```
In this example, the `getHeaders` method is used within an Express application to dynamically set HTTP headers for static files. This ensures that appropriate headers are applied based on the specific request, enhancing the handling of SSG pages.
This refactor moves the Node.js-specific request and response helper functions to the /node entry point. This change improves modularity by separating Node.js-specific logic from the main SSR codebase.
- Implemented functionality to compare and update third-party license files
- Added handling for '--accept' argument to update the golden license file
- Included tests to ensure the Critters license file matches the golden reference
This update ensures license file consistency and provides an easy way to update the reference file when necessary.