Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
<a name="19.0.0-next.12"></a>

# 19.0.0-next.12 (2024-10-21)

## Breaking Changes

### @angular-devkit/build-angular

- Protractor is no longer supported.

Protractor was marked end-of-life in August 2023 (see https://protractortest.org/). Projects still relying on Protractor should consider migrating to another E2E testing framework, several support solid migration paths from Protractor.

- https://angular.dev/tools/cli/end-to-end
- https://blog.angular.dev/the-state-of-end-to-end-testing-with-angular-d175f751cb9c

### @angular-devkit/build-angular

| Commit | Type | Description |
| --------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------- |
| [62877bdf2](https://github.com/angular/angular-cli/commit/62877bdf2b0449d8c12a167c59d0c24c77467f37) | refactor | remove Protractor builder and schematics |

### @angular/build

| Commit | Type | Description |
| --------------------------------------------------------------------------------------------------- | ---- | ----------------------------------------------------- |
| [1654acf0f](https://github.com/angular/angular-cli/commit/1654acf0ff3010b619a22d11f17eec9975d8e2a2) | fix | relax constraints on external stylesheet component id |

### @angular/ssr

| Commit | Type | Description |
| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------- |
| [44077f54e](https://github.com/angular/angular-cli/commit/44077f54e9a95afa5c1f85cf198aaa3412ee08d8) | fix | designate package as side-effect free |

<!-- CHANGELOG SPLIT MARKER -->

<a name="19.0.0-next.11"></a>

# 19.0.0-next.11 (2024-10-16)
Expand Down
6 changes: 3 additions & 3 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ yarn_install(

http_archive(
name = "aspect_bazel_lib",
sha256 = "0e31778f1fd574d2c05d238bfc4c785fa4b7e50a5ef38b506e01cfd8ec2fccb3",
strip_prefix = "bazel-lib-2.9.2",
url = "https://github.com/aspect-build/bazel-lib/releases/download/v2.9.2/bazel-lib-v2.9.2.tar.gz",
sha256 = "a272d79bb0ac6b6965aa199b1f84333413452e87f043b53eca7f347a23a478e8",
strip_prefix = "bazel-lib-2.9.3",
url = "https://github.com/aspect-build/bazel-lib/releases/download/v2.9.3/bazel-lib-v2.9.3.tar.gz",
)

load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "aspect_bazel_lib_register_toolchains")
Expand Down
1 change: 1 addition & 0 deletions goldens/public-api/angular/build/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export interface ApplicationBuilderOptions {
preserveSymlinks?: boolean;
progress?: boolean;
scripts?: ScriptElement[];
security?: Security;
server?: string;
serviceWorker?: ServiceWorker_2;
sourceMap?: SourceMapUnion;
Expand Down
10 changes: 0 additions & 10 deletions goldens/public-api/angular/ssr/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
```ts

import { EnvironmentProviders } from '@angular/core';
import { InjectionToken } from '@angular/core';

// @public
export class AngularAppEngine {
Expand Down Expand Up @@ -35,15 +34,6 @@ export enum RenderMode {
Server = 1
}

// @public
export const REQUEST: InjectionToken<Request>;

// @public
export const REQUEST_CONTEXT: InjectionToken<unknown>;

// @public
export const RESPONSE_INIT: InjectionToken<ResponseInit>;

// @public
export type ServerRoute = ServerRouteAppShell | ServerRouteClient | ServerRoutePrerender | ServerRoutePrerenderWithParams | ServerRouteServer;

Expand Down
20 changes: 20 additions & 0 deletions goldens/public-api/angular/ssr/tokens/index.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## API Report File for "@angular/ssr_tokens"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import { InjectionToken } from '@angular/core';

// @public
export const REQUEST: InjectionToken<Request>;

// @public
export const REQUEST_CONTEXT: InjectionToken<unknown>;

// @public
export const RESPONSE_INIT: InjectionToken<ResponseInit>;

// (No @packageDocumentation comment for this package)

```
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
"projectType": "application",
"targets": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"builder": "@angular-devkit/build-angular:private-protractor",
"options": {
"protractorConfig": "protractor.conf.js",
"devServerTarget": "app:serve",
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@angular/devkit-repo",
"version": "19.0.0-next.11",
"version": "19.0.0-next.12",
"private": true,
"description": "Software Development Kit for Angular",
"keywords": [
Expand Down Expand Up @@ -79,7 +79,7 @@
"@babel/plugin-transform-runtime": "7.25.7",
"@babel/preset-env": "7.25.8",
"@babel/runtime": "7.25.7",
"@bazel/bazelisk": "1.22.0",
"@bazel/bazelisk": "1.22.1",
"@bazel/buildifier": "7.3.1",
"@bazel/concatjs": "patch:@bazel/concatjs@npm%3A5.8.1#~/.yarn/patches/@bazel-concatjs-npm-5.8.1-1bf81df846.patch",
"@bazel/jasmine": "patch:@bazel/jasmine@npm%3A5.8.1#~/.yarn/patches/@bazel-jasmine-npm-5.8.1-3370fee155.patch",
Expand Down Expand Up @@ -114,8 +114,8 @@
"@types/yargs": "^17.0.20",
"@types/yargs-parser": "^21.0.0",
"@types/yarnpkg__lockfile": "^1.1.5",
"@typescript-eslint/eslint-plugin": "8.10.0",
"@typescript-eslint/parser": "8.10.0",
"@typescript-eslint/eslint-plugin": "8.11.0",
"@typescript-eslint/parser": "8.11.0",
"@vitejs/plugin-basic-ssl": "1.1.0",
"@web/test-runner": "^0.19.0",
"@yarnpkg/lockfile": "1.1.0",
Expand Down Expand Up @@ -186,7 +186,7 @@
"rollup": "4.24.0",
"rollup-plugin-sourcemaps": "^0.6.0",
"rxjs": "7.8.1",
"sass": "1.80.2",
"sass": "1.80.3",
"sass-loader": "16.0.2",
"semver": "7.6.3",
"shelljs": "^0.8.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"picomatch": "4.0.2",
"piscina": "4.7.0",
"rollup": "4.24.0",
"sass": "1.80.2",
"sass": "1.80.3",
"semver": "7.6.3",
"vite": "5.4.9",
"watchpack": "2.4.2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ export async function executeBuild(
);
}

// Override auto-CSP settings if we are serving through Vite middleware.
if (context.builder.builderName === 'dev-server' && options.security) {
options.security.autoCsp = false;
}

// Perform i18n translation inlining if enabled
if (i18nOptions.shouldInline) {
const result = await inlineI18n(options, executionResult, initialFiles);
Expand Down
2 changes: 2 additions & 0 deletions packages/angular/build/src/builders/application/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export async function normalizeOptions(
partialSSRBuild = false,
externalRuntimeStyles,
instrumentForCoverage,
security,
} = options;

// Return all the normalized options
Expand Down Expand Up @@ -461,6 +462,7 @@ export async function normalizeOptions(
partialSSRBuild: usePartialSsrBuild || partialSSRBuild,
externalRuntimeStyles,
instrumentForCoverage,
security,
};
}

Expand Down
27 changes: 27 additions & 0 deletions packages/angular/build/src/builders/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,33 @@
"type": "string",
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
},
"security": {
"description": "Security features to protect against XSS and other common attacks",
"type": "object",
"additionalProperties": false,
"properties": {
"autoCsp": {
"description": "Enables automatic generation of a hash-based Strict Content Security Policy (https://web.dev/articles/strict-csp#choose-hash) based on scripts in index.html. Will default to true once we are out of experimental/preview phases.",
"default": false,
"oneOf": [
{
"type": "object",
"properties": {
"unsafeEval": {
"type": "boolean",
"description": "Include the `unsafe-eval` directive (https://web.dev/articles/strict-csp#remove-eval) in the auto-CSP. Please only enable this if you are absolutely sure that you need to, as allowing calls to eval will weaken the XSS defenses provided by the auto-CSP.",
"default": false
}
},
"additionalProperties": false
},
{
"type": "boolean"
}
]
}
}
},
"scripts": {
"description": "Global scripts to be included in the build.",
"type": "array",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export abstract class AngularCompilation {
compilerOptions: ng.CompilerOptions;
referencedFiles: readonly string[];
externalStylesheets?: ReadonlyMap<string, string>;
templateUpdates?: ReadonlyMap<string, string>;
}>;

abstract emitAffectedFiles(): Iterable<EmitFileResult> | Promise<Iterable<EmitFileResult>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import type ng from '@angular/compiler-cli';
import assert from 'node:assert';
import { relative } from 'node:path';
import ts from 'typescript';
import { profileAsync, profileSync } from '../../esbuild/profiling';
import {
Expand Down Expand Up @@ -47,6 +48,7 @@ export class AotCompilation extends AngularCompilation {
compilerOptions: ng.CompilerOptions;
referencedFiles: readonly string[];
externalStylesheets?: ReadonlyMap<string, string>;
templateUpdates?: ReadonlyMap<string, string>;
}> {
// Dynamically load the Angular compiler CLI package
const { NgtscProgram, OptimizeFor } = await AngularCompilation.loadCompilerCli();
Expand Down Expand Up @@ -91,6 +93,40 @@ export class AotCompilation extends AngularCompilation {
);

await profileAsync('NG_ANALYZE_PROGRAM', () => angularCompiler.analyzeAsync());

let templateUpdates;
if (
compilerOptions['_enableHmr'] &&
hostOptions.modifiedFiles &&
hasOnlyTemplates(hostOptions.modifiedFiles)
) {
const componentNodes = [...hostOptions.modifiedFiles].flatMap((file) => [
...angularCompiler.getComponentsWithTemplateFile(file),
]);

for (const node of componentNodes) {
if (!ts.isClassDeclaration(node)) {
continue;
}
const componentFilename = node.getSourceFile().fileName;
let relativePath = relative(host.getCurrentDirectory(), componentFilename);
if (relativePath.startsWith('..')) {
relativePath = componentFilename;
}
const updateId = encodeURIComponent(
`${host.getCanonicalFileName(relativePath)}@${node.name?.text}`,
);
const updateText = angularCompiler.emitHmrUpdateModule(node);
if (updateText === null) {
// Build is needed if a template cannot be updated
templateUpdates = undefined;
break;
}
templateUpdates ??= new Map<string, string>();
templateUpdates.set(updateId, updateText);
}
}

const affectedFiles = profileSync('NG_FIND_AFFECTED', () =>
findAffectedFiles(typeScriptProgram, angularCompiler, usingBuildInfo),
);
Expand Down Expand Up @@ -131,6 +167,7 @@ export class AotCompilation extends AngularCompilation {
compilerOptions,
referencedFiles,
externalStylesheets: hostOptions.externalStylesheets,
templateUpdates,
};
}

Expand Down Expand Up @@ -385,3 +422,16 @@ function findAffectedFiles(

return affectedFiles;
}

function hasOnlyTemplates(modifiedFiles: Set<string>): boolean {
for (const file of modifiedFiles) {
const lowerFile = file.toLowerCase();
if (lowerFile.endsWith('.html') || lowerFile.endsWith('.svg')) {
continue;
}

return false;
}

return true;
}
Loading