From 4c9d72c659d912bd9ef4590a2e88340932a96868 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Thu, 16 Dec 2021 13:15:58 +0100 Subject: [PATCH 01/17] fix(@angular/cli): remove extra space in `Unable to find compatible package` during `ng add` (cherry picked from commit b7e29237437dcfaa9a745824a15360812f1ade3c) --- packages/angular/cli/commands/add-impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/angular/cli/commands/add-impl.ts b/packages/angular/cli/commands/add-impl.ts index b9a520a315e0..a2cd46602e22 100644 --- a/packages/angular/cli/commands/add-impl.ts +++ b/packages/angular/cli/commands/add-impl.ts @@ -168,7 +168,7 @@ export class AddCommand extends SchematicCommand { } if (!newIdentifier) { - spinner.warn("Unable to find compatible package. Using 'latest' tag."); + spinner.warn("Unable to find compatible package. Using 'latest' tag."); } else { packageIdentifier = newIdentifier; spinner.succeed( From 39c95dabaef921407efcd0cec221f2eb6be33632 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Fri, 17 Dec 2021 11:02:58 +0100 Subject: [PATCH 02/17] refactor(@angular-devkit/build-angular): ability to perform DCE but retain symbol names Previously, we enabled the `keepNames` esbuild when mangling was disabled, this caused dead code to be retained because of the transformations that esbuild did to the input. Input ```js class foo {} ``` Output ```js var l = Object.defineProperty, a = (s, c) => l(s, "name", { value: c, configurable: !0 }); class foo {} a(foo, "foo"); ``` Previously we enabled the `keepNames` esbuild option when mangling was disabled, which is actually not needed to retain the name of symbols but is needed for SSR because Domino relies on the `name` property on functions and classes. Closes #22354 (cherry picked from commit 2c9a33dddb38694b6940ec6981c49904de1ab636) --- .../src/webpack/configs/common.ts | 3 +- .../plugins/javascript-optimizer-plugin.ts | 29 ++++-- .../plugins/javascript-optimizer-worker.ts | 96 +++++++++++-------- 3 files changed, 79 insertions(+), 49 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts index 3d24edec28e9..d255acb4ab92 100644 --- a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts +++ b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts @@ -277,7 +277,8 @@ export async function getCommonConfig(wco: WebpackConfigOptions): Promise = {}) {} + constructor(public options: JavaScriptOptimizerOptions) {} apply(compiler: Compiler) { const { OriginalSource, SourceMapSource } = compiler.webpack.sources; @@ -142,22 +152,25 @@ export class JavaScriptOptimizerPlugin { } } - let target = 2017; + let target: OptimizeRequestOptions['target'] = 2017; if (this.options.target) { if (this.options.target <= ScriptTarget.ES5) { target = 5; } else if (this.options.target < ScriptTarget.ESNext) { - target = Number(ScriptTarget[this.options.target].slice(2)); + target = Number( + ScriptTarget[this.options.target].slice(2), + ) as OptimizeRequestOptions['target']; } else { target = 2020; } } // Setup the options used by all worker tasks - const optimizeOptions = { + const optimizeOptions: OptimizeRequestOptions = { sourcemap: this.options.sourcemap, define, keepNames: this.options.keepNames, + keepIdentifierNames: this.options.keepIdentifierNames, target, removeLicenses: this.options.removeLicenses, advanced: this.options.advanced, diff --git a/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-worker.ts b/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-worker.ts index fd5dc266ba7e..9e520ea02efb 100644 --- a/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-worker.ts +++ b/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-worker.ts @@ -11,6 +11,52 @@ import type { TransformFailure, TransformResult } from 'esbuild'; import { minify } from 'terser'; import { EsbuildExecutor } from './esbuild-executor'; +/** + * The options to use when optimizing. + */ +export interface OptimizeRequestOptions { + /** + * Controls advanced optimizations. + * Currently these are only terser related: + * * terser compress passes are set to 2 + * * terser pure_getters option is enabled + */ + advanced?: boolean; + /** + * Specifies the string tokens that should be replaced with a defined value. + */ + define?: Record; + /** + * Controls whether class, function, and variable names should be left intact + * throughout the output code. + */ + keepIdentifierNames: boolean; + + /** + * Controls whether to retain the original name of classes and functions. + */ + keepNames: boolean; + /** + * Controls whether license text is removed from the output code. + * Within the CLI, this option is linked to the license extraction functionality. + */ + removeLicenses?: boolean; + /** + * Controls whether source maps should be generated. + */ + sourcemap?: boolean; + /** + * Specifies the target ECMAScript version for the output code. + */ + target: 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020; + /** + * Controls whether esbuild should only use the WASM-variant instead of trying to + * use the native variant. Some platforms may not support the native-variant and + * this option allows one support test to be conducted prior to all the workers starting. + */ + alwaysUseWasm: boolean; +} + /** * A request to optimize JavaScript using the supplied options. */ @@ -18,43 +64,7 @@ interface OptimizeRequest { /** * The options to use when optimizing. */ - options: { - /** - * Controls advanced optimizations. - * Currently these are only terser related: - * * terser compress passes are set to 2 - * * terser pure_getters option is enabled - */ - advanced: boolean; - /** - * Specifies the string tokens that should be replaced with a defined value. - */ - define?: Record; - /** - * Controls whether class, function, and variable names should be left intact - * throughout the output code. - */ - keepNames: boolean; - /** - * Controls whether license text is removed from the output code. - * Within the CLI, this option is linked to the license extraction functionality. - */ - removeLicenses: boolean; - /** - * Controls whether source maps should be generated. - */ - sourcemap: boolean; - /** - * Specifies the target ECMAScript version for the output code. - */ - target: 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020; - /** - * Controls whether esbuild should only use the WASM-variant instead of trying to - * use the native variant. Some platforms may not support the native-variant and - * this option allows one support test to be conducted prior to all the workers starting. - */ - alwaysUseWasm: boolean; - }; + options: OptimizeRequestOptions; /** * The JavaScript asset to optimize. @@ -142,7 +152,7 @@ async function optimizeWithEsbuild( let result: TransformResult; try { result = await esbuild.transform(content, { - minifyIdentifiers: !options.keepNames, + minifyIdentifiers: !options.keepIdentifierNames, minifySyntax: true, // NOTE: Disabling whitespace ensures unused pure annotations are kept minifyWhitespace: false, @@ -151,6 +161,10 @@ async function optimizeWithEsbuild( sourcefile: name, sourcemap: options.sourcemap && 'external', define: options.define, + // This option should always be disabled for browser builds as we don't rely on `.name` + // and causes deadcode to be retained which makes `NG_BUILD_MANGLE` unusable to investigate tree-shaking issues. + // We enable `keepNames` only for server builds as Domino relies on `.name`. + // Once we no longer rely on Domino for SSR we should be able to remove this. keepNames: options.keepNames, target: `es${options.target}`, }); @@ -193,9 +207,9 @@ async function optimizeWithEsbuild( async function optimizeWithTerser( name: string, code: string, - sourcemaps: boolean, + sourcemaps: boolean | undefined, target: OptimizeRequest['options']['target'], - advanced: boolean, + advanced: boolean | undefined, ): Promise<{ code: string; map?: object }> { const result = await minify( { [name]: code }, @@ -207,6 +221,8 @@ async function optimizeWithTerser( ecma: target, // esbuild in the first pass is used to minify identifiers instead of mangle here mangle: false, + // esbuild in the first pass is used to minify function names + keep_fnames: true, format: { // ASCII output is enabled here as well to prevent terser from converting back to UTF-8 ascii_only: true, From 9b07191b1ccdcd2a6bb17686471acddd5862dcf5 Mon Sep 17 00:00:00 2001 From: Zoltan Lehoczky Date: Mon, 3 Jan 2022 13:10:01 +0100 Subject: [PATCH 03/17] fix(@schematics/angular): set `skipTest` flag for resolvers when using ng new --skip-tests (cherry picked from commit aadfc791524ff2bf6d040f288e7a2cca8f49b9cc) --- .../schematics/angular/application/index.ts | 25 +++++++++++++------ .../angular/application/index_spec.ts | 18 +++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/packages/schematics/angular/application/index.ts b/packages/schematics/angular/application/index.ts index 151d10518cca..b78dab4d8b3d 100644 --- a/packages/schematics/angular/application/index.ts +++ b/packages/schematics/angular/application/index.ts @@ -92,14 +92,23 @@ function addAppToWorkspaceFile( } if (options.skipTests || options.minimal) { - ['class', 'component', 'directive', 'guard', 'interceptor', 'pipe', 'service'].forEach( - (type) => { - if (!(`@schematics/angular:${type}` in schematics)) { - schematics[`@schematics/angular:${type}`] = {}; - } - (schematics[`@schematics/angular:${type}`] as JsonObject).skipTests = true; - }, - ); + const schematicsWithTests = [ + 'class', + 'component', + 'directive', + 'guard', + 'interceptor', + 'pipe', + 'resolver', + 'service', + ]; + + schematicsWithTests.forEach((type) => { + if (!(`@schematics/angular:${type}` in schematics)) { + schematics[`@schematics/angular:${type}`] = {}; + } + (schematics[`@schematics/angular:${type}`] as JsonObject).skipTests = true; + }); } if (options.strict) { diff --git a/packages/schematics/angular/application/index_spec.ts b/packages/schematics/angular/application/index_spec.ts index a372512bb262..3c9e090c80ff 100644 --- a/packages/schematics/angular/application/index_spec.ts +++ b/packages/schematics/angular/application/index_spec.ts @@ -179,6 +179,24 @@ describe('Application Schematic', () => { expect(karmaConf).toContain(`dir: require('path').join(__dirname, '../../coverage/foo')`); }); + it('should set the skipTests flag for other schematics when using --skipTests=true', async () => { + const options: ApplicationOptions = { ...defaultOptions, skipTests: true }; + const tree = await schematicRunner + .runSchematicAsync('application', options, workspaceTree) + .toPromise(); + const config = JSON.parse(tree.readContent('/angular.json')); + const schematics = config.projects.foo.schematics; + + expect(schematics['@schematics/angular:class']).toEqual({ skipTests: true }); + expect(schematics['@schematics/angular:component']).toEqual({ skipTests: true }); + expect(schematics['@schematics/angular:directive']).toEqual({ skipTests: true }); + expect(schematics['@schematics/angular:guard']).toEqual({ skipTests: true }); + expect(schematics['@schematics/angular:interceptor']).toEqual({ skipTests: true }); + expect(schematics['@schematics/angular:pipe']).toEqual({ skipTests: true }); + expect(schematics['@schematics/angular:resolver']).toEqual({ skipTests: true }); + expect(schematics['@schematics/angular:service']).toEqual({ skipTests: true }); + }); + it('minimal=true should not create e2e and test targets', async () => { const options = { ...defaultOptions, minimal: true }; const tree = await schematicRunner From 3f54e8fe94a36f50f017570c6c33c8d152fd616b Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Tue, 21 Dec 2021 13:45:03 -0800 Subject: [PATCH 04/17] build: perform package.json substitutions in bazel build (cherry picked from commit 4b5c52b0d8227da60920f5f1e2f6921e4710a03f) --- .bazelrc | 2 + .prettierignore | 3 +- BUILD.bazel | 16 ++++ WORKSPACE | 26 ++++++ packages/angular/cli/BUILD.bazel | 9 +- packages/angular/pwa/BUILD.bazel | 5 +- packages/angular_devkit/architect/BUILD.bazel | 4 +- .../angular_devkit/architect_cli/BUILD.bazel | 5 +- packages/angular_devkit/benchmark/BUILD.bazel | 4 +- .../angular_devkit/build_angular/BUILD.bazel | 6 +- .../build_optimizer/BUILD.bazel | 1 - .../angular_devkit/build_webpack/BUILD.bazel | 4 +- packages/angular_devkit/core/BUILD.bazel | 1 - .../angular_devkit/schematics/BUILD.bazel | 4 +- .../angular_devkit/schematics_cli/BUILD.bazel | 5 +- packages/ngtools/webpack/BUILD.bazel | 1 - packages/schematics/angular/BUILD.bazel | 5 +- scripts/build-bazel.ts | 9 +- tools/BUILD.bazel | 4 + tools/defaults.bzl | 75 +++++++++++++++- tools/link_package_json_to_tarballs.bzl | 87 +++++++++++++++++++ tools/package_json_release_filter.jq | 32 +++++++ tools/test/BUILD.bazel | 32 +++++++ tools/test/expected_package.json | 42 +++++++++ tools/test/project_package.json | 39 +++++++++ tools/test/root_package.json | 37 ++++++++ 26 files changed, 432 insertions(+), 26 deletions(-) create mode 100644 tools/link_package_json_to_tarballs.bzl create mode 100644 tools/package_json_release_filter.jq create mode 100644 tools/test/BUILD.bazel create mode 100644 tools/test/expected_package.json create mode 100644 tools/test/project_package.json create mode 100644 tools/test/root_package.json diff --git a/.bazelrc b/.bazelrc index b9f08a6e1942..3a243dcd8781 100644 --- a/.bazelrc +++ b/.bazelrc @@ -74,6 +74,8 @@ build:release --stamp build:snapshot --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=snapshot" build:snapshot --stamp +build:local --//:enable_package_json_tar_deps + ############################### # Output # ############################### diff --git a/.prettierignore b/.prettierignore index 8c38d582deaa..438c9f4edca4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,4 +12,5 @@ .yarn/ dist/ third_party/ -/tests/legacy-cli/e2e/assets/9.0-project/ \ No newline at end of file +/tests/legacy-cli/e2e/assets/9.0-project/ +/tools/test/*.json \ No newline at end of file diff --git a/BUILD.bazel b/BUILD.bazel index ce0a61d81f62..d36206cd6cb9 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -2,6 +2,8 @@ # # Use of this source code is governed by an MIT-style license that can be # found in the LICENSE file at https://angular.io/license +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") + package(default_visibility = ["//visibility:public"]) licenses(["notice"]) @@ -11,6 +13,7 @@ exports_files([ "tsconfig.json", # @external "tsconfig-test.json", # @external "tsconfig-build.json", # @external + "package.json", ]) # Detect if the build is running under --stamp @@ -18,3 +21,16 @@ config_setting( name = "stamp", values = {"stamp": "true"}, ) + +# If set will replace dependency versions with tarballs for packages in this repo +bool_flag( + name = "enable_package_json_tar_deps", + build_setting_default = False, +) + +config_setting( + name = "package_json_use_tar_deps", + flag_values = { + ":enable_package_json_tar_deps": "true", + }, +) diff --git a/WORKSPACE b/WORKSPACE index a98d2c045686..2f089fde7c90 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -5,6 +5,15 @@ workspace( load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "bazel_skylib", + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], +) + http_archive( name = "build_bazel_rules_nodejs", sha256 = "cfc289523cf1594598215901154a6c2515e8bf3671fd708264a6f6aefe02bf39", @@ -17,6 +26,10 @@ http_archive( urls = ["https://github.com/bazelbuild/rules_pkg/releases/download/0.5.1/rules_pkg-0.5.1.tar.gz"], ) +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") + +bazel_skylib_workspace() + load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") rules_pkg_dependencies() @@ -50,3 +63,16 @@ yarn_install( package_json = "//:package.json", yarn_lock = "//:yarn.lock", ) + +http_archive( + name = "aspect_bazel_lib", + sha256 = "534c9c61b72c257c95302d544984fd8ee63953c233292c5b6952ca5b33cd225e", + strip_prefix = "bazel-lib-0.4.2", + url = "https://github.com/aspect-build/bazel-lib/archive/v0.4.2.tar.gz", +) + +load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_jq_toolchains") + +aspect_bazel_lib_dependencies() + +register_jq_toolchains(version = "1.6") diff --git a/packages/angular/cli/BUILD.bazel b/packages/angular/cli/BUILD.bazel index a0c937b35a89..ba4a82bd9839 100644 --- a/packages/angular/cli/BUILD.bazel +++ b/packages/angular/cli/BUILD.bazel @@ -316,7 +316,14 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/architect:package.json", + "//packages/angular_devkit/build_angular:package.json", + "//packages/angular_devkit/build_webpack:package.json", + "//packages/angular_devkit/core:package.json", + "//packages/angular_devkit/schematics:package.json", + "//packages/schematics/angular:package.json", + ], deps = [ ":README.md", ":angular-cli", diff --git a/packages/angular/pwa/BUILD.bazel b/packages/angular/pwa/BUILD.bazel index c86dd005ff3e..37d9e0807fbf 100644 --- a/packages/angular/pwa/BUILD.bazel +++ b/packages/angular/pwa/BUILD.bazel @@ -76,7 +76,10 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/schematics:package.json", + "//packages/schematics/angular:package.json", + ], deps = [ ":README.md", ":license", diff --git a/packages/angular_devkit/architect/BUILD.bazel b/packages/angular_devkit/architect/BUILD.bazel index b63c471bbf5a..d59a08ff91fc 100644 --- a/packages/angular_devkit/architect/BUILD.bazel +++ b/packages/angular_devkit/architect/BUILD.bazel @@ -99,7 +99,9 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/core:package.json", + ], deps = [ ":README.md", ":architect", diff --git a/packages/angular_devkit/architect_cli/BUILD.bazel b/packages/angular_devkit/architect_cli/BUILD.bazel index 762d0c34d893..19505a0fcb05 100644 --- a/packages/angular_devkit/architect_cli/BUILD.bazel +++ b/packages/angular_devkit/architect_cli/BUILD.bazel @@ -37,7 +37,10 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/architect:package.json", + "//packages/angular_devkit/core:package.json", + ], deps = [ ":README.md", ":architect_cli", diff --git a/packages/angular_devkit/benchmark/BUILD.bazel b/packages/angular_devkit/benchmark/BUILD.bazel index 34686c5575cc..5357a92bbeb3 100644 --- a/packages/angular_devkit/benchmark/BUILD.bazel +++ b/packages/angular_devkit/benchmark/BUILD.bazel @@ -78,7 +78,9 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/core:package.json", + ], deps = [ "src/test/exit-code-one.js", "src/test/fibonacci.js", diff --git a/packages/angular_devkit/build_angular/BUILD.bazel b/packages/angular_devkit/build_angular/BUILD.bazel index dd8a1beb977a..8e8f35af9d28 100644 --- a/packages/angular_devkit/build_angular/BUILD.bazel +++ b/packages/angular_devkit/build_angular/BUILD.bazel @@ -221,7 +221,11 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/architect:package.json", + "//packages/angular_devkit/build_webpack:package.json", + "//packages/angular_devkit/core:package.json", + ], deps = [ ":README.md", ":build_angular", diff --git a/packages/angular_devkit/build_optimizer/BUILD.bazel b/packages/angular_devkit/build_optimizer/BUILD.bazel index cb7c5521ca65..eafe852cb896 100644 --- a/packages/angular_devkit/build_optimizer/BUILD.bazel +++ b/packages/angular_devkit/build_optimizer/BUILD.bazel @@ -68,7 +68,6 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], deps = [ ":README.md", ":build_optimizer", diff --git a/packages/angular_devkit/build_webpack/BUILD.bazel b/packages/angular_devkit/build_webpack/BUILD.bazel index 1d45f47ef9bb..c6f9e4bd29d0 100644 --- a/packages/angular_devkit/build_webpack/BUILD.bazel +++ b/packages/angular_devkit/build_webpack/BUILD.bazel @@ -109,7 +109,9 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/architect:package.json", + ], deps = [ ":README.md", ":build_webpack", diff --git a/packages/angular_devkit/core/BUILD.bazel b/packages/angular_devkit/core/BUILD.bazel index 3b62ad837e67..abf0abe9ed06 100644 --- a/packages/angular_devkit/core/BUILD.bazel +++ b/packages/angular_devkit/core/BUILD.bazel @@ -85,7 +85,6 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], deps = [ ":README.md", ":core", diff --git a/packages/angular_devkit/schematics/BUILD.bazel b/packages/angular_devkit/schematics/BUILD.bazel index b46d30160dd8..0cccea0629fc 100644 --- a/packages/angular_devkit/schematics/BUILD.bazel +++ b/packages/angular_devkit/schematics/BUILD.bazel @@ -73,7 +73,9 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/core:package.json", + ], deps = [ ":README.md", ":collection-schema.json", diff --git a/packages/angular_devkit/schematics_cli/BUILD.bazel b/packages/angular_devkit/schematics_cli/BUILD.bazel index 1ffe0cb979a1..57ac54222695 100644 --- a/packages/angular_devkit/schematics_cli/BUILD.bazel +++ b/packages/angular_devkit/schematics_cli/BUILD.bazel @@ -98,7 +98,10 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/schematics:package.json", + "//packages/angular_devkit/core:package.json", + ], deps = [ ":README.md", ":license", diff --git a/packages/ngtools/webpack/BUILD.bazel b/packages/ngtools/webpack/BUILD.bazel index 5b627642a2cc..5031fd5b268a 100644 --- a/packages/ngtools/webpack/BUILD.bazel +++ b/packages/ngtools/webpack/BUILD.bazel @@ -76,7 +76,6 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], deps = [ ":README.md", ":license", diff --git a/packages/schematics/angular/BUILD.bazel b/packages/schematics/angular/BUILD.bazel index 6f21b54e5021..c83b9ceb3bd3 100644 --- a/packages/schematics/angular/BUILD.bazel +++ b/packages/schematics/angular/BUILD.bazel @@ -140,7 +140,10 @@ genrule( pkg_npm( name = "npm_package", - srcs = [":package.json"], + pkg_deps = [ + "//packages/angular_devkit/schematics:package.json", + "//packages/angular_devkit/core:package.json", + ], deps = [ "library/library-long.md", ":README.md", diff --git a/scripts/build-bazel.ts b/scripts/build-bazel.ts index 8a62137bdad1..beb35eec4514 100644 --- a/scripts/build-bazel.ts +++ b/scripts/build-bazel.ts @@ -113,13 +113,6 @@ async function _build(logger: logging.Logger, mode: BuildMode): Promise $@ + """.format( + pkg_name = pkg_dep_name, + abs_path_sandbox = abs_path_sandbox, + abs_path_nosandbox = abs_path_nosandbox, + ), + outs = [pkg_dep_filter], + ) + filter_files.append(pkg_dep_filter) + + # Combine all of the filter files into a single filter by joining with | + filter = "%s.filter" % name + native.genrule( + name = "%s_filter" % name, + srcs = filter_files, + cmd = "cat $(SRCS) | sed '$$!s#$$# |#' > $@", + outs = [filter], + ) + + # Generate final package.json with tar substitutions using the above filter + jq( + name = name, + srcs = [src], + filter_file = filter, + out = out, + ) diff --git a/tools/package_json_release_filter.jq b/tools/package_json_release_filter.jq new file mode 100644 index 000000000000..e025697e1fc3 --- /dev/null +++ b/tools/package_json_release_filter.jq @@ -0,0 +1,32 @@ +# Copyright Google Inc. All Rights Reserved. +# +# Use of this source code is governed by an MIT-style license that can be +# found in the LICENSE file at https://angular.io/license +# +# This filter combines a subproject package.json with the root package.json +# and performs substitutions to prepare it for release. It should be called +# with the --slurp argument and be passed the root pacakge.json followed by +# the subproject package.json. +# +# See jq docs for filter syntax: https://stedolan.github.io/jq/manual/. + +.[0] as $root +| .[1] as $proj + +# Get the fields from root package.json that should override the project +# package.json, i.e., every field except the following +| ($root + | del(.bin, .description, .dependencies, .name, .main, .peerDependencies, .optionalDependencies, .typings, .version, .private, .workspaces, .resolutions, .scripts, .["ng-update"]) +) as $root_overrides + +# Use the project package.json as a base and override other fields from root +| $proj + $root_overrides + +# Combine keywords from both +| .keywords = ($root.keywords + $proj.keywords | unique) + +# Remove devDependencies +| del(.devDependencies) + +# Add engines ++ {"engines": {"node": "^12.20.0 || ^14.15.0 || >=16.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0"}} \ No newline at end of file diff --git a/tools/test/BUILD.bazel b/tools/test/BUILD.bazel new file mode 100644 index 000000000000..2e651ae3e654 --- /dev/null +++ b/tools/test/BUILD.bazel @@ -0,0 +1,32 @@ +load("@bazel_skylib//rules:diff_test.bzl", "diff_test") +load("@aspect_bazel_lib//lib:jq.bzl", "jq") + +jq( + name = "final_package_json", + # This jq filter relies on the order of the inputs + # buildifier: do not sort + srcs = [ + "root_package.json", + "project_package.json", + ], + args = [ + "--slurp", + ], + filter_file = "//tools:package_json_release_filter.jq", +) + +# jq outputs CR on windows https://github.com/stedolan/jq/issues/92 +# strip the CRs to do a correct comparison on all platforms +genrule( + name = "final_package_json_cr_stripped", + srcs = [":final_package_json"], + outs = ["final_package_json_cr_stripped.json"], + cmd = "cat $(execpath :final_package_json) | sed \"s#\\r##\" > $@", +) + +# Test correctness of the filter that prepares each project's package.json file for release +diff_test( + name = "package_json_filter_test", + file1 = "expected_package.json", + file2 = ":final_package_json_cr_stripped", +) diff --git a/tools/test/expected_package.json b/tools/test/expected_package.json new file mode 100644 index 000000000000..b0df6c051c75 --- /dev/null +++ b/tools/test/expected_package.json @@ -0,0 +1,42 @@ +{ + "name": "project", + "version": "0.0.0-SNAPSHOT", + "description": "Project package.json", + "main": "project/index.js", + "bin": { + "projectfoo": "./bin/project-foo.js" + }, + "keywords": [ + "a", + "b", + "c" + ], + "scripts": { + "build": "node project-build-script" + }, + "repository": { + "type": "git", + "url": "https://github.com/angular/angular-cli.git" + }, + "author": "Angular Authors", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/angular-cli/issues" + }, + "homepage": "https://github.com/angular/angular-cli", + "dependencies": { + "@project/foo": "1.0.0", + "@project/bar": "2.0.0" + }, + "ng-update": { + "migrations": "@project/migration-collection.json", + "packageGroup": { + "@project/abc": "0.0.0" + } + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } +} diff --git a/tools/test/project_package.json b/tools/test/project_package.json new file mode 100644 index 000000000000..894c9f4cf3f2 --- /dev/null +++ b/tools/test/project_package.json @@ -0,0 +1,39 @@ +{ + "name": "project", + "version": "0.0.0-SNAPSHOT", + "description": "Project package.json", + "main": "project/index.js", + "bin": { + "projectfoo": "./bin/project-foo.js" + }, + "keywords": [ + "b", + "c" + ], + "scripts": { + "build": "node project-build-script" + }, + "repository": { + "type": "git", + "url": "https://github.com/angular/angular-cli.git" + }, + "author": "Angular Authors", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/angular-cli/issues" + }, + "homepage": "https://github.com/angular/angular-cli", + "dependencies": { + "@project/foo": "1.0.0", + "@project/bar": "2.0.0" + }, + "devDependencies": { + "@project/devdep": "1.2.3" + }, + "ng-update": { + "migrations": "@project/migration-collection.json", + "packageGroup": { + "@project/abc": "0.0.0" + } + } +} diff --git a/tools/test/root_package.json b/tools/test/root_package.json new file mode 100644 index 000000000000..e0b263aef042 --- /dev/null +++ b/tools/test/root_package.json @@ -0,0 +1,37 @@ +{ + "name": "root", + "version": "1.0.0-next.1", + "private": true, + "description": "Root package.json", + "bin": { + "root-foo": "./bin/root-foo.js", + "root-bar": "./bin/root-bar.js" + }, + "keywords": [ + "a", + "b" + ], + "scripts": { + "build": "node root-build-script" + }, + "repository": { + "type": "git", + "url": "https://github.com/angular/angular-cli.git" + }, + "author": "Angular Authors", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/angular-cli/issues" + }, + "homepage": "https://github.com/angular/angular-cli", + "workspaces": { + "packages": ["packages/root/foo/*", "packages/root/bar/*"] + }, + "resolutions": { + "root/foo/bar": "1.0.0" + }, + "devDependencies": { + "@root/foo": "1.0.0", + "@root/bar": "2.0.0" + } +} From 0c03a2f3cfd001aca450919fb9907d14fc02e8bf Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Mon, 10 Jan 2022 14:02:49 +0100 Subject: [PATCH 05/17] docs: remove old information from debugging section `universal-analytics` has been removed via https://github.com/angular/angular-cli/commit/dbce2a3f28673991db1059c902cae326c725518a which makes `DEBUG=universal-analytics` unusable. (cherry picked from commit 17c78a53bac9027026d224352a56b16c7a918456) --- docs/design/analytics.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/design/analytics.md b/docs/design/analytics.md index 00f5c9d91c15..a3a2785eeba5 100644 --- a/docs/design/analytics.md +++ b/docs/design/analytics.md @@ -98,9 +98,6 @@ Node version is our App ID, but a dimension is also used to get the numeric MAJO # Debugging -Using `DEBUG=universal-analytics` will report all calls to the universal-analytics library, -including queuing events and sending them to the server. - Using `DEBUG=ng:analytics` will report additional information regarding initialization and decisions made during the usage analytics process, e.g. if the user has analytics disabled. From de68daa5581dd1f257382da16704d442b540ec41 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Thu, 6 Jan 2022 11:55:45 +0100 Subject: [PATCH 06/17] fix(@angular-devkit/build-angular): enable `:where` CSS pseudo-class Currently when using the `:where` CSS pseudo-class in Angular CLI projects, a warning will be emitted, as `:where` could not be interpreted. Updating to the latest version of `critters` fixes this issue. (cherry picked from commit 9a9af20400a4be53f6c62187401cc9bf2fadc57e) --- package.json | 2 +- .../angular_devkit/build_angular/package.json | 2 +- yarn.lock | 31 ++++++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6c1e713685c4..04a647821ad0 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "conventional-commits-parser": "^3.0.0", "copy-webpack-plugin": "10.0.0", "core-js": "3.19.3", - "critters": "0.0.15", + "critters": "0.0.16", "css-loader": "6.5.1", "debug": "^4.1.1", "esbuild": "0.14.2", diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index 95f4e65940c0..f502c98563a7 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -29,7 +29,7 @@ "circular-dependency-plugin": "5.2.2", "copy-webpack-plugin": "10.0.0", "core-js": "3.19.3", - "critters": "0.0.15", + "critters": "0.0.16", "css-loader": "6.5.1", "esbuild-wasm": "0.14.2", "glob": "7.2.0", diff --git a/yarn.lock b/yarn.lock index 3b08ea88b06f..2d427652ab62 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4098,6 +4098,18 @@ critters@0.0.15: postcss "^8.3.7" pretty-bytes "^5.3.0" +critters@0.0.16: + version "0.0.16" + resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93" + integrity sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A== + dependencies: + chalk "^4.1.0" + css-select "^4.2.0" + parse5 "^6.0.1" + parse5-htmlparser2-tree-adapter "^6.0.1" + postcss "^8.3.7" + pretty-bytes "^5.3.0" + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4168,7 +4180,18 @@ css-select@^4.1.3: domutils "^2.6.0" nth-check "^2.0.0" -css-what@^5.0.0: +css-select@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" + integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== + dependencies: + boolbase "^1.0.0" + css-what "^5.1.0" + domhandler "^4.3.0" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^5.0.0, css-what@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== @@ -4548,7 +4571,7 @@ domexception@^1.0.1: dependencies: webidl-conversions "^4.0.2" -domhandler@^4.2.0: +domhandler@^4.2.0, domhandler@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== @@ -4565,7 +4588,7 @@ dompurify@^2.2.6: resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.4.tgz#1cf5cf0105ccb4debdf6db162525bd41e6ddacc6" integrity sha512-6BVcgOAVFXjI0JTjEvZy901Rghm+7fDQOrNIcxB4+gdhj6Kwp6T9VBhBY/AbagKHJocRkDYGd6wvI+p4/10xtQ== -domutils@^2.6.0: +domutils@^2.6.0, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -7994,7 +8017,7 @@ npmlog@^6.0.0: gauge "^4.0.0" set-blocking "^2.0.0" -nth-check@^2.0.0: +nth-check@^2.0.0, nth-check@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== From 6046e06b926af29f89c605504f5356ec553c6390 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Mon, 10 Jan 2022 12:57:34 +0100 Subject: [PATCH 07/17] fix(@angular-devkit/build-angular): correctly resolve `core-js/proposals/reflect-metadata` Closes #22443 (cherry picked from commit a5e375ca93a93dd887d7fde34686ec9019619981) --- .../angular_devkit/build_angular/src/webpack/configs/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts index d255acb4ab92..b82b1eb9930b 100644 --- a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts +++ b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts @@ -125,7 +125,7 @@ export async function getCommonConfig(wco: WebpackConfigOptions): Promise Date: Mon, 10 Jan 2022 12:51:21 +0100 Subject: [PATCH 08/17] fix(@angular-devkit/build-angular): use `contenthash` instead of `chunkhash` for chunks See https://github.com/waysact/webpack-subresource-integrity/tree/main/webpack-subresource-integrity#caching and https://github.com/waysact/webpack-subresource-integrity/issues/162 for more information about this. Closes #22439 (cherry picked from commit 11f817adae4f06d8b80a9d74534468f6e3c2d2c5) --- .../angular_devkit/build_angular/src/webpack/utils/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts b/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts index 4944cb0d0c4d..ab0f78250a5d 100644 --- a/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts +++ b/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts @@ -32,13 +32,13 @@ export function getOutputHashFormat(option: string, length = 20): HashFormat { none: { chunk: '', extract: '', file: '', script: '' }, media: { chunk: '', extract: '', file: `.[hash:${length}]`, script: '' }, bundles: { - chunk: `.[chunkhash:${length}]`, + chunk: `.[contenthash:${length}]`, extract: `.[contenthash:${length}]`, file: '', script: `.[hash:${length}]`, }, all: { - chunk: `.[chunkhash:${length}]`, + chunk: `.[contenthash:${length}]`, extract: `.[contenthash:${length}]`, file: `.[hash:${length}]`, script: `.[hash:${length}]`, From 5b39e0eca6e8a3825f66ad6cd1818e551bf98f08 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Wed, 12 Jan 2022 08:03:14 +0100 Subject: [PATCH 09/17] fix(@angular-devkit/build-angular): automatically purge stale build cache entries With every build-angular release, previously created cache entries get stale and are no longer used. This causes the cache to keep growing as older files are not purged. With this change we automatically purge entries that have been created with older version of build-angular and can no longer be used with the current installed version. Closes #22323 (cherry picked from commit 6d2087b8f8332d742bc1140b7c4e490f5cc57d08) --- .../build_angular/src/babel/webpack-loader.ts | 3 +- .../src/builders/browser/index.ts | 4 ++ .../src/builders/dev-server/index.ts | 4 ++ .../src/builders/extract-i18n/index.ts | 4 ++ .../build_angular/src/builders/karma/index.ts | 4 ++ .../src/builders/ng-packagr/index.ts | 4 ++ .../src/builders/server/index.ts | 4 ++ .../src/utils/index-file/inline-fonts.ts | 5 +- .../src/utils/normalize-cache.ts | 12 ++++- .../src/utils/package-version.ts | 9 ++++ .../build_angular/src/utils/purge-cache.ts | 53 +++++++++++++++++++ .../src/webpack/utils/helpers.ts | 5 +- .../e2e/tests/build/disk-cache-purge.ts | 27 ++++++++++ 13 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 packages/angular_devkit/build_angular/src/utils/package-version.ts create mode 100644 packages/angular_devkit/build_angular/src/utils/purge-cache.ts create mode 100644 tests/legacy-cli/e2e/tests/build/disk-cache-purge.ts diff --git a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts index 958b0cf7f99b..3653ab20c4fc 100644 --- a/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts +++ b/packages/angular_devkit/build_angular/src/babel/webpack-loader.ts @@ -10,6 +10,7 @@ import remapping from '@ampproject/remapping'; import { custom } from 'babel-loader'; import { ScriptTarget } from 'typescript'; import { loadEsmModule } from '../utils/load-esm'; +import { VERSION } from '../utils/package-version'; import { ApplicationPresetOptions, I18nPluginCreators } from './presets/application'; interface AngularCustomOptions extends Omit { @@ -196,7 +197,7 @@ export default custom(() => { ...baseOptions, ...rawOptions, cacheIdentifier: JSON.stringify({ - buildAngular: require('../../package.json').version, + buildAngular: VERSION, customOptions, baseOptions, rawOptions, diff --git a/packages/angular_devkit/build_angular/src/builders/browser/index.ts b/packages/angular_devkit/build_angular/src/builders/browser/index.ts index 255c07b47f25..4236bb37d166 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/index.ts @@ -39,6 +39,7 @@ import { import { normalizeCacheOptions } from '../../utils/normalize-cache'; import { ensureOutputPaths } from '../../utils/output-paths'; import { generateEntryPoints } from '../../utils/package-chunk-sort'; +import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { augmentAppWithServiceWorker } from '../../utils/service-worker'; import { Spinner } from '../../utils/spinner'; import { getSupportedBrowsers } from '../../utils/supported-browsers'; @@ -157,6 +158,9 @@ export function buildWebpackBrowser( ), ); + // Purge old build disk cache. + await purgeStaleBuildCache(context); + checkInternetExplorerSupport(sysProjectRoot, context.logger); return { diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts index 208c095bac90..5a19d8002ba8 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts @@ -28,6 +28,7 @@ import { IndexHtmlTransform } from '../../utils/index-file/index-html-generator' import { createTranslationLoader } from '../../utils/load-translations'; import { NormalizedCachedOptions, normalizeCacheOptions } from '../../utils/normalize-cache'; import { generateEntryPoints } from '../../utils/package-chunk-sort'; +import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { assertCompatibleAngularVersion } from '../../utils/version'; import { generateI18nBrowserWebpackConfigFromContext, @@ -90,6 +91,9 @@ export function serveWebpackBrowser( throw new Error('The builder requires a target.'); } + // Purge old build disk cache. + await purgeStaleBuildCache(context); + options.port = await checkPort(options.port ?? 4200, options.host || 'localhost'); if (options.hmr) { diff --git a/packages/angular_devkit/build_angular/src/builders/extract-i18n/index.ts b/packages/angular_devkit/build_angular/src/builders/extract-i18n/index.ts index 169763a86767..59ca53297c68 100644 --- a/packages/angular_devkit/build_angular/src/builders/extract-i18n/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/extract-i18n/index.ts @@ -17,6 +17,7 @@ import webpack, { Configuration } from 'webpack'; import { ExecutionTransformer } from '../../transforms'; import { createI18nOptions } from '../../utils/i18n-options'; import { loadEsmModule } from '../../utils/load-esm'; +import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { assertCompatibleAngularVersion } from '../../utils/version'; import { generateBrowserWebpackConfigFromContext } from '../../utils/webpack-browser-config'; import { getCommonConfig } from '../../webpack/configs'; @@ -130,6 +131,9 @@ export async function execute( // Check Angular version. assertCompatibleAngularVersion(context.workspaceRoot); + // Purge old build disk cache. + await purgeStaleBuildCache(context); + const browserTarget = targetFromTargetString(options.browserTarget); const browserOptions = await context.validateOptions( await context.getTargetOptions(browserTarget), diff --git a/packages/angular_devkit/build_angular/src/builders/karma/index.ts b/packages/angular_devkit/build_angular/src/builders/karma/index.ts index 1bcb2a348d53..ae5dcfbff171 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/index.ts @@ -14,6 +14,7 @@ import { Observable, from } from 'rxjs'; import { defaultIfEmpty, switchMap } from 'rxjs/operators'; import { Configuration } from 'webpack'; import { ExecutionTransformer } from '../../transforms'; +import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { assertCompatibleAngularVersion } from '../../utils/version'; import { generateBrowserWebpackConfigFromContext } from '../../utils/webpack-browser-config'; import { getCommonConfig, getStylesConfig } from '../../webpack/configs'; @@ -32,6 +33,9 @@ async function initialize( context: BuilderContext, webpackConfigurationTransformer?: ExecutionTransformer, ): Promise<[typeof import('karma'), Configuration]> { + // Purge old build disk cache. + await purgeStaleBuildCache(context); + const { config } = await generateBrowserWebpackConfigFromContext( // only two properties are missing: // * `outputPath` which is fixed for tests diff --git a/packages/angular_devkit/build_angular/src/builders/ng-packagr/index.ts b/packages/angular_devkit/build_angular/src/builders/ng-packagr/index.ts index 27c379a1582b..0122bce230e4 100644 --- a/packages/angular_devkit/build_angular/src/builders/ng-packagr/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/ng-packagr/index.ts @@ -11,6 +11,7 @@ import { join, resolve } from 'path'; import { Observable, from, of } from 'rxjs'; import { catchError, mapTo, switchMap } from 'rxjs/operators'; import { normalizeCacheOptions } from '../../utils/normalize-cache'; +import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { Schema as NgPackagrBuilderOptions } from './schema'; /** @@ -22,6 +23,9 @@ export function execute( ): Observable { return from( (async () => { + // Purge old build disk cache. + await purgeStaleBuildCache(context); + const root = context.workspaceRoot; const packager = (await import('ng-packagr')).ngPackagr(); diff --git a/packages/angular_devkit/build_angular/src/builders/server/index.ts b/packages/angular_devkit/build_angular/src/builders/server/index.ts index 216050d1d5df..848d9ab1a396 100644 --- a/packages/angular_devkit/build_angular/src/builders/server/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/server/index.ts @@ -19,6 +19,7 @@ import { NormalizedBrowserBuilderSchema, deleteOutputDir } from '../../utils'; import { i18nInlineEmittedFiles } from '../../utils/i18n-inlining'; import { I18nOptions } from '../../utils/i18n-options'; import { ensureOutputPaths } from '../../utils/output-paths'; +import { purgeStaleBuildCache } from '../../utils/purge-cache'; import { assertCompatibleAngularVersion } from '../../utils/version'; import { generateI18nBrowserWebpackConfigFromContext } from '../../utils/webpack-browser-config'; import { getCommonConfig, getStylesConfig } from '../../webpack/configs'; @@ -146,6 +147,9 @@ async function initialize( i18n: I18nOptions; target: ScriptTarget; }> { + // Purge old build disk cache. + await purgeStaleBuildCache(context); + const originalOutputPath = options.outputPath; const { config, i18n, target } = await generateI18nBrowserWebpackConfigFromContext( { diff --git a/packages/angular_devkit/build_angular/src/utils/index-file/inline-fonts.ts b/packages/angular_devkit/build_angular/src/utils/index-file/inline-fonts.ts index 6d2a25263f8b..af7719687883 100644 --- a/packages/angular_devkit/build_angular/src/utils/index-file/inline-fonts.ts +++ b/packages/angular_devkit/build_angular/src/utils/index-file/inline-fonts.ts @@ -13,10 +13,9 @@ import proxyAgent from 'https-proxy-agent'; import { join } from 'path'; import { URL } from 'url'; import { NormalizedCachedOptions } from '../normalize-cache'; +import { VERSION } from '../package-version'; import { htmlRewritingStream } from './html-rewriting-stream'; -const packageVersion = require('../../../package.json').version; - interface FontProviderDetails { preconnectUrl: string; } @@ -156,7 +155,7 @@ export class InlineFontsProcessor { } private async getResponse(url: URL): Promise { - const key = `${packageVersion}|${url}`; + const key = `${VERSION}|${url}`; if (this.cachePath) { const entry = await cacache.get.info(this.cachePath, key); diff --git a/packages/angular_devkit/build_angular/src/utils/normalize-cache.ts b/packages/angular_devkit/build_angular/src/utils/normalize-cache.ts index cf3f9fc46f43..5cc6585e8735 100644 --- a/packages/angular_devkit/build_angular/src/utils/normalize-cache.ts +++ b/packages/angular_devkit/build_angular/src/utils/normalize-cache.ts @@ -7,12 +7,17 @@ */ import { json } from '@angular-devkit/core'; -import { resolve } from 'path'; +import { join, resolve } from 'path'; import { cachingDisabled } from './environment-options'; +import { VERSION } from './package-version'; export interface NormalizedCachedOptions { + /** Whether disk cache is enabled. */ enabled: boolean; + /** Disk cache path. Example: `/.angular/cache/v12.0.0`. */ path: string; + /** Disk cache base path. Example: `/.angular/cache`. */ + basePath: string; } interface CacheMetadata { @@ -49,8 +54,11 @@ export function normalizeCacheOptions( } } + const cacheBasePath = resolve(worspaceRoot, path); + return { enabled: cacheEnabled, - path: resolve(worspaceRoot, path), + basePath: cacheBasePath, + path: join(cacheBasePath, VERSION), }; } diff --git a/packages/angular_devkit/build_angular/src/utils/package-version.ts b/packages/angular_devkit/build_angular/src/utils/package-version.ts new file mode 100644 index 000000000000..4634959bd831 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/utils/package-version.ts @@ -0,0 +1,9 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +export const VERSION: string = require('../../package.json').version; diff --git a/packages/angular_devkit/build_angular/src/utils/purge-cache.ts b/packages/angular_devkit/build_angular/src/utils/purge-cache.ts new file mode 100644 index 000000000000..6f11bbd938be --- /dev/null +++ b/packages/angular_devkit/build_angular/src/utils/purge-cache.ts @@ -0,0 +1,53 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { BuilderContext } from '@angular-devkit/architect'; +import { PathLike, existsSync, promises as fsPromises } from 'fs'; +import { join } from 'path'; +import { normalizeCacheOptions } from './normalize-cache'; + +/** Delete stale cache directories used by previous versions of build-angular. */ +export async function purgeStaleBuildCache(context: BuilderContext): Promise { + const projectName = context.target?.project; + if (!projectName) { + return; + } + + const metadata = await context.getProjectMetadata(projectName); + const { basePath, path, enabled } = normalizeCacheOptions(metadata, context.workspaceRoot); + + if (!enabled || !existsSync(basePath)) { + return; + } + + // The below should be removed and replaced with just `rm` when support for Node.Js 12 is removed. + const { rm, rmdir } = fsPromises as typeof fsPromises & { + rm?: ( + path: PathLike, + options?: { + force?: boolean; + maxRetries?: number; + recursive?: boolean; + retryDelay?: number; + }, + ) => Promise; + }; + + const entriesToDelete = (await fsPromises.readdir(basePath, { withFileTypes: true })) + .filter((d) => join(basePath, d.name) !== path && d.isDirectory()) + .map((d) => { + const subPath = join(basePath, d.name); + try { + return rm + ? rm(subPath, { force: true, recursive: true, maxRetries: 3 }) + : rmdir(subPath, { recursive: true, maxRetries: 3 }); + } catch {} + }); + + await Promise.all(entriesToDelete); +} diff --git a/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts b/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts index ab0f78250a5d..d8a59c72efb9 100644 --- a/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts +++ b/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts @@ -19,6 +19,7 @@ import { ExtraEntryPointClass, } from '../../builders/browser/schema'; import { WebpackConfigOptions } from '../../utils/build-options'; +import { VERSION } from '../../utils/package-version'; export interface HashFormat { chunk: string; @@ -122,8 +123,6 @@ export function getCacheSettings( ): WebpackOptionsNormalized['cache'] { const { enabled, path: cacheDirectory } = wco.buildOptions.cache; if (enabled) { - const packageVersion = require('../../../package.json').version; - return { type: 'filesystem', profile: wco.buildOptions.verbose, @@ -134,7 +133,7 @@ export function getCacheSettings( // None of which are "named". name: createHash('sha1') .update(angularVersion) - .update(packageVersion) + .update(VERSION) .update(wco.projectRoot) .update(JSON.stringify(wco.tsConfig)) .update( diff --git a/tests/legacy-cli/e2e/tests/build/disk-cache-purge.ts b/tests/legacy-cli/e2e/tests/build/disk-cache-purge.ts new file mode 100644 index 000000000000..732117419bed --- /dev/null +++ b/tests/legacy-cli/e2e/tests/build/disk-cache-purge.ts @@ -0,0 +1,27 @@ +import { join } from 'path'; +import { createDir, expectFileNotToExist, expectFileToExist } from '../../utils/fs'; +import { ng } from '../../utils/process'; +import { updateJsonFile } from '../../utils/project'; + +export default async function () { + const cachePath = '.angular/cache'; + const staleCachePath = join(cachePath, 'v1.0.0'); + + // Enable cache for all environments + await updateJsonFile('angular.json', (config) => { + config.cli ??= {}; + config.cli.cache = { + environment: 'all', + enabled: true, + path: cachePath, + }; + }); + + // Create a dummy stale disk cache directory. + await createDir(staleCachePath); + await expectFileToExist(staleCachePath); + + await ng('build'); + await expectFileToExist(cachePath); + await expectFileNotToExist(staleCachePath); +} From 6ca0e41a9b54aef0a8ea626be73e06d19370f3a7 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 11 Jan 2022 11:58:06 +0100 Subject: [PATCH 10/17] perf(@angular-devkit/build-angular): update `esbuild` to `0.14.11` Closes #22472 --- package.json | 4 +- .../angular_devkit/build_angular/package.json | 4 +- yarn.lock | 123 +++++++++++++++++- 3 files changed, 125 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 04a647821ad0..456af3856814 100644 --- a/package.json +++ b/package.json @@ -142,8 +142,8 @@ "critters": "0.0.16", "css-loader": "6.5.1", "debug": "^4.1.1", - "esbuild": "0.14.2", - "esbuild-wasm": "0.14.2", + "esbuild": "0.14.11", + "esbuild-wasm": "0.14.11", "eslint": "8.4.1", "eslint-config-prettier": "8.3.0", "eslint-plugin-header": "3.1.1", diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index f502c98563a7..2192596060c1 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -31,7 +31,7 @@ "core-js": "3.19.3", "critters": "0.0.16", "css-loader": "6.5.1", - "esbuild-wasm": "0.14.2", + "esbuild-wasm": "0.14.11", "glob": "7.2.0", "https-proxy-agent": "5.0.0", "inquirer": "8.2.0", @@ -72,7 +72,7 @@ "webpack-subresource-integrity": "5.0.0" }, "optionalDependencies": { - "esbuild": "0.14.2" + "esbuild": "0.14.11" }, "peerDependencies": { "@angular/compiler-cli": "^13.0.0 || ^13.1.0-next", diff --git a/yarn.lock b/yarn.lock index 2d427652ab62..612b2ef5bde9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4840,6 +4840,11 @@ esbuild-android-arm64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.12.tgz#e1f199dc05405cdc6670c00fb6c793822bf8ae4c" integrity sha512-TSVZVrb4EIXz6KaYjXfTzPyyRpXV5zgYIADXtQsIenjZ78myvDGaPi11o4ZSaHIwFHsuwkB6ne5SZRBwAQ7maw== +esbuild-android-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.11.tgz#b8b34e35a5b43880664ac7a3fbc70243d7ed894f" + integrity sha512-6iHjgvMnC/SzDH8TefL+/3lgCjYWwAd1LixYfmz/TBPbDQlxcuSkX0yiQgcJB9k+ibZ54yjVXziIwGdlc+6WNw== + esbuild-android-arm64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.2.tgz#256b7cf2f9d382a2a92a4ff4e13187587c9b7c6a" @@ -4850,6 +4855,11 @@ esbuild-darwin-64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.12.tgz#f5c59e622955c01f050e5a7ac9c1d41db714b94d" integrity sha512-c51C+N+UHySoV2lgfWSwwmlnLnL0JWj/LzuZt9Ltk9ub1s2Y8cr6SQV5W3mqVH1egUceew6KZ8GyI4nwu+fhsw== +esbuild-darwin-64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.11.tgz#ba805de98c0412e50fcd0636451797da157b0625" + integrity sha512-olq84ikh6TiBcrs3FnM4eR5VPPlcJcdW8BnUz/lNoEWYifYQ+Po5DuYV1oz1CTFMw4k6bQIZl8T3yxL+ZT2uvQ== + esbuild-darwin-64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.2.tgz#891a59ce6bc3aded0265f982469b3eb9571b92f8" @@ -4860,6 +4870,11 @@ esbuild-darwin-arm64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.12.tgz#8abae74c2956a8aa568fc52c78829338c4a4b988" integrity sha512-JvAMtshP45Hd8A8wOzjkY1xAnTKTYuP/QUaKp5eUQGX+76GIie3fCdUUr2ZEKdvpSImNqxiZSIMziEiGB5oUmQ== +esbuild-darwin-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.11.tgz#4d3573e448af76ce33e16231f3d9f878542d6fe8" + integrity sha512-Jj0ieWLREPBYr/TZJrb2GFH8PVzDqiQWavo1pOFFShrcmHWDBDrlDxPzEZ67NF/Un3t6sNNmeI1TUS/fe1xARg== + esbuild-darwin-arm64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.2.tgz#ab834fffa9c612b2901ca1e77e4695d4d8aa63a2" @@ -4870,6 +4885,11 @@ esbuild-freebsd-64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.12.tgz#6ad2ab8c0364ee7dd2d6e324d876a8e60ae75d12" integrity sha512-r6On/Skv9f0ZjTu6PW5o7pdXr8aOgtFOEURJZYf1XAJs0IQ+gW+o1DzXjVkIoT+n1cm3N/t1KRJfX71MPg/ZUA== +esbuild-freebsd-64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.11.tgz#9294e6ab359ec93590ab097b0f2017de7c78ab4d" + integrity sha512-C5sT3/XIztxxz/zwDjPRHyzj/NJFOnakAanXuyfLDwhwupKPd76/PPHHyJx6Po6NI6PomgVp/zi6GRB8PfrOTA== + esbuild-freebsd-64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.2.tgz#f7fc87a83f02de27d5a48472571efa1a432ae86d" @@ -4880,6 +4900,11 @@ esbuild-freebsd-arm64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.12.tgz#6f38155f4c300ac4c8adde1fde3cc6a4440a8294" integrity sha512-F6LmI2Q1gii073kmBE3NOTt/6zLL5zvZsxNLF8PMAwdHc+iBhD1vzfI8uQZMJA1IgXa3ocr3L3DJH9fLGXy6Yw== +esbuild-freebsd-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.11.tgz#ae3e0b09173350b66cf8321583c9a1c1fcb8bb55" + integrity sha512-y3Llu4wbs0bk4cwjsdAtVOesXb6JkdfZDLKMt+v1U3tOEPBdSu6w8796VTksJgPfqvpX22JmPLClls0h5p+L9w== + esbuild-freebsd-arm64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.2.tgz#bc8758420431106751f3180293cac0b5bc4ce2ee" @@ -4890,6 +4915,11 @@ esbuild-linux-32@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.12.tgz#b1d15e330188a8c21de75c3f0058628a3eefade7" integrity sha512-U1UZwG3UIwF7/V4tCVAo/nkBV9ag5KJiJTt+gaCmLVWH3bPLX7y+fNlhIWZy8raTMnXhMKfaTvWZ9TtmXzvkuQ== +esbuild-linux-32@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.11.tgz#ddadbc7038aa5a6b1675bb1503cf79a0cbf1229a" + integrity sha512-Cg3nVsxArjyLke9EuwictFF3Sva+UlDTwHIuIyx8qpxRYAOUTmxr2LzYrhHyTcGOleLGXUXYsnUVwKqnKAgkcg== + esbuild-linux-32@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.2.tgz#0cc2dcd816d6d66e255bc7aeac139b1d04246812" @@ -4900,6 +4930,11 @@ esbuild-linux-64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.12.tgz#25bd64b66162b02348e32d8f12e4c9ee61f1d070" integrity sha512-YpXSwtu2NxN3N4ifJxEdsgd6Q5d8LYqskrAwjmoCT6yQnEHJSF5uWcxv783HWN7lnGpJi9KUtDvYsnMdyGw71Q== +esbuild-linux-64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.11.tgz#d698e3ce3a231ddfeec6b5df8c546ae8883fcd88" + integrity sha512-oeR6dIrrojr8DKVrxtH3xl4eencmjsgI6kPkDCRIIFwv4p+K7ySviM85K66BN01oLjzthpUMvBVfWSJkBLeRbg== + esbuild-linux-64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.2.tgz#c790f739aa75b15c153609ea3457153fbe4db93d" @@ -4910,6 +4945,11 @@ esbuild-linux-arm64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.12.tgz#ba582298457cc5c9ac823a275de117620c06537f" integrity sha512-sgDNb8kb3BVodtAlcFGgwk+43KFCYjnFOaOfJibXnnIojNWuJHpL6aQJ4mumzNWw8Rt1xEtDQyuGK9f+Y24jGA== +esbuild-linux-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.11.tgz#85faea9fa99ad355b5e3b283197a4dfd0a110fe7" + integrity sha512-+e6ZCgTFQYZlmg2OqLkg1jHLYtkNDksxWDBWNtI4XG4WxuOCUErLqfEt9qWjvzK3XBcCzHImrajkUjO+rRkbMg== + esbuild-linux-arm64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.2.tgz#96858a1f89ad30274dec780d0e3dd8b5691c6b0c" @@ -4920,6 +4960,11 @@ esbuild-linux-arm@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.12.tgz#6bc81c957bff22725688cc6359c29a25765be09b" integrity sha512-SyiT/JKxU6J+DY2qUiSLZJqCAftIt3uoGejZ0HDnUM2MGJqEGSGh7p1ecVL2gna3PxS4P+j6WAehCwgkBPXNIw== +esbuild-linux-arm@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.11.tgz#74cbcf0b8a22c8401bcbcd6ebd4cbf2baca8b7b4" + integrity sha512-vcwskfD9g0tojux/ZaTJptJQU3a7YgTYsptK1y6LQ/rJmw7U5QJvboNawqM98Ca3ToYEucfCRGbl66OTNtp6KQ== + esbuild-linux-arm@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.2.tgz#03e193225afa9b1215d2ec6efe8edf0c03eeed6f" @@ -4930,6 +4975,11 @@ esbuild-linux-mips64le@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.12.tgz#ef3c4aba3e585d847cbade5945a8b4a5c62c7ce2" integrity sha512-qQJHlZBG+QwVIA8AbTEtbvF084QgDi4DaUsUnA+EolY1bxrG+UyOuGflM2ZritGhfS/k7THFjJbjH2wIeoKA2g== +esbuild-linux-mips64le@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.11.tgz#490429211a3233f5cbbd8575b7758b897e42979a" + integrity sha512-Rrs99L+p54vepmXIb87xTG6ukrQv+CzrM8eoeR+r/OFL2Rg8RlyEtCeshXJ2+Q66MXZOgPJaokXJZb9snq28bw== + esbuild-linux-mips64le@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.2.tgz#972f218d2cb5125237376d40ad60a6e5356a782c" @@ -4940,16 +4990,31 @@ esbuild-linux-ppc64le@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.12.tgz#a21fb64e80c38bef06122e48283990fc6db578e1" integrity sha512-2dSnm1ldL7Lppwlo04CGQUpwNn5hGqXI38OzaoPOkRsBRWFBozyGxTFSee/zHFS+Pdh3b28JJbRK3owrrRgWNw== +esbuild-linux-ppc64le@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.11.tgz#fc79d60710213b5b98345f5b138d48245616827a" + integrity sha512-JyzziGAI0D30Vyzt0HDihp4s1IUtJ3ssV2zx9O/c+U/dhUHVP2TmlYjzCfCr2Q6mwXTeloDcLS4qkyvJtYptdQ== + esbuild-linux-ppc64le@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.2.tgz#20b71622ac09142b0e523f633af0829def7fed6b" integrity sha512-vxptskw8JfCDD9QqpRO0XnsM1osuWeRjPaXX1TwdveLogYsbdFtcuiuK/4FxGiNMUr1ojtnCS2rMPbY8puc5NA== +esbuild-linux-s390x@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.11.tgz#ca4b93556bbba6cc95b0644f2ee93c982165ba07" + integrity sha512-DoThrkzunZ1nfRGoDN6REwmo8ZZWHd2ztniPVIR5RMw/Il9wiWEYBahb8jnMzQaSOxBsGp0PbyJeVLTUatnlcw== + esbuild-netbsd-64@0.13.12: version "0.13.12" resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.12.tgz#1ea7fc8cfce88a20a4047b867ef184049a6641ae" integrity sha512-D4raxr02dcRiQNbxOLzpqBzcJNFAdsDNxjUbKkDMZBkL54Z0vZh4LRndycdZAMcIdizC/l/Yp/ZsBdAFxc5nbA== +esbuild-netbsd-64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.11.tgz#edb340bc6653c88804cac2253e21b74258fce165" + integrity sha512-12luoRQz+6eihKYh1zjrw0CBa2aw3twIiHV/FAfjh2NEBDgJQOY4WCEUEN+Rgon7xmLh4XUxCQjnwrvf8zhACw== + esbuild-netbsd-64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.2.tgz#dbd6a25117902ef67aa11d8779dd9c6bca7fbe82" @@ -4960,6 +5025,11 @@ esbuild-openbsd-64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.12.tgz#adde32f2f1b05dc4bd4fc544d6ea5a4379f9ca4d" integrity sha512-KuLCmYMb2kh05QuPJ+va60bKIH5wHL8ypDkmpy47lzwmdxNsuySeCMHuTv5o2Af1RUn5KLO5ZxaZeq4GEY7DaQ== +esbuild-openbsd-64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.11.tgz#caeff5f946f79a60ce7bcf88871ca4c71d3476e8" + integrity sha512-l18TZDjmvwW6cDeR4fmizNoxndyDHamGOOAenwI4SOJbzlJmwfr0jUgjbaXCUuYVOA964siw+Ix+A+bhALWg8Q== + esbuild-openbsd-64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.2.tgz#3c5f199eed459b2f88865548394c0b77383d9ca4" @@ -4970,6 +5040,11 @@ esbuild-sunos-64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.12.tgz#a7ecaf52b7364fbee76dc8aa707fa3e1cff3342c" integrity sha512-jBsF+e0woK3miKI8ufGWKG3o3rY9DpHvCVRn5eburMIIE+2c+y3IZ1srsthKyKI6kkXLvV4Cf/E7w56kLipMXw== +esbuild-sunos-64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.11.tgz#90ce7e1749c2958a53509b4bae7b8f7d98f276d6" + integrity sha512-bmYzDtwASBB8c+0/HVOAiE9diR7+8zLm/i3kEojUH2z0aIs6x/S4KiTuT5/0VKJ4zk69kXel1cNWlHBMkmavQg== + esbuild-sunos-64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.2.tgz#900a681db6b76c6a7f60fc28d2bfe5b11698641c" @@ -4980,7 +5055,12 @@ esbuild-wasm@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.13.12.tgz#1f78316c12e66ca7dffded832d5a9630b34b7657" integrity sha512-eGdiSewbnJffEvyA0qQmr+w3HurBMVp4QhOfICzeeoL9naC8qC3PFaw6hZaqSgks5DXnQONtUGUFLsX3eXpq8A== -esbuild-wasm@0.14.2, esbuild-wasm@^0.14.0: +esbuild-wasm@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.14.11.tgz#bd09f4c42969cddcae39007d284f8ef747aae85d" + integrity sha512-9e1R6hv0hiU+BkJI2edqUuWfXUbOP2Mox+Ijl/uY1vLLlSsunkrcADqD/4Rz+VCEDzw6ecscJM+uJqR2fRmEUg== + +esbuild-wasm@^0.14.0: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-wasm/-/esbuild-wasm-0.14.2.tgz#49c59c610a0be48becec87a7d9019d143468f2f9" integrity sha512-Rs8NjWoo1UdsVjhxT2o6kLCX9Sh65pyd3/h4XeJ3jjQNM6NgL+/CSowuJgvOIjDAXMLXpc6fdGnyZQDil9IUJA== @@ -4990,6 +5070,11 @@ esbuild-windows-32@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.12.tgz#a8756033dc905c4b7bea19be69f7ee68809f8770" integrity sha512-L9m4lLFQrFeR7F+eLZXG82SbXZfUhyfu6CexZEil6vm+lc7GDCE0Q8DiNutkpzjv1+RAbIGVva9muItQ7HVTkQ== +esbuild-windows-32@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.11.tgz#d067f4ce15b29efba6336e6a23597120fafe49ec" + integrity sha512-J1Ys5hMid8QgdY00OBvIolXgCQn1ARhYtxPnG6ESWNTty3ashtc4+As5nTrsErnv8ZGUcWZe4WzTP/DmEVX1UQ== + esbuild-windows-32@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.2.tgz#61e0ba5bd95b277a55d2b997ac4c04dfe2559220" @@ -5000,6 +5085,11 @@ esbuild-windows-64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.12.tgz#ae694aa66ca078acb8509b2da31197ed1f40f798" integrity sha512-k4tX4uJlSbSkfs78W5d9+I9gpd+7N95W7H2bgOMFPsYREVJs31+Q2gLLHlsnlY95zBoPQMIzHooUIsixQIBjaQ== +esbuild-windows-64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.11.tgz#13e86dd37a6cd61a5276fa2d271342d0f74da864" + integrity sha512-h9FmMskMuGeN/9G9+LlHPAoiQk9jlKDUn9yA0MpiGzwLa82E7r1b1u+h2a+InprbSnSLxDq/7p5YGtYVO85Mlg== + esbuild-windows-64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.2.tgz#6ab59ef721ff75c682a1c8ae0570dabb637abddb" @@ -5010,6 +5100,11 @@ esbuild-windows-arm64@0.13.12: resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.12.tgz#782c5a8bd6d717ea55aaafe648f9926ca36a4a88" integrity sha512-2tTv/BpYRIvuwHpp2M960nG7uvL+d78LFW/ikPItO+2GfK51CswIKSetSpDii+cjz8e9iSPgs+BU4o8nWICBwQ== +esbuild-windows-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.11.tgz#e8edfdf1d712085e6dc3fba18a0c225aaae32b75" + integrity sha512-dZp7Krv13KpwKklt9/1vBFBMqxEQIO6ri7Azf8C+ob4zOegpJmha2XY9VVWP/OyQ0OWk6cEeIzMJwInRZrzBUQ== + esbuild-windows-arm64@0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.2.tgz#aca2a4f83d2f0d1592ad4be832ed0045fc888cda" @@ -5038,7 +5133,31 @@ esbuild@0.13.12: esbuild-windows-64 "0.13.12" esbuild-windows-arm64 "0.13.12" -esbuild@0.14.2, esbuild@^0.14.0: +esbuild@0.14.11: + version "0.14.11" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.11.tgz#ac4acb78907874832afb704c3afe58ad37715c27" + integrity sha512-xZvPtVj6yecnDeFb3KjjCM6i7B5TCAQZT77kkW/CpXTMnd6VLnRPKrUB1XHI1pSq6a4Zcy3BGueQ8VljqjDGCg== + optionalDependencies: + esbuild-android-arm64 "0.14.11" + esbuild-darwin-64 "0.14.11" + esbuild-darwin-arm64 "0.14.11" + esbuild-freebsd-64 "0.14.11" + esbuild-freebsd-arm64 "0.14.11" + esbuild-linux-32 "0.14.11" + esbuild-linux-64 "0.14.11" + esbuild-linux-arm "0.14.11" + esbuild-linux-arm64 "0.14.11" + esbuild-linux-mips64le "0.14.11" + esbuild-linux-ppc64le "0.14.11" + esbuild-linux-s390x "0.14.11" + esbuild-netbsd-64 "0.14.11" + esbuild-openbsd-64 "0.14.11" + esbuild-sunos-64 "0.14.11" + esbuild-windows-32 "0.14.11" + esbuild-windows-64 "0.14.11" + esbuild-windows-arm64 "0.14.11" + +esbuild@^0.14.0: version "0.14.2" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.2.tgz#9c1e1a652549cc33e44885eea42ea2cc6267edc2" integrity sha512-l076A6o/PIgcyM24s0dWmDI/b8RQf41uWoJu9I0M71CtW/YSw5T5NUeXxs5lo2tFQD+O4CW4nBHJXx3OY5NpXg== From 92b4e067b24bdcd1bb7e40612b5355ce61e040ce Mon Sep 17 00:00:00 2001 From: Bill Barry Date: Mon, 10 Jan 2022 08:49:44 -0500 Subject: [PATCH 11/17] fix(@angular-devkit/build-angular): load translations fresh start Currently when making a change while serving a localized application, duplicate translation warnings appear for every translation id. This fixes that by replacing the whole translation object with a new one each time translations are loaded. fixes #22398 --- .../build_angular/src/utils/i18n-options.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/utils/i18n-options.ts b/packages/angular_devkit/build_angular/src/utils/i18n-options.ts index da6652062b25..f3ef1d7b9dde 100644 --- a/packages/angular_devkit/build_angular/src/utils/i18n-options.ts +++ b/packages/angular_devkit/build_angular/src/utils/i18n-options.ts @@ -283,6 +283,7 @@ export function loadTranslations( logger: { warn: (message: string) => void; error: (message: string) => void }, usedFormats?: Set, ) { + let translations: Record | undefined = undefined; for (const file of desc.files) { const loadResult = loader(path.join(workspaceRoot, file.path)); @@ -304,19 +305,20 @@ export function loadTranslations( file.format = loadResult.format; file.integrity = loadResult.integrity; - if (desc.translation) { + if (translations) { // Merge translations for (const [id, message] of Object.entries(loadResult.translations)) { - if (desc.translation[id] !== undefined) { + if (translations[id] !== undefined) { logger.warn( `WARNING [${file.path}]: Duplicate translations for message '${id}' when merging`, ); } - desc.translation[id] = message; + translations[id] = message; } } else { // First or only translation file - desc.translation = loadResult.translations; + translations = loadResult.translations; } } + desc.translation = translations; } From 11fd02105908e155c4a9c7f87e9641127cc2f378 Mon Sep 17 00:00:00 2001 From: Elio Goettelmann Date: Sat, 8 Jan 2022 23:02:35 +0100 Subject: [PATCH 12/17] fix(@angular-devkit/build-angular): websocket client only injected if required After the webpack-dev-server migration to v4, the websocket client was always injected, even if not required. This caused unnecessary 'ws' requests when live-reload and hmr were disabled. (cherry picked from commit 50167a36b0f9803ebcedafa9abbd9ecc5bc19a40) --- .../src/webpack/configs/dev-server.ts | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/webpack/configs/dev-server.ts b/packages/angular_devkit/build_angular/src/webpack/configs/dev-server.ts index 956c83321333..ae6340283580 100644 --- a/packages/angular_devkit/build_angular/src/webpack/configs/dev-server.ts +++ b/packages/angular_devkit/build_angular/src/webpack/configs/dev-server.ts @@ -51,8 +51,6 @@ export async function getDevServerConfig( }); } - const webSocketPath = posix.join(servePath, 'ws'); - return { plugins: extraPlugins, module: { @@ -76,11 +74,6 @@ export async function getDevServerConfig( }, ], }, - webSocketServer: { - options: { - path: webSocketPath, - }, - }, compress: false, static: false, server: getServerConfig(root, wco.buildOptions), @@ -92,14 +85,7 @@ export async function getDevServerConfig( liveReload, hot: hmr && !liveReload ? 'only' : hmr, proxy: await addProxyConfig(root, proxyConfig), - client: { - logging: 'info', - webSocketURL: getPublicHostOptions(wco.buildOptions, webSocketPath), - overlay: { - errors: true, - warnings: false, - }, - }, + ...getWebSocketSettings(wco.buildOptions, servePath), }, }; } @@ -297,6 +283,40 @@ function getAllowedHostsConfig( return undefined; } +function getWebSocketSettings( + options: WebpackDevServerOptions, + servePath: string, +): { + webSocketServer?: DevServerConfiguration['webSocketServer']; + client?: DevServerConfiguration['client']; +} { + const { hmr, liveReload } = options; + if (!hmr && !liveReload) { + return { + webSocketServer: false, + client: undefined, + }; + } + + const webSocketPath = posix.join(servePath, 'ws'); + + return { + webSocketServer: { + options: { + path: webSocketPath, + }, + }, + client: { + logging: 'info', + webSocketURL: getPublicHostOptions(options, webSocketPath), + overlay: { + errors: true, + warnings: false, + }, + }, + }; +} + function getPublicHostOptions(options: WebpackDevServerOptions, webSocketPath: string): string { let publicHost: string | null | undefined = options.publicHost; if (publicHost) { From de5fe42a73cf3dd512abc0c1f70a58e9ac3618b9 Mon Sep 17 00:00:00 2001 From: Kasper Christensen Date: Wed, 22 Dec 2021 12:31:39 +0100 Subject: [PATCH 13/17] refactor(@schematics/angular): changed casings and small reorganizing Removed profiling files Removed chrome-profiler-events*.json as it's no longer generated. (cherry picked from commit 08152f78b294aff58a1f4063020c8bb28414c79a) --- .../workspace/files/__dot__gitignore.template | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/schematics/angular/workspace/files/__dot__gitignore.template b/packages/schematics/angular/workspace/files/__dot__gitignore.template index 105c00f22e08..0711527ef9d5 100644 --- a/packages/schematics/angular/workspace/files/__dot__gitignore.template +++ b/packages/schematics/angular/workspace/files/__dot__gitignore.template @@ -1,20 +1,18 @@ # See http://help.github.com/ignore-files/ for more about ignoring files. -# compiled output +# Compiled output /dist /tmp /out-tsc -# Only exists if Bazel was run /bazel-out -# dependencies +# Node /node_modules - -# profiling files -chrome-profiler-events*.json +npm-debug.log +yarn-error.log # IDEs and editors -/.idea +.idea/ .project .classpath .c9/ @@ -22,7 +20,7 @@ chrome-profiler-events*.json .settings/ *.sublime-workspace -# IDE - VSCode +# Visual Studio Code .vscode/* !.vscode/settings.json !.vscode/tasks.json @@ -30,17 +28,15 @@ chrome-profiler-events*.json !.vscode/extensions.json .history/* -# misc +# Miscellaneous /.angular/cache -/.sass-cache +.sass-cache/ /connect.lock /coverage /libpeerconnection.log -npm-debug.log -yarn-error.log testem.log /typings -# System Files +# System files .DS_Store Thumbs.db From d674dcd1af409910dd4f41ac676349aee363ebdb Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 11 Jan 2022 08:36:03 +0100 Subject: [PATCH 14/17] fix(@angular-devkit/build-angular): localized bundle generation fails in watch mode Previously, we used to delete the temporary emitted JS and map files. However this causes a problem in watch mode, as Webpack will not re-emit these deleted files during the next incremental re-build. With this change we now delete the entire temporary directory when the process is being terminated instead of a file by file bases. Closes #22395 (cherry picked from commit 0d68ed547362e6bad0a9c5ca5209b65ed125bbd8) --- .../src/builders/browser/index.ts | 6 ++ .../tests/behavior/localize_watch_spec.ts | 95 +++++++++++++++++++ .../tests/behavior/rebuild-errors_spec.ts | 8 +- .../build_angular/src/utils/i18n-inlining.ts | 18 ---- .../build_angular/src/utils/i18n-options.ts | 35 ++++++- 5 files changed, 135 insertions(+), 27 deletions(-) create mode 100644 packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/localize_watch_spec.ts diff --git a/packages/angular_devkit/build_angular/src/builders/browser/index.ts b/packages/angular_devkit/build_angular/src/builders/browser/index.ts index 4236bb37d166..7aa57d8090fc 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/index.ts @@ -74,6 +74,12 @@ export type BrowserBuilderOutput = json.JsonObject & outputPath: string; }; +/** + * Maximum time in milliseconds for single build/rebuild + * This accounts for CI variability. + */ +export const BUILD_TIMEOUT = 30_000; + async function initialize( options: BrowserBuilderSchema, context: BuilderContext, diff --git a/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/localize_watch_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/localize_watch_spec.ts new file mode 100644 index 000000000000..6b1e00abab3b --- /dev/null +++ b/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/localize_watch_spec.ts @@ -0,0 +1,95 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { concatMap, count, take, timeout } from 'rxjs/operators'; +import { BUILD_TIMEOUT, buildWebpackBrowser } from '../../index'; +import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup'; + +describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => { + describe('Behavior: "localize works in watch mode"', () => { + beforeEach(() => { + harness.useProject('test', { + root: '.', + sourceRoot: 'src', + cli: { + cache: { + enabled: false, + }, + }, + i18n: { + locales: { + 'fr': 'src/locales/messages.fr.xlf', + }, + }, + }); + }); + + it('localize works in watch mode', async () => { + harness.useTarget('build', { + ...BASE_OPTIONS, + watch: true, + localize: true, + }); + + await harness.writeFile( + 'src/app/app.component.html', + ` +

Hello {{ title }}!

+ `, + ); + + await harness.writeFile('src/locales/messages.fr.xlf', TRANSLATION_FILE_CONTENT); + + const buildCount = await harness + .execute() + .pipe( + timeout(BUILD_TIMEOUT), + concatMap(async ({ result }, index) => { + expect(result?.success).toBe(true); + + switch (index) { + case 0: { + harness.expectFile('dist/fr/main.js').content.toContain('Bonjour'); + + // Trigger rebuild + await harness.appendToFile('src/app/app.component.html', '\n\n'); + break; + } + case 1: { + harness.expectFile('dist/fr/main.js').content.toContain('Bonjour'); + break; + } + } + }), + take(2), + count(), + ) + .toPromise(); + + expect(buildCount).toBe(2); + }); + }); +}); + +const TRANSLATION_FILE_CONTENT = ` + + + + + + Bonjour ! + + src/app/app.component.html + 2,3 + + An introduction header for this sample + + + + +`; diff --git a/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/rebuild-errors_spec.ts b/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/rebuild-errors_spec.ts index 6dfe95b144c9..cb553c366c80 100644 --- a/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/rebuild-errors_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/browser/tests/behavior/rebuild-errors_spec.ts @@ -8,7 +8,7 @@ import { logging } from '@angular-devkit/core'; import { concatMap, count, take, timeout } from 'rxjs/operators'; -import { buildWebpackBrowser } from '../../index'; +import { BUILD_TIMEOUT, buildWebpackBrowser } from '../../index'; import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup'; describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => { @@ -70,7 +70,7 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => { const buildCount = await harness .execute({ outputLogsOnFailure: false }) .pipe( - timeout(60000), + timeout(BUILD_TIMEOUT), concatMap(async ({ result, logs }, index) => { switch (index) { case 0: @@ -219,7 +219,7 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => { const buildCount = await harness .execute({ outputLogsOnFailure: false }) .pipe( - timeout(60000), + timeout(BUILD_TIMEOUT), concatMap(async ({ result, logs }, index) => { switch (index) { case 0: @@ -307,7 +307,7 @@ describeBuilder(buildWebpackBrowser, BROWSER_BUILDER_INFO, (harness) => { const buildCount = await harness .execute({ outputLogsOnFailure: false }) .pipe( - timeout(30000), + timeout(BUILD_TIMEOUT), concatMap(async ({ result, logs }, index) => { switch (index) { case 0: diff --git a/packages/angular_devkit/build_angular/src/utils/i18n-inlining.ts b/packages/angular_devkit/build_angular/src/utils/i18n-inlining.ts index cf30f6481811..0a563642add2 100644 --- a/packages/angular_devkit/build_angular/src/utils/i18n-inlining.ts +++ b/packages/angular_devkit/build_angular/src/utils/i18n-inlining.ts @@ -47,28 +47,10 @@ function emittedFilesToInlineOptions( }; originalFiles.push(originalPath); - // Remove temporary original file as the content has now been read - try { - fs.unlinkSync(originalPath); - } catch (e) { - context.logger.debug( - `Unable to delete i18n temporary file [${originalPath}]: ${e.toString()}`, - ); - } - try { const originalMapPath = originalPath + '.map'; action.map = fs.readFileSync(originalMapPath, 'utf8'); originalFiles.push(originalMapPath); - - // Remove temporary original map file as the content has now been read - try { - fs.unlinkSync(originalMapPath); - } catch (e) { - context.logger.debug( - `Unable to delete i18n temporary file [${originalMapPath}]: ${e.toString()}`, - ); - } } catch (err) { if (err.code !== 'ENOENT') { throw err; diff --git a/packages/angular_devkit/build_angular/src/utils/i18n-options.ts b/packages/angular_devkit/build_angular/src/utils/i18n-options.ts index f3ef1d7b9dde..d088394bf7dc 100644 --- a/packages/angular_devkit/build_angular/src/utils/i18n-options.ts +++ b/packages/angular_devkit/build_angular/src/utils/i18n-options.ts @@ -248,11 +248,12 @@ export async function configureI18nBuild { - try { - fs.rmdirSync(tempPath, { recursive: true, maxRetries: 3 }); - } catch {} + process.on('exit', () => deleteTempDirectory(tempPath)); + process.once('SIGINT', () => { + deleteTempDirectory(tempPath); + + // Needed due to `ora` as otherwise process will not terminate. + process.kill(process.pid, 'SIGINT'); }); } @@ -275,6 +276,30 @@ function findLocaleDataPath(locale: string, resolver: (locale: string) => string } } +/** Remove temporary directory used for i18n processing. */ +function deleteTempDirectory(tempPath: string): void { + // The below should be removed and replaced with just `rmSync` when support for Node.Js 12 is removed. + const { rmSync, rmdirSync } = fs as typeof fs & { + rmSync?: ( + path: fs.PathLike, + options?: { + force?: boolean; + maxRetries?: number; + recursive?: boolean; + retryDelay?: number; + }, + ) => void; + }; + + try { + if (rmSync) { + rmSync(tempPath, { force: true, recursive: true, maxRetries: 3 }); + } else { + rmdirSync(tempPath, { recursive: true, maxRetries: 3 }); + } + } catch {} +} + export function loadTranslations( locale: string, desc: LocaleDescription, From 6a617ff4a2fe75968965dc5dcf0f3ba7bae92935 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 11 Jan 2022 08:31:36 +0100 Subject: [PATCH 15/17] fix(@angular-devkit/build-angular): ensure `$localize` calls are replaced in watch mode When `translations` is undefined `$localize` calls are not replaced. https://github.com/angular/angular-cli/blob/2c9a33dddb38694b6940ec6981c49904de1ab636/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts#L382 Closes #22435 (cherry picked from commit 426ddb68d9a21b036d6151e6cdee625e58ca1194) --- .../src/builders/dev-server/index.ts | 2 +- .../build_localize_replaced_watch_spec.ts | 82 +++++++++++++++++++ .../src/builders/dev-server/tests/setup.ts | 2 +- 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts index 5a19d8002ba8..87e48524573c 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts @@ -378,7 +378,7 @@ async function setupLocalize( addError(compilation, message); }, }); - i18nLoaderOptions.translation = localeDescription.translation; + i18nLoaderOptions.translation = localeDescription.translation ?? {}; } compilation.hooks.finishModules.tap('build-angular', () => { diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts new file mode 100644 index 000000000000..5ada84dcc828 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build_localize_replaced_watch_spec.ts @@ -0,0 +1,82 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/* eslint-disable max-len */ +import fetch from 'node-fetch'; // eslint-disable-line import/no-extraneous-dependencies +import { concatMap, count, take, timeout } from 'rxjs/operators'; +import { URL } from 'url'; +import { serveWebpackBrowser } from '../../index'; +import { + BASE_OPTIONS, + BUILD_TIMEOUT, + DEV_SERVER_BUILDER_INFO, + describeBuilder, + setupBrowserTarget, +} from '../setup'; + +describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { + describe('Behavior: "i18n $localize calls are replaced during watching"', () => { + beforeEach(() => { + harness.useProject('test', { + root: '.', + sourceRoot: 'src', + cli: { + cache: { + enabled: false, + }, + }, + i18n: { + sourceLocale: { + 'code': 'fr', + }, + }, + }); + + setupBrowserTarget(harness, { localize: ['fr'] }); + }); + + it('$localize are replaced in watch', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + await harness.writeFile( + 'src/app/app.component.html', + ` +

Hello {{ title }}!

+ `, + ); + + const buildCount = await harness + .execute() + .pipe( + timeout(BUILD_TIMEOUT), + concatMap(async ({ result }, index) => { + expect(result?.success).toBe(true); + + const response = await fetch(new URL('main.js', `${result?.baseUrl}`)); + expect(await response?.text()).not.toContain('$localize`:'); + + switch (index) { + case 0: { + await harness.modifyFile('src/app/app.component.html', (content) => + content.replace('introduction', 'intro'), + ); + break; + } + } + }), + take(2), + count(), + ) + .toPromise(); + + expect(buildCount).toBe(2); + }); + }); +}); diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts index 92cd146a40c4..a6330da2a7cb 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/setup.ts @@ -38,7 +38,7 @@ export const BASE_OPTIONS = Object.freeze({ * Maximum time for single build/rebuild * This accounts for CI variability. */ -export const BUILD_TIMEOUT = 15000; +export const BUILD_TIMEOUT = 15_000; /** * Cached browser builder option schema From fc698c6662788f916d7199b59d1b4d65715517ee Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Wed, 12 Jan 2022 10:48:50 -0800 Subject: [PATCH 16/17] build: update shelljs dependencies to "^0.8.5" Update shelljs dependencies to ^0.8.5 to fix a vulnerability reported to shelljs. (cherry picked from commit 7b24cee0c7d76cefb6fcf6ebff27949992c1b056) --- package.json | 2 +- yarn.lock | 20 ++++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 456af3856814..2fa498edb4b4 100644 --- a/package.json +++ b/package.json @@ -205,7 +205,7 @@ "sass-loader": "12.4.0", "sauce-connect-proxy": "https://saucelabs.com/downloads/sc-4.6.4-linux.tar.gz", "semver": "7.3.5", - "shelljs": "^0.8.4", + "shelljs": "^0.8.5", "source-map": "0.7.3", "source-map-loader": "3.0.0", "source-map-support": "0.5.21", diff --git a/yarn.lock b/yarn.lock index 612b2ef5bde9..808af0609d97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4086,18 +4086,6 @@ critters@0.0.14: postcss "^8.3.7" pretty-bytes "^5.3.0" -critters@0.0.15: - version "0.0.15" - resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.15.tgz#b1c8d18fd18e614471733d7d749deac0f386b738" - integrity sha512-AE7hkXb3eZUbEvS1SKZa+OU4o2kUOXtzVeE/2E/mjU/0mV1wpBT1HfUCWVRS4zwvkBNJ0AQYsVjAoFm+kIhfdw== - dependencies: - chalk "^4.1.0" - css-select "^4.1.3" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - postcss "^8.3.7" - pretty-bytes "^5.3.0" - critters@0.0.16: version "0.0.16" resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93" @@ -10015,10 +10003,10 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" - integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== +shelljs@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== dependencies: glob "^7.0.0" interpret "^1.0.0" From 05d762ccdf2b7e2d90fd1353b481aabeaa5c4e81 Mon Sep 17 00:00:00 2001 From: Doug Parker Date: Wed, 12 Jan 2022 13:32:03 -0800 Subject: [PATCH 17/17] release: cut the v13.1.3 release --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca83725eb977..c543132bdd0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ + + +# 13.1.3 (2022-01-12) + +### @angular/cli + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------- | +| [4c9d72c65](https://github.com/angular/angular-cli/commit/4c9d72c659d912bd9ef4590a2e88340932a96868) | fix | remove extra space in `Unable to find compatible package` during `ng add` | + +### @schematics/angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ---------------------------------------------------------------- | +| [9b07191b1](https://github.com/angular/angular-cli/commit/9b07191b1ccdcd2a6bb17686471acddd5862dcf5) | fix | set `skipTest` flag for resolvers when using ng new --skip-tests | + +### @angular-devkit/build-angular + +| Commit | Type | Description | +| --------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------ | +| [5b39e0eca](https://github.com/angular/angular-cli/commit/5b39e0eca6e8a3825f66ad6cd1818e551bf98f08) | fix | automatically purge stale build cache entries | +| [6046e06b9](https://github.com/angular/angular-cli/commit/6046e06b926af29f89c605504f5356ec553c6390) | fix | correctly resolve `core-js/proposals/reflect-metadata` | +| [de68daa55](https://github.com/angular/angular-cli/commit/de68daa5581dd1f257382da16704d442b540ec41) | fix | enable `:where` CSS pseudo-class | +| [6a617ff4a](https://github.com/angular/angular-cli/commit/6a617ff4a2fe75968965dc5dcf0f3ba7bae92935) | fix | ensure `$localize` calls are replaced in watch mode | +| [92b4e067b](https://github.com/angular/angular-cli/commit/92b4e067b24bdcd1bb7e40612b5355ce61e040ce) | fix | load translations fresh start | +| [d674dcd1a](https://github.com/angular/angular-cli/commit/d674dcd1af409910dd4f41ac676349aee363ebdb) | fix | localized bundle generation fails in watch mode | +| [6876ad36e](https://github.com/angular/angular-cli/commit/6876ad36efaadac5c4d371cff96c9a4cfa0e3d2b) | fix | use `contenthash` instead of `chunkhash` for chunks | +| [11fd02105](https://github.com/angular/angular-cli/commit/11fd02105908e155c4a9c7f87e9641127cc2f378) | fix | websocket client only injected if required | +| [6ca0e41a9](https://github.com/angular/angular-cli/commit/6ca0e41a9b54aef0a8ea626be73e06d19370f3a7) | perf | update `esbuild` to `0.14.11` | + +## Special Thanks + +Alan Agius, Bill Barry, Derek Cormier, Elio Goettelmann, Joey Perrott, Kasper Christensen, Lukas Spirig and Zoltan Lehoczky + + + # 13.1.2 (2021-12-15) diff --git a/package.json b/package.json index 2fa498edb4b4..8351694ba0ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@angular/devkit-repo", - "version": "13.1.2", + "version": "13.1.3", "private": true, "description": "Software Development Kit for Angular", "bin": {