refactor: simplify devtools setup given recent ESM changes (#48521)

Since the `defaults.bzl` repo-wide macros are now supporting ESM,
the special spec-bundle logic from `devtools` can be removed.

Also the esbuild configurations need to be updated to account
for the recent dev-infra build-tooling changes. Also properly
now ensures that `aysnc/await` is downleveled for ZoneJS compatibility.

PR Close #48521
This commit is contained in:
Paul Gschwendtner 2022-12-14 10:38:17 +00:00
parent abfef9992a
commit c841da82c2
8 changed files with 81 additions and 149 deletions

View file

@ -1,36 +1,8 @@
# Re-export of Bazel rules with devtools-wide defaults
load("@npm//@angular/build-tooling/bazel/spec-bundling:index.bzl", "spec_bundle")
load("@npm//@angular/build-tooling/bazel/karma:index.bzl", _karma_web_test_suite = "karma_web_test_suite")
load("@npm//@angular/build-tooling/bazel:extract_js_module_output.bzl", "extract_js_module_output")
load("//tools:defaults.bzl", _karma_web_test_suite = "karma_web_test_suite")
def karma_web_test_suite(name, **kwargs):
test_deps = kwargs.get("deps", [])
kwargs["deps"] = ["%s_bundle" % name]
# TODO(ESM): Remove this when devmode & prodmode are combined.
extract_js_module_output(
name = "%s_prodmode_deps" % name,
deps = test_deps,
provider = "JSEcmaScriptModuleInfo",
forward_linker_mappings = True,
include_external_npm_packages = True,
include_default_files = False,
include_declarations = True,
testonly = True,
)
spec_bundle(
name = "%s_bundle" % name,
deps = ["%s_prodmode_deps" % name],
platform = "browser",
run_angular_linker = True,
# We consume the Angular framework packages directly from source. The
# placeholders might not be substituted and still use `0.0.0-PLACEHOLDER`.
linker_unknown_declaration_handling = "ignore",
workspace_name = "angular",
)
# Set up default browsers if no explicit `browsers` have been specified.
if not hasattr(kwargs, "browsers"):
kwargs["tags"] = ["native"] + kwargs.get("tags", [])
@ -44,8 +16,5 @@ def karma_web_test_suite(name, **kwargs):
# Default test suite with all configured browsers.
_karma_web_test_suite(
name = name,
bootstrap = [
"@npm//:node_modules/tslib/tslib.js",
],
**kwargs
)

View file

@ -1,11 +1,16 @@
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
load("//tools:defaults.bzl", "esbuild_config")
load(":index.bzl", "create_angular_bundle_targets")
package(default_visibility = ["//visibility:public"])
esbuild_config(
js_library(
name = "esbuild_base",
config_file = "esbuild-base.config.mjs",
srcs = ["esbuild-base.config.mjs"],
deps = [
"//packages/compiler-cli/private",
"@npm//@angular/build-tooling/shared-scripts/angular-optimization:js_lib",
],
)
esbuild_config(
@ -13,7 +18,7 @@ esbuild_config(
config_file = "esbuild-esm.config.mjs",
deps = [
":esbuild_base",
"@npm//@angular/build-tooling/shared-scripts/angular-linker:js_lib",
"@npm//@angular/build-tooling/shared-scripts/angular-optimization:js_lib",
],
)
@ -22,9 +27,6 @@ esbuild_config(
config_file = "esbuild-esm-prod.config.mjs",
deps = [
":esbuild_base",
"//packages/compiler-cli/private",
"@npm//@angular/build-tooling/shared-scripts/angular-linker:js_lib",
"@npm//@angular/build-tooling/shared-scripts/angular-optimization:js_lib",
],
)
@ -42,7 +44,6 @@ esbuild_config(
config_file = "esbuild-spec.config.mjs",
deps = [
":esbuild_base",
"@npm//@angular/build-tooling/shared-scripts/angular-linker:js_lib",
],
)

View file

@ -6,10 +6,57 @@
* found in the LICENSE file at https://angular.io/license
*/
export default {
resolveExtensions: ['.mjs', '.js'],
// This ensures that we prioritize ES2020. RxJS would otherwise use the ESM5 output.
mainFields: ['es2020', 'es2015', 'module', 'main'],
// `tslib` sets the `module` condition to resolve to ESM.
conditions: ['es2020', 'es2015', 'module']
};
import {createEsbuildAngularOptimizePlugin} from '@angular/build-tooling/shared-scripts/angular-optimization/esbuild-plugin.mjs';
import {GLOBAL_DEFS_FOR_TERSER_WITH_AOT} from '@angular/compiler-cli/private/tooling.js';
/** Converts an object to a string dictionary. */
function convertObjectToStringDictionary(value) {
return Object.entries(value).reduce((result, [propName, value]) => {
result[propName] = String(value);
return result;
}, {});
}
export default async function createConfig({enableLinker, optimize}) {
return {
resolveExtensions: ['.mjs', '.js'],
// This ensures that we prioritize ES2020. RxJS would otherwise use the ESM5 output.
mainFields: ['es2020', 'es2015', 'module', 'main'],
// `tslib` sets the `module` condition to resolve to ESM.
conditions: ['es2020', 'es2015', 'module'],
supported: {
// Downlevel native `async/await` so that ZoneJS can intercept it.
'async-await': false,
},
define: optimize ? convertObjectToStringDictionary(GLOBAL_DEFS_FOR_TERSER_WITH_AOT) : undefined,
plugins: [
await createEsbuildAngularOptimizePlugin({
optimize: {
isSideEffectFree: null,
},
downlevelAsyncGeneratorsIfPresent: true,
enableLinker: enableLinker
? {
ensureNoPartialDeclaration: false,
// Only run the linker on `fesm2020/` bundles. This should not have an effect on
// the bundle output, but helps speeding up ESBuild when it visits other modules.
filterPaths: /fesm2020/,
linkerOptions: {
// DevTools relies on angular framework packages that are consumed,
// locally via bazel. These packages have a version of 0.0.0-PLACEHOLDER.
// DevTools also relies on Angular CDK and Material packages that are consumed via npm.
// Because of this, we set unknownDeclarationVersionHandling to ignore so that we bypass
// selecting a linker for our CDK and Material dependencies based on our local framework
// version (0.0.0-PLACEHOLDER).
// Instead this option defaults to the latest linker version, which should
// be correct, except for the small time interval where we rollout a new
// declaration version and target a material release that hasn't been compiled
// with that version yet.
unknownDeclarationVersionHandling: 'ignore',
},
}
: undefined,
}),
],
};
}

View file

@ -6,42 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import { createLinkerEsbuildPlugin } from '@angular/build-tooling/shared-scripts/angular-linker/esbuild-plugin.mjs';
import { createEsbuildAngularOptimizePlugin } from '@angular/build-tooling/shared-scripts/angular-optimization/esbuild-plugin.mjs';
import { GLOBAL_DEFS_FOR_TERSER_WITH_AOT } from '@angular/compiler-cli/private/tooling.js';
import baseEsbuildConfig from './esbuild-base.config.mjs';
import createConfig from './esbuild-base.config.mjs';
export default {
...baseEsbuildConfig,
...createConfig({enableLinker: true, optimize: true}),
format: 'esm',
plugins: [
// Only run the linker on `fesm2020/` bundles. This should not have an effect on
// the bundle output, but helps speeding up ESBuild when it visits other modules.
await createLinkerEsbuildPlugin(
/fesm2020/,
/* ensureNoPartialDeclaration */ false,
// DevTools relies on angular framework packages that are consumed,
// locally via bazel. These packages have a version of 0.0.0-PLACEHOLDER.
// DevTools also relies on Angular CDK and Material packages that are consumed via npm.
// Because of this, we set unknownDeclarationVersionHandling to ignore so that we bypass
// selecting a linker for our CDK and Material dependencies based on our local framework
// version (0.0.0-PLACEHOLDER).
// Instead this option defaults to the latest linker version, which should
// be correct, except for the small time interval where we rollout a new
// declaration version and target a material release that hasn't been compiled
// with that version yet.
{ unknownDeclarationVersionHandling: 'ignore' }
),
await createEsbuildAngularOptimizePlugin()
],
define: convertObjectToStringDictionary(GLOBAL_DEFS_FOR_TERSER_WITH_AOT),
};
/** Converts an object to a string dictionary. */
function convertObjectToStringDictionary(value) {
return Object.entries(value).reduce((result, [propName, value]) => {
result[propName] = String(value);
return result;
}, {});
}

View file

@ -6,30 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import {createLinkerEsbuildPlugin} from '@angular/build-tooling/shared-scripts/angular-linker/esbuild-plugin.mjs';
import baseEsbuildConfig from './esbuild-base.config.mjs';
import createConfig from './esbuild-base.config.mjs';
export default {
...baseEsbuildConfig,
...createConfig({enableLinker: true, optimize: false}),
format: 'esm',
plugins: [
// Only run the linker on `fesm2020/` bundles. This should not have an effect on
// the bundle output, but helps speeding up ESBuild when it visits other modules.
await createLinkerEsbuildPlugin(
/fesm2020/,
/* ensureNoPartialDeclaration */ false,
// DevTools relies on angular framework packages that are consumed,
// locally via bazel. These packages have a version of 0.0.0-PLACEHOLDER.
// DevTools also relies on Angular CDK and Material packages that are consumed via npm.
// Because of this, we set unknownDeclarationVersionHandling to ignore so that we bypass
// selecting a linker for our CDK and Material dependencies based on our local framework
// version (0.0.0-PLACEHOLDER).
// Instead this option defaults to the latest linker version, which should
// be correct, except for the small time interval where we rollout a new
// declaration version and target a material release that hasn't been compiled
// with that version yet.
{ unknownDeclarationVersionHandling: 'ignore' }
),
],
};

View file

@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/
import baseEsbuildConfig from './esbuild-base.config.mjs';
import createConfig from './esbuild-base.config.mjs';
export default {
...baseEsbuildConfig,
format: 'iife'
...createConfig({enableLinker: false, optimize: false}),
format: 'iife',
};

View file

@ -6,46 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/
import baseEsbuildConfig from './esbuild-base.config.mjs';
/**
* Loads and creates the ESBuild linker plugin.
*
* The plugin is not loaded at top-level as not all spec bundle targets rely
* on the linker and this would slow-down bundling.
*/
async function fetchAndCreateLinkerEsbuildPlugin() {
// Note: This needs to be a NPM module path as this ESBuild config is generated and can
// end up in arbitrary Bazel packages or differently-named consumer workspaces.
const {createLinkerEsbuildPlugin} = await import(
'@angular/build-tooling/shared-scripts/angular-linker/esbuild-plugin.mjs'
);
return await createLinkerEsbuildPlugin(
/.*/,
/* ensureNoPartialDeclaration */ true,
// DevTools relies on angular framework packages that are consumed,
// locally via bazel. These packages have a version of 0.0.0-PLACEHOLDER.
// DevTools also relies on Angular CDK and Material packages that are consumed via npm.
// Because of this, we set unknownDeclarationVersionHandling to ignore so that we bypass
// selecting a linker for our CDK and Material dependencies based on our local framework
// version (0.0.0-PLACEHOLDER).
// Instead this option defaults to the latest linker version, which should
// be correct, except for the small time interval where we rollout a new
// declaration version and target a Material release that hasn't been compiled
// with that version yet
{ unknownDeclarationVersionHandling: 'ignore' }
);
}
// Based on the Bazel action and its substitutions, we run the linker for all inputs.
const plugins = [await fetchAndCreateLinkerEsbuildPlugin()];
import createConfig from './esbuild-base.config.mjs';
export default {
...baseEsbuildConfig,
...createConfig({enableLinker: true, optimize: false}),
// Use the `iife` format for the test entry-point as tests should run immediately.
// For browser tests which are wrapped in an AMD header and footer, this works as well.
format: 'iife',
plugins,
};

View file

@ -295,7 +295,14 @@ def pkg_npm(name, validate = True, use_prodmode_output = False, **kwargs):
visibility = visibility,
)
def karma_web_test_suite(name, external = [], **kwargs):
def karma_web_test_suite(
name,
external = [],
browsers = [
"@npm//@angular/build-tooling/bazel/browsers/chromium:chromium",
"@npm//@angular/build-tooling/bazel/browsers/firefox:firefox",
],
**kwargs):
"""Default values for karma_web_test_suite"""
# Default value for bootstrap
@ -322,10 +329,7 @@ def karma_web_test_suite(name, external = [], **kwargs):
_karma_web_test_suite(
name = name,
deps = [":%s_bundle" % name],
browsers = [
"@npm//@angular/build-tooling/bazel/browsers/chromium:chromium",
"@npm//@angular/build-tooling/bazel/browsers/firefox:firefox",
],
browsers = browsers,
data = data,
tags = tags,
**kwargs