From c0143cb2abdd172de1b95fd1d2c4cfc738640e28 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Thu, 12 Mar 2020 21:10:41 +0100 Subject: [PATCH] build: ng_rollup_bundle internal rule should support ngcc (#36044) The `ng_rollup_bundle` rule currently is only consumed in the Angular framework repository. This means that Angular packages are built from source, and ngcc is never needed to build rollup bundles using Ivy. Though, this rule is planned to be shared with other repositories to support common benchmark code. This means that ngcc needs to be handled as these other repositories cannot build Angular from source, but instead consume Angular through NPM (with ngcc enabling Ivy). The `ng_rollup_bundle` rule needs to dynamically prioritize `ngcc` generated main resolution fields if `--define=angular_ivy_enabled=True` is set (or with the alias: `--config=ivy`). ds PR Close #36044 --- tools/ng_rollup_bundle/ng_rollup_bundle.bzl | 7 ++++--- tools/ng_rollup_bundle/rollup.config.js | 23 +++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/tools/ng_rollup_bundle/ng_rollup_bundle.bzl b/tools/ng_rollup_bundle/ng_rollup_bundle.bzl index 30ecc22054..db5c17a265 100644 --- a/tools/ng_rollup_bundle/ng_rollup_bundle.bzl +++ b/tools/ng_rollup_bundle/ng_rollup_bundle.bzl @@ -66,7 +66,7 @@ _NG_ROLLUP_BUNDLE_DEPS_ASPECTS = [esm5_outputs_aspect, ng_rollup_module_mappings _NG_ROLLUP_BUNDLE_ATTRS = { "build_optimizer": attr.bool( doc = """Use build optimizer plugin - + Only used if sources are esm5 which depends on value of esm5_sources.""", default = True, ), @@ -82,7 +82,7 @@ _NG_ROLLUP_BUNDLE_ATTRS = { "entry_point": attr.label( doc = """The starting point of the application, passed as the `--input` flag to rollup. - If the entry JavaScript file belongs to the same package (as the BUILD file), + If the entry JavaScript file belongs to the same package (as the BUILD file), you can simply reference it by its relative name to the package directory: ``` @@ -110,7 +110,7 @@ _NG_ROLLUP_BUNDLE_ATTRS = { The rule will use the corresponding `.js` output of the ts_library rule as the entry point. - If the entry point target is a rule, it should produce a single JavaScript entry file that will be passed to the nodejs_binary rule. + If the entry point target is a rule, it should produce a single JavaScript entry file that will be passed to the nodejs_binary rule. For example: ``` @@ -274,6 +274,7 @@ def _write_rollup_config(ctx, root_dir, build_optimizer, filename = "_%s.rollup. "TMPL_workspace_name": ctx.workspace_name, "TMPL_external": ", ".join(["'%s'" % e for e in external]), "TMPL_globals": ", ".join(["'%s': '%s'" % g for g in globals]), + "TMPL_ivy_enabled": "true" if ctx.var.get("angular_ivy_enabled", None) == "True" else "false", }, ) diff --git a/tools/ng_rollup_bundle/rollup.config.js b/tools/ng_rollup_bundle/rollup.config.js index d7e1b05fe1..2b20f71eda 100644 --- a/tools/ng_rollup_bundle/rollup.config.js +++ b/tools/ng_rollup_bundle/rollup.config.js @@ -28,6 +28,7 @@ const bannerFile = TMPL_banner_file; const stampData = TMPL_stamp_data; const moduleMappings = TMPL_module_mappings; const nodeModulesRoot = 'TMPL_node_modules_root'; +const ivyEnabled = TMPL_ivy_enabled; log_verbose(`running with cwd: ${process.cwd()} @@ -38,6 +39,7 @@ log_verbose(`running with stampData: ${stampData} moduleMappings: ${JSON.stringify(moduleMappings)} nodeModulesRoot: ${nodeModulesRoot} + ivyEnabled: ${ivyEnabled} `); function fileExists(filePath) { @@ -141,18 +143,27 @@ function resolveBazel( return resolved; } +// We make mainFields match what was the default for plugin-node-resolve <4.2.0 +// when mainFields was introduced. Resolving to 'browser' or 'es2015' first breaks +// some of the benchmarks such as `//modules/benchmarks/src/expanding_rows:perf_chromium-local`. +// See https://app.circleci.com/jobs/github/angular/angular/507444 && +// https://app.circleci.com/jobs/github/angular/angular/507442 for affected tests. +const mainFields = ['module', 'main']; +const ngccMainFields = mainFields.map(f => `${f}_ivy_ngcc`); + let plugins = [ { name: 'resolveBazel', resolveId: resolveBazel, }, nodeResolve({ - // We make mainFields match what was the default for plugin-node-resolve <4.2.0 - // when mainFields was introduced. Resolving to 'browser' or 'es2015' first breaks - // some of the benchmarks such as `//modules/benchmarks/src/expanding_rows:perf_chromium-local`. - // See https://app.circleci.com/jobs/github/angular/angular/507444 && - // https://app.circleci.com/jobs/github/angular/angular/507442 for affected tests. - mainFields: ['module', 'main'], + // If Ivy is enabled, we need to make sure that the module resolution prioritizes ngcc + // processed entry-point fields. Ngcc adds special fields to `package.json` files of + // modules that have been processed. Prioritizing these fields matches the Angular CLIs + // behavior for supporting Ivy. We need to support ngcc because `ng_rollup_bundle` rule is + // shared with other repositories that consume Angular from NPM (w/ ngcc). + // https://github.com/angular/angular-cli/blob/1a1ceb609b9a87c4021cce3a6f0fc6d167cd09d2/packages/ngtools/webpack/src/angular_compiler_plugin.ts#L918-L920 + mainFields: ivyEnabled ? [...ngccMainFields, ...mainFields] : mainFields, jail: process.cwd(), customResolveOptions: {moduleDirectory: nodeModulesRoot} }),