From 3de72e41245988578ea86bac4aa7e862838132da Mon Sep 17 00:00:00 2001 From: Greg Magolan Date: Tue, 5 Nov 2019 14:10:30 -0800 Subject: [PATCH] revert: build: remove deps on legacy nodejs rules rollup_bundle internals (#33201) (#33604) This reverts commit 0addaab27031e9f7607e399b2e524e62402216e6. PR Close #33604 --- integration/bazel/package.json | 4 +- integration/bazel/yarn.lock | 48 +- package.json | 10 +- packages/bazel/docs/BUILD.bazel | 1 + packages/bazel/package.json | 11 +- packages/bazel/src/BUILD.bazel | 17 + packages/bazel/src/ng_package/BUILD.bazel | 24 +- packages/bazel/src/ng_package/ng_package.bzl | 338 ++----------- packages/bazel/src/ng_package/packager.ts | 29 +- .../bazel/src/ng_package/rollup.config.js | 160 ------ .../src/ng_package/terser_config.default.json | 12 - packages/bazel/src/ng_rollup_bundle.bzl | 229 +++++++++ .../test/ng_package/example_package.golden | 20 +- .../example_with_ts_library_package.golden | 26 +- .../test/bundling/cyclic_import/BUILD.bazel | 2 +- .../test/bundling/hello_world/BUILD.bazel | 2 +- packages/language-service/BUILD.bazel | 3 +- packages/language-service/bundles/BUILD.bazel | 2 +- packages/language-service/bundles/rollup.bzl | 65 +++ tools/defaults.bzl | 12 +- tools/ng_rollup_bundle/BUILD.bazel | 18 - tools/ng_rollup_bundle/ng_rollup_bundle.bzl | 457 ------------------ tools/ng_rollup_bundle/rollup.config.js | 182 ------- yarn.lock | 331 +++++++++---- 24 files changed, 671 insertions(+), 1332 deletions(-) delete mode 100644 packages/bazel/src/ng_package/rollup.config.js delete mode 100644 packages/bazel/src/ng_package/terser_config.default.json create mode 100644 packages/bazel/src/ng_rollup_bundle.bzl create mode 100644 packages/language-service/bundles/rollup.bzl delete mode 100644 tools/ng_rollup_bundle/BUILD.bazel delete mode 100644 tools/ng_rollup_bundle/ng_rollup_bundle.bzl delete mode 100644 tools/ng_rollup_bundle/rollup.config.js diff --git a/integration/bazel/package.json b/integration/bazel/package.json index 61bd473e72..b0b6bdba5a 100644 --- a/integration/bazel/package.json +++ b/integration/bazel/package.json @@ -30,11 +30,11 @@ "@bazel/typescript": "0.39.1", "@types/jasmine": "2.8.8", "http-server": "^0.11.1", - "rollup": "~1.25.0", + "rollup": "^1.21.4", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-sourcemaps": "^0.4.2", - "terser": "^4.3.9", + "terser": "4.3.1", "typescript": "3.6.4" }, "scripts": { diff --git a/integration/bazel/yarn.lock b/integration/bazel/yarn.lock index fa2f87dda6..e56a9ac556 100644 --- a/integration/bazel/yarn.lock +++ b/integration/bazel/yarn.lock @@ -63,29 +63,29 @@ "@angular/router@file:../../dist/packages-dist/router": version "9.0.0-next.14" -"@bazel/bazel-darwin_x64@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-1.0.0.tgz#8ab7ecba867130d87e3ecd6cfd5757e59ea274ab" - integrity sha512-2J8qPpUAhSsuZ1P0kMFLvAQUz8zB8mkKmGL3/8raXUnw9TblsykwAdeg3QlJwTLORn+ZqdAjOYEQIarnTpS1NA== +"@bazel/bazel-darwin_x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.28.1.tgz#415658785e1dbd6f7ab5c8f2b98c1c99c614e1d5" + integrity sha512-VDKWmplAfa4uCAbkIQ5nRn04MFQqtsPNuc2HkluJ8OIum773yC2dPR+OlLBKxrlBuKJYB27TtbOwOa6w/uK7aw== -"@bazel/bazel-linux_x64@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-1.0.0.tgz#7043cc41eaf7b1d2618766e0759d513873bb9659" - integrity sha512-/ZpOrYyDNGqUyAGPHFr4Y1kn8xCG1G4Lg2VMZtfCZzDohzoYFYs8iyQGU2/8PwldH8XX+oJT9atWqSt1EyoeAw== +"@bazel/bazel-linux_x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.28.1.tgz#f78006089e17660261088272a0e04fc886572e34" + integrity sha512-n4XfNxagYhejQD32V4XSxT/qzuH1l/2jxslbKSak66/uQ+wad8Ew9rjNb4JUin3xtrfFtzmxx2jpQkybZsRVGA== -"@bazel/bazel-win32_x64@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-1.0.0.tgz#1111e4910c155a1917162ae96fd3737d062d20dd" - integrity sha512-p5LpQ/WiijwOS+eBkdD7UewHL8JwK+8gpb4tIKqgh/a2yawgzEQPJDPBUV9ykss5t+s85BL2kEMhduuDewt/MA== +"@bazel/bazel-win32_x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.28.1.tgz#60a2819618cf7582cc35ac16c01763a5e807b414" + integrity sha512-T4xksGfKikaHS4zxnGT6r5R436mz9j2lz//L1vc5sJnaEF/1e2Gv6MLl86vfZW2Xxo6iIEi6ntSzgYxP2Blohw== "@bazel/bazel@file:../../node_modules/@bazel/bazel": - version "1.0.0" + version "0.28.1" dependencies: "@bazel/hide-bazel-files" latest optionalDependencies: - "@bazel/bazel-darwin_x64" "1.0.0" - "@bazel/bazel-linux_x64" "1.0.0" - "@bazel/bazel-win32_x64" "1.0.0" + "@bazel/bazel-darwin_x64" "0.28.1" + "@bazel/bazel-linux_x64" "0.28.1" + "@bazel/bazel-win32_x64" "0.28.1" "@bazel/hide-bazel-files@latest": version "0.38.3" @@ -2867,10 +2867,10 @@ rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.8.1: dependencies: estree-walker "^0.6.1" -rollup@~1.25.0: - version "1.25.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.25.2.tgz#739f508bd8f7ece52bb6c1fcda83466af82b7f6d" - integrity sha512-+7z6Wab/L45QCPcfpuTZKwKiB0tynj05s/+s2U3F2Bi7rOLPr9UcjUwO7/xpjlPNXA/hwnth6jBExFRGyf3tMg== +rollup@^1.21.4: + version "1.26.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.26.0.tgz#cf40fd5e1edc4d7f3d4235a0a43f1c2be1cf294b" + integrity sha512-5HljNYn9icFvXX+Oe97qY5TWvnWhKqgGT0HGeWWqFPx7w7+Anzg7dfHMtUif7YYy6QxAgynDSwK6uxbgcrVUxw== dependencies: "@types/estree" "*" "@types/node" "*" @@ -3296,10 +3296,10 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.3" -terser@^4.3.9: - version "4.3.9" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.9.tgz#e4be37f80553d02645668727777687dad26bbca8" - integrity sha512-NFGMpHjlzmyOtPL+fDw3G7+6Ueh/sz4mkaUYa4lJCxOPTNzd0Uj0aZJOmsDYoSQyfuVoWDMSWTPU3huyOm2zdA== +terser@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65" + integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg== dependencies: commander "^2.20.0" source-map "~0.6.1" diff --git a/package.json b/package.json index f17bba4b76..a288280b46 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "@bazel/jasmine": "0.39.1", "@bazel/karma": "0.39.1", "@bazel/protractor": "0.39.1", - "@bazel/terser": "0.39.1", "@bazel/typescript": "0.39.1", "@microsoft/api-extractor": "^7.3.9", "@schematics/angular": "^8.0.0-beta.15", @@ -103,9 +102,11 @@ "nodejs-websocket": "^1.7.2", "protractor": "^5.4.2", "reflect-metadata": "^0.1.3", - "rollup": "~1.25.0", - "rollup-plugin-commonjs": "^10.1.0", - "rollup-plugin-node-resolve": "^5.2.0", + "rollup": "^1.1.0", + "rollup-plugin-amd": "^3.0.0", + "rollup-plugin-commonjs": "^9.2.1", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-sourcemaps": "^0.4.2", "rxjs": "^6.5.3", "selenium-webdriver": "3.5.0", @@ -113,7 +114,6 @@ "source-map": "^0.6.1", "source-map-support": "0.5.9", "systemjs": "0.18.10", - "terser": "4.3.3", "tsickle": "0.37.0", "tslib": "^1.10.0", "tslint": "5.7.0", diff --git a/packages/bazel/docs/BUILD.bazel b/packages/bazel/docs/BUILD.bazel index 55b84494d8..2e32d61ec1 100644 --- a/packages/bazel/docs/BUILD.bazel +++ b/packages/bazel/docs/BUILD.bazel @@ -4,6 +4,7 @@ skylark_doc( name = "docs", srcs = [ "//packages/bazel/src:ng_module.bzl", + "//packages/bazel/src:ng_rollup_bundle.bzl", "//packages/bazel/src/ng_package:ng_package.bzl", ], format = "html", diff --git a/packages/bazel/package.json b/packages/bazel/package.json index 1c33305055..6cc2f7ef55 100644 --- a/packages/bazel/package.json +++ b/packages/bazel/package.json @@ -33,11 +33,10 @@ "peerDependencies": { "@angular/compiler-cli": "0.0.0-PLACEHOLDER", "@bazel/typescript": "0.*", - "typescript": ">=3.6 <3.7", - "rollup": ">=1.20.0", - "rollup-plugin-commonjs": ">=9.0.0", - "rollup-plugin-node-resolve": ">=4.2.0", - "rollup-plugin-sourcemaps": ">=0.4.0" + "typescript": ">=3.6 <3.7" + }, + "devDependencies": { + }, "repository": { "type": "git", @@ -48,4 +47,4 @@ "ng-update": { "packageGroup": "NG_UPDATE_PACKAGE_GROUP" } -} \ No newline at end of file +} diff --git a/packages/bazel/src/BUILD.bazel b/packages/bazel/src/BUILD.bazel index 7a7b73b51a..f661f8a17c 100644 --- a/packages/bazel/src/BUILD.bazel +++ b/packages/bazel/src/BUILD.bazel @@ -10,6 +10,23 @@ exports_files(glob(["*.bzl"])) load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") +nodejs_binary( + name = "rollup_with_build_optimizer", + data = [ + "@npm//@angular-devkit/build-optimizer", + "@npm//is-builtin-module", + "@npm//rollup", + "@npm//rollup-plugin-amd", + "@npm//rollup-plugin-commonjs", + "@npm//rollup-plugin-json", + "@npm//rollup-plugin-node-resolve", + "@npm//rollup-plugin-sourcemaps", + ], + entry_point = "@npm//:node_modules/rollup/bin/rollup", + install_source_map_support = False, + visibility = ["//visibility:public"], +) + filegroup( name = "empty_node_modules", srcs = [], diff --git a/packages/bazel/src/ng_package/BUILD.bazel b/packages/bazel/src/ng_package/BUILD.bazel index 6de304b664..c2e931be78 100644 --- a/packages/bazel/src/ng_package/BUILD.bazel +++ b/packages/bazel/src/ng_package/BUILD.bazel @@ -27,29 +27,9 @@ nodejs_binary( install_source_map_support = False, ) -nodejs_binary( - name = "rollup_for_ng_package", - data = [ - "@npm//rollup", - "@npm//rollup-plugin-commonjs", - "@npm//rollup-plugin-node-resolve", - "@npm//rollup-plugin-sourcemaps", - ], - entry_point = "@npm//:node_modules/rollup/dist/bin/rollup", - install_source_map_support = False, -) - -exports_files([ - "ng_package.bzl", - "rollup.config.js", - "terser_config.default.json", -]) +exports_files(["ng_package.bzl"]) filegroup( name = "package_assets", - srcs = glob(["*.bzl"]) + [ - "BUILD.bazel", - "rollup.config.js", - "terser_config.default.json", - ], + srcs = glob(["*.bzl"]) + ["BUILD.bazel"], ) diff --git a/packages/bazel/src/ng_package/ng_package.bzl b/packages/bazel/src/ng_package/ng_package.bzl index db0ba87a50..cfd7790970 100644 --- a/packages/bazel/src/ng_package/ng_package.bzl +++ b/packages/bazel/src/ng_package/ng_package.bzl @@ -13,7 +13,15 @@ It packages your library following the Angular Package Format, see the specification of this format at https://goo.gl/jB3GVv """ -load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "JSNamedModuleInfo", "NpmPackageInfo", "node_modules_aspect") +load("@build_bazel_rules_nodejs//internal/common:collect_es6_sources.bzl", "collect_es6_sources") +load("@build_bazel_rules_nodejs//:providers.bzl", "JSNamedModuleInfo", "NpmPackageInfo") +load( + "@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl", + "ROLLUP_ATTRS", + "ROLLUP_DEPS_ASPECTS", + "run_terser", + "write_rollup_config", +) load( "@build_bazel_rules_nodejs//internal/npm_package:npm_package.bzl", "NPM_PACKAGE_ATTRS", @@ -30,47 +38,6 @@ def _debug(vars, *args): print("[ng_package.bzl]", args) _DEFAULT_NG_PACKAGER = "@npm//@angular/bazel/bin:packager" -_DEFAULT_ROLLUP_CONFIG_TMPL = "@npm_angular_bazel//src/ng_package:rollup.config.js" -_DEFALUT_TERSER_CONFIG_FILE = "@npm_angular_bazel//src/ng_package:terser_config.default.json" -_DEFAULT_ROLLUP = "@npm_angular_bazel//src/ng_package:rollup_for_ng_package" -_DEFAULT_TERSER = "@npm//terser/bin:terser" - -_NG_PACKAGE_MODULE_MAPPINGS_ATTR = "ng_package_module_mappings" - -def _ng_package_module_mappings_aspect_impl(target, ctx): - mappings = dict() - for dep in ctx.rule.attr.deps: - if hasattr(dep, _NG_PACKAGE_MODULE_MAPPINGS_ATTR): - for k, v in getattr(dep, _NG_PACKAGE_MODULE_MAPPINGS_ATTR).items(): - if k in mappings and mappings[k] != v: - fail(("duplicate module mapping at %s: %s maps to both %s and %s" % - (target.label, k, mappings[k], v)), "deps") - mappings[k] = v - if ((hasattr(ctx.rule.attr, "module_name") and ctx.rule.attr.module_name) or - (hasattr(ctx.rule.attr, "module_root") and ctx.rule.attr.module_root)): - mn = ctx.rule.attr.module_name - if not mn: - mn = target.label.name - mr = target.label.package - if target.label.workspace_root: - mr = "%s/%s" % (target.label.workspace_root, mr) - if ctx.rule.attr.module_root and ctx.rule.attr.module_root != ".": - if ctx.rule.attr.module_root.endswith(".ts"): - # This is the type-checking module mapping. Strip the trailing .d.ts - # as it doesn't belong in TypeScript's path mapping. - mr = "%s/%s" % (mr, ctx.rule.attr.module_root.replace(".d.ts", "")) - else: - mr = "%s/%s" % (mr, ctx.rule.attr.module_root) - if mn in mappings and mappings[mn] != mr: - fail(("duplicate module mapping at %s: %s maps to both %s and %s" % - (target.label, mn, mappings[mn], mr)), "deps") - mappings[mn] = mr - return struct(ng_package_module_mappings = mappings) - -ng_package_module_mappings_aspect = aspect( - _ng_package_module_mappings_aspect_impl, - attr_aspects = ["deps"], -) # Convert from some-dash-case to someCamelCase def _convert_dash_case_to_camel_case(s): @@ -135,122 +102,18 @@ WELL_KNOWN_GLOBALS = {p: _global_name(p) for p in [ # TODO(gregmagolan): clean this up _DEPSET_TYPE = "depset" -def _terser(ctx, input, output): - """Runs terser on an input file. - - Args: - ctx: Bazel rule execution context - input: input file - output: output file - - Returns: - The sourcemap file - """ - - map_output = ctx.actions.declare_file(output.basename + ".map", sibling = output) - - args = ctx.actions.args() - - args.add(input.path) - args.add_all(["--output", output.path]) - - # Source mapping options are comma-packed into one argv - # see https://github.com/terser-js/terser#command-line-usage - source_map_opts = ["includeSources", "base=" + ctx.bin_dir.path] - - # This option doesn't work in the config file, only on the CLI - args.add_all(["--source-map", ",".join(source_map_opts)]) - - args.add("--comments") - - args.add_all(["--config-file", ctx.file.terser_config_file.path]) - - ctx.actions.run( - progress_message = "Optimizing JavaScript %s [terser]" % output.short_path, - executable = ctx.executable.terser, - inputs = [input, ctx.file.terser_config_file], - outputs = [output, map_output], - arguments = [args], - ) - - return map_output - -def _compute_node_modules_root(ctx): - """Computes the node_modules root from the node_modules and deps attributes. - - Args: - ctx: the skylark execution context - - Returns: - The node_modules root as a string - """ - node_modules_root = None - for d in ctx.attr.deps: - if NpmPackageInfo in d: - possible_root = "/".join(["external", d[NpmPackageInfo].workspace, "node_modules"]) - if not node_modules_root: - node_modules_root = possible_root - elif node_modules_root != possible_root: - fail("All npm dependencies need to come from a single workspace. Found '%s' and '%s'." % (node_modules_root, possible_root)) - if not node_modules_root: - # there are no fine grained deps but we still need a node_modules_root even if its empty - node_modules_root = "external/npm/node_modules" - return node_modules_root - -def _write_rollup_config(ctx, root_dir, filename = "_%s.rollup.conf.js"): - """Generate a rollup config file. - - Args: - ctx: Bazel rule execution context - root_dir: root directory for module resolution (defaults to None) - filename: output filename pattern (defaults to `_%s.rollup.conf.js`) - - Returns: - The rollup config file. See https://rollupjs.org/guide/en#configuration-files - """ - config = ctx.actions.declare_file(filename % ctx.label.name) - - mappings = dict() - all_deps = ctx.attr.deps + ctx.attr.srcs - for dep in all_deps: - if hasattr(dep, _NG_PACKAGE_MODULE_MAPPINGS_ATTR): - for k, v in getattr(dep, _NG_PACKAGE_MODULE_MAPPINGS_ATTR).items(): - if k in mappings and mappings[k] != v: - fail(("duplicate module mapping at %s: %s maps to both %s and %s" % - (dep.label, k, mappings[k], v)), "deps") - mappings[k] = v - - ctx.actions.expand_template( - output = config, - template = ctx.file.rollup_config_tmpl, - substitutions = { - "TMPL_banner_file": "\"%s\"" % ctx.file.license_banner.path if ctx.file.license_banner else "undefined", - "TMPL_module_mappings": str(mappings), - "TMPL_node_modules_root": _compute_node_modules_root(ctx), - "TMPL_root_dir": root_dir, - "TMPL_stamp_data": "\"%s\"" % ctx.version_file.path if ctx.version_file else "undefined", - "TMPL_workspace_name": ctx.workspace_name, - }, - ) - - return config - -def _run_rollup(ctx, bundle_name, rollup_config, entry_point, inputs, js_output, format, module_name = "", include_tslib = False): +def _rollup(ctx, bundle_name, rollup_config, entry_point, inputs, js_output, format = "es", module_name = "", include_tslib = False): map_output = ctx.actions.declare_file(js_output.basename + ".map", sibling = js_output) args = ctx.actions.args() args.add("--config", rollup_config) + args.add("--input", entry_point) args.add("--output.file", js_output) args.add("--output.format", format) if module_name: args.add("--output.name", _global_name(module_name)) args.add("--amd.id", module_name) - elif format == "umd" or format == "iife": - # If we're generating UMD or IIFE we need a global name. - # See https://risanb.com/posts/bundling-your-javascript-library-with-rollup/#umd-output and - # https://risanb.com/posts/bundling-your-javascript-library-with-rollup/#umd-output. - args.add("--output.name", ctx.label.name) # After updating to build_bazel_rules_nodejs 0.27.0+, rollup has been updated to v1.3.1 # which tree shakes @__PURE__ annotations and const variables which are later amended by NGCC. @@ -266,8 +129,6 @@ def _run_rollup(ctx, bundle_name, rollup_config, entry_point, inputs, js_output, # of command line args args.add("--sourcemap") - args.add("--preserveSymlinks") - globals = dict(WELL_KNOWN_GLOBALS, **ctx.attr.globals) external = globals.keys() if not include_tslib: @@ -280,8 +141,6 @@ def _run_rollup(ctx, bundle_name, rollup_config, entry_point, inputs, js_output, join_with = ",", ) - # We will produce errors as needed. Anything else is spammy: a well-behaved - # bazel rule prints nothing on success. args.add("--silent") other_inputs = [rollup_config] @@ -294,8 +153,8 @@ def _run_rollup(ctx, bundle_name, rollup_config, entry_point, inputs, js_output, mnemonic = "AngularPackageRollup", inputs = inputs.to_list() + other_inputs, outputs = [js_output, map_output], - executable = ctx.executable.rollup, - tools = [ctx.executable.rollup], + executable = ctx.executable._rollup, + tools = [ctx.executable._rollup], arguments = [args], ) return struct( @@ -332,6 +191,9 @@ def _filter_out_generated_files(files, extension, package_path = None): return depset(result) +def _esm2015_root_dir(ctx): + return ctx.label.name + ".es6" + def _filter_js_inputs(all_inputs): all_inputs_list = all_inputs.to_list() if type(all_inputs) == _DEPSET_TYPE else all_inputs return [ @@ -344,12 +206,7 @@ def _filter_js_inputs(all_inputs): def _ng_package_impl(ctx): npm_package_directory = ctx.actions.declare_directory("%s.ng_pkg" % ctx.label.name) - esm_2015_files_depsets = [] - for dep in ctx.attr.deps: - if JSEcmaScriptModuleInfo in dep: - esm_2015_files_depsets.append(dep[JSEcmaScriptModuleInfo].sources) - - esm_2015_files = _filter_out_generated_files(depset(transitive = esm_2015_files_depsets), "mjs") + esm_2015_files = _filter_out_generated_files(collect_es6_sources(ctx), "js") esm5_sources = _filter_out_generated_files(flatten_esm5(ctx), "js") # These accumulators match the directory names where the files live in the @@ -368,9 +225,7 @@ def _ng_package_impl(ctx): if f.path.endswith(".js"): esm5.append(struct(js = f, map = None)) for f in esm_2015_files.to_list(): - # tsickle generated `{module}.externs.js` file will be added to JSEcmaScriptModuleInfo sources - # by ng_module so we include both .js and .mjs sources from the JSEcmaScriptModuleInfo provider - if f.path.endswith(".js") or f.path.endswith(".mjs"): + if f.path.endswith(".js"): esm2015.append(struct(js = f, map = None)) # We infer the entry points to be: @@ -461,8 +316,10 @@ def _ng_package_impl(ctx): es2015_entry_point = "/".join([p for p in [ ctx.bin_dir.path, ctx.label.package, + _esm2015_root_dir(ctx), + ctx.label.package, entry_point, - index_file.replace(".js", ".mjs"), + index_file, ] if p]) es5_entry_point = "/".join([p for p in [ @@ -486,43 +343,23 @@ def _ng_package_impl(ctx): umd_output = ctx.outputs.umd min_output = ctx.outputs.umd_min + node_modules_files = _filter_js_inputs(ctx.files.node_modules) + # Also include files from npm fine grained deps as inputs. # These deps are identified by the NpmPackageInfo provider. - node_modules_files = [] for d in ctx.attr.deps: if NpmPackageInfo in d: node_modules_files += _filter_js_inputs(d.files) esm5_rollup_inputs = depset(node_modules_files, transitive = [esm5_sources]) - esm2015_config = _write_rollup_config(ctx, ctx.bin_dir.path, filename = "_%s.rollup_esm2015.conf.js") - esm5_config = _write_rollup_config(ctx, "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]), filename = "_%s.rollup_esm5.conf.js") + esm2015_config = write_rollup_config(ctx, [], "/".join([ctx.bin_dir.path, ctx.label.package, _esm2015_root_dir(ctx)]), filename = "_%s.rollup_esm2015.conf.js") + esm5_config = write_rollup_config(ctx, [], "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]), filename = "_%s.rollup_esm5.conf.js") - fesm2015.append( - _run_rollup( - ctx, - "fesm2015", - esm2015_config, - es2015_entry_point, - depset(node_modules_files, transitive = [esm_2015_files]), - fesm2015_output, - format = "esm", - ), - ) - - fesm5.append( - _run_rollup( - ctx, - "fesm5", - esm5_config, - es5_entry_point, - esm5_rollup_inputs, - fesm5_output, - format = "esm", - ), - ) + fesm2015.append(_rollup(ctx, "fesm2015", esm2015_config, es2015_entry_point, depset(node_modules_files, transitive = [esm_2015_files]), fesm2015_output)) + fesm5.append(_rollup(ctx, "fesm5", esm5_config, es5_entry_point, esm5_rollup_inputs, fesm5_output)) bundles.append( - _run_rollup( + _rollup( ctx, "umd", esm5_config, @@ -534,10 +371,11 @@ def _ng_package_impl(ctx): include_tslib = True, ), ) - terser_sourcemap = _terser( + terser_sourcemap = run_terser( ctx, umd_output, min_output, + config_name = entry_point.replace("/", "_"), ) bundles.append(struct(js = min_output, map = terser_sourcemap)) @@ -630,89 +468,21 @@ def _ng_package_impl(ctx): files = depset([package_dir]), )] -_NG_PACKAGE_DEPS_ASPECTS = [esm5_outputs_aspect, ng_package_module_mappings_aspect, node_modules_aspect] +DEPS_ASPECTS = [esm5_outputs_aspect] -_NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **{ - "srcs": attr.label_list( - doc = """JavaScript source files from the workspace. - These can use ES2015 syntax and ES Modules (import/export)""", - allow_files = True, - ), - "entry_point": attr.label( - doc = """The starting point of the application, passed as the `--input` flag to rollup. +# Workaround skydoc bug which assumes ROLLUP_DEPS_ASPECTS is a str type +[DEPS_ASPECTS.append(a) for a in ROLLUP_DEPS_ASPECTS] - 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: - - ``` - ng_package( - name = "bundle", - entry_point = ":main.js", - ) - ``` - - You can specify the entry point as a typescript file so long as you also include - the ts_library target in deps: - - ``` - ts_library( - name = "main", - srcs = ["main.ts"], - ) - - ng_package( - name = "bundle", - deps = [":main"] - entry_point = ":main.ts", - ) - ``` - - 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. - For example: - - ``` - filegroup( - name = "entry_file", - srcs = ["main.js"], - ) - - ng_package( - name = "bundle", - entry_point = ":entry_file", - ) - ``` - """, - mandatory = True, - allow_single_file = True, - ), - "globals": attr.string_dict( - doc = """A dict of symbols that reference external scripts. - The keys are variable names that appear in the program, - and the values are the symbol to reference at runtime in a global context (UMD bundles). - For example, a program referencing @angular/core should use ng.core - as the global reference, so Angular users should include the mapping - `"@angular/core":"ng.core"` in the globals.""", - default = {}, - ), - "license_banner": attr.label( - doc = """A .txt file passed to the `banner` config option of rollup. - The contents of the file will be copied to the top of the resulting bundles. - Note that you can replace a version placeholder in the license file, by using - the special version `0.0.0-PLACEHOLDER`. See the section on stamping in the README.""", - allow_single_file = [".txt"], - ), - "deps": attr.label_list( - doc = """Other rules that produce JavaScript outputs, such as `ts_library`.""", - aspects = _NG_PACKAGE_DEPS_ASPECTS, - ), +NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **dict(ROLLUP_ATTRS, **{ + "srcs": attr.label_list(allow_files = True), + "deps": attr.label_list(aspects = DEPS_ASPECTS), "data": attr.label_list( doc = "Additional, non-Angular files to be added to the package, e.g. global CSS assets.", allow_files = True, ), "include_devmode_srcs": attr.bool(default = False), "readme_md": attr.label(allow_single_file = [".md"]), + "globals": attr.string_dict(default = {}), "entry_point_name": attr.string( doc = "Name to use when generating bundle files for the primary entry-point.", ), @@ -721,34 +491,16 @@ _NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **{ executable = True, cfg = "host", ), - "rollup": attr.label( - default = Label(_DEFAULT_ROLLUP), + "_rollup": attr.label( + default = Label("@build_bazel_rules_nodejs//internal/rollup"), executable = True, cfg = "host", ), - "terser": attr.label( - executable = True, - cfg = "host", - default = Label(_DEFAULT_TERSER), - ), - "terser_config_file": attr.label( - doc = """A JSON file containing Terser minify() options. - -This is the file you would pass to the --config-file argument in terser's CLI. -https://github.com/terser-js/terser#minify-options documents the content of the file. - -If `config_file` isn't supplied, Bazel will use a default config file. -""", - allow_single_file = True, - # These defaults match how terser was run in the legacy built-in rollup_bundle rule. - # We keep them the same so it's easier for users to migrate. - default = Label(_DEFALUT_TERSER_CONFIG_FILE), - ), - "rollup_config_tmpl": attr.label( - default = Label(_DEFAULT_ROLLUP_CONFIG_TMPL), + "_rollup_config_tmpl": attr.label( + default = Label("@build_bazel_rules_nodejs//internal/rollup:rollup.config.js"), allow_single_file = True, ), -}) +})) # Angular wants these named after the entry_point, # eg. for //packages/core it looks like "packages/core/index.js", we want @@ -787,7 +539,7 @@ def primary_entry_point_name(name, entry_point, entry_point_name): # Fall back to the name of the ng_package rule. return name -def _ng_package_outputs(name, entry_point, entry_point_name): +def ng_package_outputs(name, entry_point, entry_point_name): """This is not a public API. This function computes the named outputs for an ng_package rule. @@ -818,8 +570,8 @@ def _ng_package_outputs(name, entry_point, entry_point_name): ng_package = rule( implementation = _ng_package_impl, - attrs = _NG_PACKAGE_ATTRS, - outputs = _ng_package_outputs, + attrs = NG_PACKAGE_ATTRS, + outputs = ng_package_outputs, ) """ ng_package produces an npm-ready package from an Angular library. diff --git a/packages/bazel/src/ng_package/packager.ts b/packages/bazel/src/ng_package/packager.ts index c4f17fb77f..97d075b6a9 100644 --- a/packages/bazel/src/ng_package/packager.ts +++ b/packages/bazel/src/ng_package/packager.ts @@ -140,28 +140,20 @@ function main(args: string[]): number { /** * Relativize the path where a file is written. - * @param file a path containing a re-rooted segment like .esm5 + * @param file a path containing a re-rooted segment like .esm5 or .es6 * @param suffix the re-rooted directory * @param outDir path where we copy the file, relative to the out */ function writeEsmFile(file: string, suffix: string, outDir: string) { - function relPath(file: string, suffix: string) { - if (suffix) { - // Note that the specified file path is always using the posix path delimiter. - const root = - suffix ? file.substr(0, file.lastIndexOf(`${suffix}/`) + suffix.length + 1) : binDir; - return path.dirname(path.relative(path.join(root, srcDir), file)); - } else { - return path.dirname(path.relative(binDir, file)); - } - } - const rel = relPath(file, suffix); + // Note that the specified file path is always using the posix path delimiter. + const root = file.substr(0, file.lastIndexOf(`${suffix}/`) + suffix.length + 1); + const rel = path.dirname(path.relative(path.join(root, srcDir), file)); if (!rel.startsWith('..')) { copyFile(file, path.join(out, outDir), rel); } } - esm2015.forEach(file => writeEsmFile(file, '', 'esm2015')); + esm2015.forEach(file => writeEsmFile(file, '.es6', 'esm2015')); esm5.forEach(file => writeEsmFile(file, '.esm5', 'esm5')); bundles.forEach(bundle => { copyFile(bundle, out, 'bundles'); }); @@ -284,22 +276,19 @@ function main(args: string[]): number { function copyFile(file: string, baseDir: string, relative = '.') { const dir = path.join(baseDir, relative); - // output file is .js if the input file is .mjs - const outFile = path.posix.join( - dir, path.basename(file.endsWith('.mjs') ? file.replace(/\.mjs$/, '.js') : file)); shx.mkdir('-p', dir); - shx.cp(file, outFile); + shx.cp(file, dir); // Double-underscore is used to escape forward slash in FESM filenames. // See ng_package.bzl: // fesm_output_filename = entry_point.replace("/", "__") // We need to unescape these. - if (outFile.indexOf('__') >= 0) { - const outputPath = path.join(dir, ...path.basename(outFile).split('__')); + if (file.indexOf('__') >= 0) { + const outputPath = path.join(dir, ...path.basename(file).split('__')); shx.mkdir('-p', path.dirname(outputPath)); shx.mv(path.join(dir, path.basename(file)), outputPath); // if we are renaming the .js file, we'll also need to update the sourceMappingURL in the file - if (outFile.endsWith('.js')) { + if (file.endsWith('.js')) { shx.chmod('+w', outputPath); shx.sed('-i', `${path.basename(file)}.map`, `${path.basename(outputPath)}.map`, outputPath); } diff --git a/packages/bazel/src/ng_package/rollup.config.js b/packages/bazel/src/ng_package/rollup.config.js deleted file mode 100644 index 66cb42e8fb..0000000000 --- a/packages/bazel/src/ng_package/rollup.config.js +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @license - * 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 - */ -// Rollup configuration -// GENERATED BY Bazel - -const nodeResolve = require('rollup-plugin-node-resolve'); -const sourcemaps = require('rollup-plugin-sourcemaps'); -const commonjs = require('rollup-plugin-commonjs'); -const path = require('path'); -const fs = require('fs'); - -function log_verbose(...m) { - // This is a template file so we use __filename to output the actual filename - if (!!process.env['VERBOSE_LOGS']) console.error(`[${path.basename(__filename)}]`, ...m); -} - -const workspaceName = 'TMPL_workspace_name'; -const rootDir = 'TMPL_root_dir'; -const bannerFile = TMPL_banner_file; -const stampData = TMPL_stamp_data; -const moduleMappings = TMPL_module_mappings; -const nodeModulesRoot = 'TMPL_node_modules_root'; - -log_verbose(`running with - cwd: ${process.cwd()} - workspaceName: ${workspaceName} - rootDir: ${rootDir} - bannerFile: ${bannerFile} - stampData: ${stampData} - moduleMappings: ${JSON.stringify(moduleMappings)} - nodeModulesRoot: ${nodeModulesRoot} -`); - -function fileExists(filePath) { - try { - return fs.statSync(filePath).isFile(); - } catch (e) { - return false; - } -} - -// This resolver mimics the TypeScript Path Mapping feature, which lets us resolve -// modules based on a mapping of short names to paths. -function resolveBazel( - importee, importer, baseDir = process.cwd(), resolve = require.resolve, root = rootDir) { - log_verbose(`resolving '${importee}' from ${importer}`); - - function resolveInRootDir(importee) { - var candidate = path.join(baseDir, root, importee); - log_verbose(`try to resolve '${importee}' at '${candidate}'`); - try { - var result = resolve(candidate); - return result; - } catch (e) { - return undefined; - } - } - - // Since mappings are always in POSIX paths, when comparing the importee to mappings - // we should normalize the importee. - // Having it normalized is also useful to determine relative paths. - const normalizedImportee = importee.replace(/\\/g, '/'); - - // If import is fully qualified then resolve it directly - if (fileExists(importee)) { - log_verbose(`resolved fully qualified '${importee}'`); - return importee; - } - - var resolved; - if (normalizedImportee.startsWith('./') || normalizedImportee.startsWith('../')) { - // relative import - if (importer) { - let importerRootRelative = path.dirname(importer); - const relative = path.relative(path.join(baseDir, root), importerRootRelative); - if (!relative.startsWith('.')) { - importerRootRelative = relative; - } - resolved = path.join(importerRootRelative, importee); - } else { - throw new Error('cannot resolve relative paths without an importer'); - } - if (resolved) resolved = resolveInRootDir(resolved); - } - - if (!resolved) { - // possible workspace import or external import if importee matches a module - // mapping - for (const k in moduleMappings) { - if (normalizedImportee == k || normalizedImportee.startsWith(k + '/')) { - // replace the root module name on a mappings match - // note that the module_root attribute is intended to be used for type-checking - // so it uses eg. "index.d.ts". At runtime, we have only index.js, so we strip the - // .d.ts suffix and let node require.resolve do its thing. - var v = moduleMappings[k].replace(/\.d\.ts$/, ''); - const mappedImportee = path.join(v, normalizedImportee.slice(k.length + 1)); - log_verbose(`module mapped '${importee}' to '${mappedImportee}'`); - resolved = resolveInRootDir(mappedImportee); - if (resolved) break; - } - } - } - - if (!resolved) { - // workspace import - const userWorkspacePath = path.relative(workspaceName, importee); - resolved = resolveInRootDir(userWorkspacePath.startsWith('..') ? importee : userWorkspacePath); - } - - if (resolved) { - log_verbose(`resolved to ${resolved}`); - } else { - log_verbose(`allowing rollup to resolve '${importee}' with node module resolution`); - } - - return resolved; -} - -let banner = ''; -if (bannerFile) { - banner = fs.readFileSync(bannerFile, {encoding: 'utf-8'}); - if (stampData) { - const versionTag = fs.readFileSync(stampData, {encoding: 'utf-8'}) - .split('\n') - .find(s => s.startsWith('BUILD_SCM_VERSION')); - // Don't assume BUILD_SCM_VERSION exists - if (versionTag) { - const version = versionTag.split(' ')[1].trim(); - banner = banner.replace(/0.0.0-PLACEHOLDER/, version); - } - } -} - -const plugins = [ - { - name: 'resolveBazel', - resolveId: resolveBazel, - }, - nodeResolve({ - mainFields: ['browser', 'es2015', 'module', 'jsnext:main', 'main'], - jail: process.cwd(), - customResolveOptions: {moduleDirectory: nodeModulesRoot} - }), - commonjs({ignoreGlobal: true}), - sourcemaps(), -]; - -const config = { - plugins, - output: { - banner, - } -}; - -module.exports = config; diff --git a/packages/bazel/src/ng_package/terser_config.default.json b/packages/bazel/src/ng_package/terser_config.default.json deleted file mode 100644 index 7fe029be71..0000000000 --- a/packages/bazel/src/ng_package/terser_config.default.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compress": { - "global_defs": {"ngDevMode": false, "ngI18nClosureMode": false}, - "keep_fnames": true, - "passes": 3, - "pure_getters": true, - "reduce_funcs": true, - "reduce_vars": true, - "sequences": true - }, - "mangle": true -} \ No newline at end of file diff --git a/packages/bazel/src/ng_rollup_bundle.bzl b/packages/bazel/src/ng_rollup_bundle.bzl new file mode 100644 index 0000000000..46f9641ead --- /dev/null +++ b/packages/bazel/src/ng_rollup_bundle.bzl @@ -0,0 +1,229 @@ +# 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 + +"""Rollup with Build Optimizer + + This provides a variant of the [rollup_bundle] rule that works better for Angular apps. + + It registers `@angular-devkit/build-optimizer` as a rollup plugin, to get + better optimization. It also uses ESM5 format inputs, as this is what + build-optimizer is hard-coded to look for and transform. + + [rollup_bundle]: https://bazelbuild.github.io/rules_nodejs/rollup/rollup_bundle.html +""" + +load( + "@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl", + "ROLLUP_ATTRS", + "ROLLUP_DEPS_ASPECTS", + "run_rollup", + "run_sourcemapexplorer", + "run_terser", + "write_rollup_config", +) +load("@build_bazel_rules_nodejs//internal/common:collect_es6_sources.bzl", collect_es2015_sources = "collect_es6_sources") +load(":esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5") + +ROLLUP_OUTPUTS = { + "build_cjs": "%{name}.cjs.js", + "build_es2015": "%{name}.es2015.js", + "build_es2015_min": "%{name}.min.es2015.js", + "build_es2015_min_debug": "%{name}.min_debug.es2015.js", + "build_es5": "%{name}.js", + "build_es5_min": "%{name}.min.js", + "build_es5_min_debug": "%{name}.min_debug.js", + "build_umd": "%{name}.umd.js", + "explore_html": "%{name}.explore.html", +} + +PACKAGES = [ + # Generated paths when using ng_rollup_bundle outside this monorepo. + "external/angular/packages/core/src", + "external/angular/packages/common/src", + "external/angular/packages/compiler/src", + "external/angular/packages/platform-browser/src", + "external/rxjs", + # Generated paths when using ng_rollup_bundle inside this monorepo. + "packages/core/src", + "packages/common/src", + "packages/compiler/src", + "packages/platform-browser/src", +] +PLUGIN_CONFIG = "{sideEffectFreeModules: [\n%s]}" % ",\n".join( + [" '.esm5/{0}'".format(p) for p in PACKAGES], +) +BO_ROLLUP = "npm/node_modules/@angular-devkit/build-optimizer/src/build-optimizer/rollup-plugin.js" +BO_PLUGIN = "require('%s').default(%s)" % (BO_ROLLUP, PLUGIN_CONFIG) + +def _use_plain_rollup(ctx): + """Determine whether to use the Angular or upstream versions of the rollup_bundle rule. + + In most modes, the Angular version of rollup is used. This runs build optimizer as part of its + processing, which affects decorators and annotations. + + In JIT modes, an emulation of the upstream rollup_bundle rule is used. This avoids running + build optimizer on code which isn't designed to be optimized by it. + + Args: + ctx: skylark rule execution context + + Returns: + true iff the Angular version of rollup with build optimizer should be used, false otherwise + """ + + if "compile" not in ctx.var: + return False + + strategy = ctx.var["compile"] + return strategy == "jit" + +def run_brotli(ctx, input, output): + """Execute the Brotli compression utility. + + Args: + ctx: Bazel's rule execution context + input: any file + output: the compressed file + """ + ctx.actions.run( + executable = ctx.executable._brotli, + inputs = [input], + outputs = [output], + arguments = ["--output=%s" % output.path, input.path], + ) + +# Borrowed from bazelbuild/rules_nodejs +def _run_tsc(ctx, input, output): + args = ctx.actions.args() + args.add("--target", "es5") + args.add("--allowJS") + args.add(input) + args.add("--outFile", output) + + ctx.actions.run( + executable = ctx.executable._tsc, + inputs = [input], + outputs = [output], + arguments = [args], + ) + +# Borrowed from bazelbuild/rules_nodejs, with the addition of brotli compression output +def _plain_rollup_bundle(ctx): + rollup_config = write_rollup_config(ctx) + run_rollup(ctx, collect_es2015_sources(ctx), rollup_config, ctx.outputs.build_es2015) + run_terser(ctx, ctx.outputs.build_es2015, ctx.outputs.build_es2015_min, config_name = ctx.label.name + "es2015_min") + run_terser(ctx, ctx.outputs.build_es2015, ctx.outputs.build_es2015_min_debug, debug = True, config_name = ctx.label.name + "es2015_min_debug") + _run_tsc(ctx, ctx.outputs.build_es2015, ctx.outputs.build_es5) + source_map = run_terser(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min) + run_terser(ctx, ctx.outputs.build_es5, ctx.outputs.build_es5_min_debug, debug = True) + umd_rollup_config = write_rollup_config(ctx, filename = "_%s_umd.rollup.conf.js", output_format = "umd") + run_rollup(ctx, collect_es2015_sources(ctx), umd_rollup_config, ctx.outputs.build_umd) + cjs_rollup_config = write_rollup_config(ctx, filename = "_%s_cjs.rollup.conf.js", output_format = "cjs") + run_rollup(ctx, collect_es2015_sources(ctx), cjs_rollup_config, ctx.outputs.build_cjs) + run_sourcemapexplorer(ctx, ctx.outputs.build_es5_min, source_map, ctx.outputs.explore_html) + + run_brotli(ctx, ctx.outputs.build_es5_min, ctx.outputs.build_es5_min_compressed) + files = [ctx.outputs.build_es5_min, source_map] + return DefaultInfo(files = depset(files), runfiles = ctx.runfiles(files)) + +def _ng_rollup_bundle(ctx): + # Escape and use the plain rollup rule if the compilation strategy requires it + if _use_plain_rollup(ctx): + return _plain_rollup_bundle(ctx) + + # We don't expect anyone to make use of this bundle yet, but it makes this rule + # compatible with rollup_bundle which allows them to be easily swapped back and + # forth. + esm2015_rollup_config = write_rollup_config(ctx, filename = "_%s.rollup_es2015.conf.js") + esm2015_rollup_sourcemap = run_rollup(ctx, collect_es2015_sources(ctx), esm2015_rollup_config, ctx.outputs.build_es2015) + + run_terser( + ctx, + ctx.outputs.build_es2015, + ctx.outputs.build_es2015_min, + config_name = ctx.label.name + "es2015_min", + comments = False, + in_source_map = esm2015_rollup_sourcemap, + ) + run_terser( + ctx, + ctx.outputs.build_es2015, + ctx.outputs.build_es2015_min_debug, + config_name = ctx.label.name + "es2015_min_debug", + debug = True, + comments = False, + ) + + esm5_sources = flatten_esm5(ctx) + + rollup_config = write_rollup_config(ctx, [BO_PLUGIN], "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)])) + rollup_sourcemap = run_rollup(ctx, esm5_sources, rollup_config, ctx.outputs.build_es5) + + sourcemap = run_terser( + ctx, + ctx.outputs.build_es5, + ctx.outputs.build_es5_min, + config_name = ctx.label.name + "es5_min", + comments = False, + in_source_map = rollup_sourcemap, + ) + run_terser( + ctx, + ctx.outputs.build_es5, + ctx.outputs.build_es5_min_debug, + config_name = ctx.label.name + "es5_min_debug", + debug = True, + comments = False, + ) + + umd_rollup_config = write_rollup_config(ctx, filename = "_%s_umd.rollup.conf.js", output_format = "umd") + run_rollup(ctx, collect_es2015_sources(ctx), umd_rollup_config, ctx.outputs.build_umd) + cjs_rollup_config = write_rollup_config(ctx, filename = "_%s_cjs.rollup.conf.js", output_format = "cjs") + run_rollup(ctx, collect_es2015_sources(ctx), cjs_rollup_config, ctx.outputs.build_cjs) + + run_brotli(ctx, ctx.outputs.build_es5_min, ctx.outputs.build_es5_min_compressed) + + run_sourcemapexplorer(ctx, ctx.outputs.build_es5_min, sourcemap, ctx.outputs.explore_html) + + return DefaultInfo(files = depset([ctx.outputs.build_es5_min, sourcemap])) + +DEPS_ASPECTS = [esm5_outputs_aspect] + +# Workaround skydoc bug which assumes ROLLUP_DEPS_ASPECTS is a str type +[DEPS_ASPECTS.append(a) for a in ROLLUP_DEPS_ASPECTS] + +ng_rollup_bundle = rule( + implementation = _ng_rollup_bundle, + attrs = dict(ROLLUP_ATTRS, **{ + "deps": attr.label_list( + doc = """Other targets that provide JavaScript files. + Typically this will be `ts_library` or `ng_module` targets.""", + aspects = DEPS_ASPECTS, + ), + "_brotli": attr.label( + executable = True, + cfg = "host", + default = Label("//tools/brotli-cli"), + ), + "_rollup": attr.label( + executable = True, + cfg = "host", + default = Label("@angular//packages/bazel/src:rollup_with_build_optimizer"), + ), + }), + outputs = dict(ROLLUP_OUTPUTS, **{ + "build_es5_min_compressed": "%{name}.min.js.br", + }), +) +""" +Run [Rollup] with the [Build Optimizer] plugin. + +This rule extends from the [rollup_bundle] rule, so attributes and outputs of +that rule are used here too. + +[Rollup]: https://rollupjs.org/ +[Build Optimizer]: https://www.npmjs.com/package/@angular-devkit/build-optimizer +[rollup_bundle]: https://bazelbuild.github.io/rules_nodejs/rollup/rollup_bundle.html +""" diff --git a/packages/bazel/test/ng_package/example_package.golden b/packages/bazel/test/ng_package/example_package.golden index d9607949bb..d19653a457 100644 --- a/packages/bazel/test/ng_package/example_package.golden +++ b/packages/bazel/test/ng_package/example_package.golden @@ -96,7 +96,7 @@ Hello typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) : typeof define === 'function' && define.amd ? define('example/secondary', ['exports', '@angular/core'], factory) : (global = global || self, factory((global.example = global.example || {}, global.example.secondary = {}), global.ng.core)); -}(this, (function (exports, core) { 'use strict'; +}(this, function (exports, core) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. @@ -329,7 +329,7 @@ Hello Object.defineProperty(exports, '__esModule', { value: true }); -}))); +})); //# sourceMappingURL=waffels-secondary.umd.js.map @@ -340,7 +340,7 @@ Hello * (c) 2010-2019 Google LLC. https://angular.io/ * License: MIT */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example/secondary",["exports","@angular/core"],t):t(((e=e||self).example=e.example||{},e.example.secondary={}),e.ng.core)}(this,(function(e,t){"use strict"; +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example/secondary",["exports","@angular/core"],t):t(((e=e||self).example=e.example||{},e.example.secondary={}),e.ng.core)}(this,function(e,t){"use strict"; /** * @license * Copyright Google Inc. All Rights Reserved. @@ -348,7 +348,7 @@ Hello * 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 */ -var o=function n(e,t,o,r){var c,f=arguments.length,l=f<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,o,r);else for(var a=e.length-1;a>=0;a--)(c=e[a])&&(l=(f<3?c(l):f>3?c(t,o,l):c(t,o))||l);return f>3&&l&&Object.defineProperty(t,o,l),l}([t.NgModule({})],(function o(){})); +var o=function(){return function o(e,t,n,r){var c,f=arguments.length,l=f<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,n,r);else for(var u=e.length-1;u>=0;u--)(c=e[u])&&(l=(f<3?c(l):f>3?c(t,n,l):c(t,n))||l);return f>3&&l&&Object.defineProperty(t,n,l),l}([t.NgModule({})],function e(){})}(); /** * @license * Copyright Google Inc. All Rights Reserved. @@ -356,7 +356,7 @@ var o=function n(e,t,o,r){var c,f=arguments.length,l=f<3?t:null===r?r=Object.get * 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 */ -e.SecondaryModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); +e.SecondaryModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})}); --- bundles/waffels.umd.js --- @@ -370,7 +370,7 @@ e.SecondaryModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) : typeof define === 'function' && define.amd ? define('example', ['exports', '@angular/core'], factory) : (global = global || self, factory(global.example = {}, global.ng.core)); -}(this, (function (exports, core) { 'use strict'; +}(this, function (exports, core) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. @@ -601,7 +601,7 @@ e.SecondaryModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); Object.defineProperty(exports, '__esModule', { value: true }); -}))); +})); //# sourceMappingURL=waffels.umd.js.map @@ -612,7 +612,7 @@ e.SecondaryModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); * (c) 2010-2019 Google LLC. https://angular.io/ * License: MIT */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example",["exports","@angular/core"],t):t((e=e||self).example={},e.ng.core)}(this,(function(e,t){"use strict"; +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example",["exports","@angular/core"],t):t((e=e||self).example={},e.ng.core)}(this,function(e,t){"use strict"; /** * @license * Copyright Google Inc. All Rights Reserved. @@ -620,14 +620,14 @@ e.SecondaryModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); * 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 */ -var o=function n(e,t,o,r){var f,c=arguments.length,l=c<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,o,r);else for(var u=e.length-1;u>=0;u--)(f=e[u])&&(l=(c<3?f(l):c>3?f(t,o,l):f(t,o))||l);return c>3&&l&&Object.defineProperty(t,o,l),l}([t.NgModule({})],(function o(){})); +var o=function(){return function o(e,t,n,r){var f,c=arguments.length,u=c<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)u=Reflect.decorate(e,t,n,r);else for(var i=e.length-1;i>=0;i--)(f=e[i])&&(u=(c<3?f(u):c>3?f(t,n,u):f(t,n))||u);return c>3&&u&&Object.defineProperty(t,n,u),u}([t.NgModule({})],function e(){})}(); /** * @license * 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 - */e.MyModule=o,Object.defineProperty(e,"__esModule",{value:!0})})); + */e.MyModule=o,Object.defineProperty(e,"__esModule",{value:!0})}); --- esm2015/example.externs.js --- diff --git a/packages/bazel/test/ng_package/example_with_ts_library_package.golden b/packages/bazel/test/ng_package/example_with_ts_library_package.golden index 03b0e39477..0528d83c51 100644 --- a/packages/bazel/test/ng_package/example_with_ts_library_package.golden +++ b/packages/bazel/test/ng_package/example_with_ts_library_package.golden @@ -84,7 +84,7 @@ License: MIT typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) : typeof define === 'function' && define.amd ? define('example/portal', ['exports', '@angular/core'], factory) : (global = global || self, factory((global.example = global.example || {}, global.example.portal = {}), global.ng.core)); -}(this, (function (exports, core) { 'use strict'; +}(this, function (exports, core) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. @@ -317,7 +317,7 @@ License: MIT Object.defineProperty(exports, '__esModule', { value: true }); -}))); +})); //# sourceMappingURL=example-with-ts-library-portal.umd.js.map @@ -328,7 +328,7 @@ License: MIT * (c) 2010-2019 Google LLC. https://angular.io/ * License: MIT */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example/portal",["exports","@angular/core"],t):t(((e=e||self).example=e.example||{},e.example.portal={}),e.ng.core)}(this,(function(e,t){"use strict"; +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example/portal",["exports","@angular/core"],t):t(((e=e||self).example=e.example||{},e.example.portal={}),e.ng.core)}(this,function(e,t){"use strict"; /** * @license * Copyright Google Inc. All Rights Reserved. @@ -336,7 +336,7 @@ License: MIT * 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 */ -var o=function r(e,t,o,n){var f,l=arguments.length,c=l<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,o):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)c=Reflect.decorate(e,t,o,n);else for(var a=e.length-1;a>=0;a--)(f=e[a])&&(c=(l<3?f(c):l>3?f(t,o,c):f(t,o))||c);return l>3&&c&&Object.defineProperty(t,o,c),c}([t.NgModule({})],(function o(){})); +var o=function(){return function o(e,t,r,n){var f,l=arguments.length,c=l<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)c=Reflect.decorate(e,t,r,n);else for(var u=e.length-1;u>=0;u--)(f=e[u])&&(c=(l<3?f(c):l>3?f(t,r,c):f(t,r))||c);return l>3&&c&&Object.defineProperty(t,r,c),c}([t.NgModule({})],function e(){})}(); /** * @license * Copyright Google Inc. All Rights Reserved. @@ -344,7 +344,7 @@ var o=function r(e,t,o,n){var f,l=arguments.length,c=l<3?t:null===n?n=Object.get * 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 */ -e.PortalModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); +e.PortalModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})}); --- bundles/example-with-ts-library-utils.umd.js --- @@ -358,7 +358,7 @@ e.PortalModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define('example/utils', ['exports'], factory) : (global = global || self, factory((global.example = global.example || {}, global.example.utils = {}))); -}(this, (function (exports) { 'use strict'; +}(this, function (exports) { 'use strict'; /** * @license @@ -383,7 +383,7 @@ e.PortalModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); Object.defineProperty(exports, '__esModule', { value: true }); -}))); +})); //# sourceMappingURL=example-with-ts-library-utils.umd.js.map @@ -394,7 +394,7 @@ e.PortalModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); * (c) 2010-2019 Google LLC. https://angular.io/ * License: MIT */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define("example/utils",["exports"],t):t(((e=e||self).example=e.example||{},e.example.utils={}))}(this,(function(e){"use strict"; +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define("example/utils",["exports"],t):t(((e=e||self).example=e.example||{},e.example.utils={}))}(this,function(e){"use strict"; /** * @license * Copyright Google Inc. All Rights Reserved. @@ -409,7 +409,7 @@ e.PortalModule=o,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})})); * 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 */ -e.dispatchFakeEvent=function t(e,n){e.dispatchEvent(n)},Object.defineProperty(e,"__esModule",{value:!0})})); +e.dispatchFakeEvent=function t(e,n){e.dispatchEvent(n)},Object.defineProperty(e,"__esModule",{value:!0})}); --- bundles/example-with-ts-library.umd.js --- @@ -423,7 +423,7 @@ e.dispatchFakeEvent=function t(e,n){e.dispatchEvent(n)},Object.defineProperty(e, typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define('example', ['exports'], factory) : (global = global || self, factory(global.example = {})); -}(this, (function (exports) { 'use strict'; +}(this, function (exports) { 'use strict'; /** * @license @@ -438,7 +438,7 @@ e.dispatchFakeEvent=function t(e,n){e.dispatchEvent(n)},Object.defineProperty(e, Object.defineProperty(exports, '__esModule', { value: true }); -}))); +})); //# sourceMappingURL=example-with-ts-library.umd.js.map @@ -449,14 +449,14 @@ e.dispatchFakeEvent=function t(e,n){e.dispatchEvent(n)},Object.defineProperty(e, * (c) 2010-2019 Google LLC. https://angular.io/ * License: MIT */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define("example",["exports"],t):t((e=e||self).example={})}(this,(function(e){"use strict"; +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define("example",["exports"],t):t((e=e||self).example={})}(this,function(e){"use strict"; /** * @license * 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 - */e.VERSION="0.0.0",Object.defineProperty(e,"__esModule",{value:!0})})); + */e.VERSION="0.0.0",Object.defineProperty(e,"__esModule",{value:!0})}); --- esm2015/example.externs.js --- diff --git a/packages/core/test/bundling/cyclic_import/BUILD.bazel b/packages/core/test/bundling/cyclic_import/BUILD.bazel index 3d285fde27..d6c5b1d228 100644 --- a/packages/core/test/bundling/cyclic_import/BUILD.bazel +++ b/packages/core/test/bundling/cyclic_import/BUILD.bazel @@ -49,8 +49,8 @@ ts_library( jasmine_node_test( name = "test", data = [ + ":bundle", ":bundle.js", - ":bundle.min.js", ":bundle.min.js.br", ":bundle.min_debug.js", ], diff --git a/packages/core/test/bundling/hello_world/BUILD.bazel b/packages/core/test/bundling/hello_world/BUILD.bazel index 488ad2d796..c22a6cf432 100644 --- a/packages/core/test/bundling/hello_world/BUILD.bazel +++ b/packages/core/test/bundling/hello_world/BUILD.bazel @@ -46,8 +46,8 @@ ts_library( jasmine_node_test( name = "test", data = [ + ":bundle", ":bundle.js", - ":bundle.min.js", ":bundle.min.js.br", ":bundle.min_debug.js", ], diff --git a/packages/language-service/BUILD.bazel b/packages/language-service/BUILD.bazel index db9d9e1229..eba37455db 100644 --- a/packages/language-service/BUILD.bazel +++ b/packages/language-service/BUILD.bazel @@ -31,7 +31,6 @@ npm_package( visibility = ["//visibility:private"], deps = [ ":language-service", - # min bundle is not used at the moment; omit from package to speed up build - "//packages/language-service/bundles:language-service.umd.js", + "//packages/language-service/bundles:language-service", ], ) diff --git a/packages/language-service/bundles/BUILD.bazel b/packages/language-service/bundles/BUILD.bazel index cfb20da7b5..7ddb1345de 100644 --- a/packages/language-service/bundles/BUILD.bazel +++ b/packages/language-service/bundles/BUILD.bazel @@ -1,4 +1,4 @@ -load("//tools/ng_rollup_bundle:ng_rollup_bundle.bzl", "ls_rollup_bundle") +load(":rollup.bzl", "ls_rollup_bundle") ls_rollup_bundle( name = "language-service", diff --git a/packages/language-service/bundles/rollup.bzl b/packages/language-service/bundles/rollup.bzl new file mode 100644 index 0000000000..73f1cc207b --- /dev/null +++ b/packages/language-service/bundles/rollup.bzl @@ -0,0 +1,65 @@ +"""Custom rollup_bundle for language service. + +Overrides format to AMD and produces only umd and min, no FESM. + +We do this so that we bundle all of the dependencies into the bundle +except for typescript, fs and path. + +This allows editors and other tools to easily use the language service bundle +without having to provide all of the angular specific peer dependencies. +""" + +load( + "@build_bazel_rules_nodejs//internal/rollup:rollup_bundle.bzl", + "ROLLUP_ATTRS", + "ROLLUP_DEPS_ASPECTS", + "run_rollup", + # "run_terser", + "write_rollup_config", +) +load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5") + +# Note: the file is called "umd.js" and "umd.min.js" because of historical +# reasons. The format is actually amd and not umd, but we are afraid to rename +# the file because that would likely break the IDE and other integrations that +# have the path hardcoded in them. +_ROLLUP_OUTPUTS = { + "build_umd": "%{name}.umd.js", + # min bundle is not used at the moment. Disable to speed up build + # "build_umd_min": "%{name}.umd.min.js", +} + +DEPS_ASPECTS = [esm5_outputs_aspect] + +# Workaround skydoc bug which assumes ROLLUP_DEPS_ASPECTS is a str type +[DEPS_ASPECTS.append(a) for a in ROLLUP_DEPS_ASPECTS] + +def _ls_rollup_bundle(ctx): + esm5_sources = flatten_esm5(ctx) + rollup_config = write_rollup_config( + ctx, + root_dir = "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]), + output_format = "amd", + ) + run_rollup(ctx, esm5_sources, rollup_config, ctx.outputs.build_umd) + + # source_map = run_terser(ctx, ctx.outputs.build_umd, ctx.outputs.build_umd_min) + return DefaultInfo( + files = depset([ + ctx.outputs.build_umd, + # ctx.outputs.build_umd_min, + # source_map, + ]), + ) + +ls_rollup_bundle = rule( + implementation = _ls_rollup_bundle, + attrs = dict(ROLLUP_ATTRS, **{ + "deps": attr.label_list( + doc = """Other targets that provide JavaScript files. + Typically this will be `ts_library` or `ng_module` targets.""", + aspects = DEPS_ASPECTS, + ), + }), + outputs = _ROLLUP_OUTPUTS, +) diff --git a/tools/defaults.bzl b/tools/defaults.bzl index f7f16fca3b..08c078de62 100644 --- a/tools/defaults.bzl +++ b/tools/defaults.bzl @@ -5,17 +5,14 @@ load("@npm_bazel_jasmine//:index.bzl", _jasmine_node_test = "jasmine_node_test") load("@npm_bazel_karma//:index.bzl", _karma_web_test = "karma_web_test", _karma_web_test_suite = "karma_web_test_suite", _ts_web_test = "ts_web_test", _ts_web_test_suite = "ts_web_test_suite") load("@npm_bazel_typescript//:index.bzl", _ts_library = "ts_library") load("//packages/bazel:index.bzl", _ng_module = "ng_module", _ng_package = "ng_package") -load("//tools/ng_rollup_bundle:ng_rollup_bundle.bzl", _ng_rollup_bundle = "ng_rollup_bundle") +load("//packages/bazel/src:ng_rollup_bundle.bzl", _ng_rollup_bundle = "ng_rollup_bundle") load("//tools:ng_benchmark.bzl", _ng_benchmark = "ng_benchmark") _DEFAULT_TSCONFIG_TEST = "//packages:tsconfig-test" _INTERNAL_NG_MODULE_API_EXTRACTOR = "//packages/bazel/src/api-extractor:api_extractor" _INTERNAL_NG_MODULE_COMPILER = "//packages/bazel/src/ngc-wrapped" _INTERNAL_NG_MODULE_XI18N = "//packages/bazel/src/ngc-wrapped:xi18n" -_INTERNAL_NG_PACKAGE_PACKAGER = "//packages/bazel/src/ng_package:packager" -_INTERNAL_NG_PACKAGE_DEFALUT_TERSER_CONFIG_FILE = "//packages/bazel/src/ng_package:terser_config.default.json" -_INTERNAL_NG_PACKAGE_DEFAULT_ROLLUP_CONFIG_TMPL = "//packages/bazel/src/ng_package:rollup.config.js" -_INTERNAL_NG_PACKAGE_DEFAULT_ROLLUP = "//packages/bazel/src/ng_package:rollup_for_ng_package" +_INTERNAL_NG_PACKAGER_PACKAGER = "//packages/bazel/src/ng_package:packager" # Packages which are versioned together on npm ANGULAR_SCOPED_PACKAGES = ["@angular/%s" % p for p in [ @@ -148,10 +145,7 @@ def ng_package(name, readme_md = None, license_banner = None, deps = [], **kwarg readme_md = readme_md, license_banner = license_banner, replacements = PKG_GROUP_REPLACEMENTS, - ng_packager = _INTERNAL_NG_PACKAGE_PACKAGER, - terser_config_file = _INTERNAL_NG_PACKAGE_DEFALUT_TERSER_CONFIG_FILE, - rollup_config_tmpl = _INTERNAL_NG_PACKAGE_DEFAULT_ROLLUP_CONFIG_TMPL, - rollup = _INTERNAL_NG_PACKAGE_DEFAULT_ROLLUP, + ng_packager = _INTERNAL_NG_PACKAGER_PACKAGER, **kwargs ) diff --git a/tools/ng_rollup_bundle/BUILD.bazel b/tools/ng_rollup_bundle/BUILD.bazel deleted file mode 100644 index c615a86bbb..0000000000 --- a/tools/ng_rollup_bundle/BUILD.bazel +++ /dev/null @@ -1,18 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") - -exports_files(["rollup.config.js"]) - -nodejs_binary( - name = "rollup_with_build_optimizer", - data = [ - "@npm//@angular-devkit/build-optimizer", - "@npm//rollup", - "@npm//rollup-plugin-commonjs", - "@npm//rollup-plugin-node-resolve", - "@npm//rollup-plugin-sourcemaps", - ], - entry_point = "@npm//:node_modules/rollup/dist/bin/rollup", - install_source_map_support = False, -) diff --git a/tools/ng_rollup_bundle/ng_rollup_bundle.bzl b/tools/ng_rollup_bundle/ng_rollup_bundle.bzl deleted file mode 100644 index 2780d5eb65..0000000000 --- a/tools/ng_rollup_bundle/ng_rollup_bundle.bzl +++ /dev/null @@ -1,457 +0,0 @@ -# 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 - -"""Rollup with Build Optimizer - - This provides a variant of the [rollup_bundle] rule that works better for Angular apps. - - It registers `@angular-devkit/build-optimizer` as a rollup plugin, to get - better optimization. It also uses ESM5 format inputs, as this is what - build-optimizer is hard-coded to look for and transform. - - [rollup_bundle]: https://bazelbuild.github.io/rules_nodejs/rollup/rollup_bundle.html -""" - -load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin") -load("@build_bazel_rules_nodejs//:providers.bzl", "JSEcmaScriptModuleInfo", "NpmPackageInfo", "node_modules_aspect") -load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "esm5_root_dir", "flatten_esm5") -load("@npm_bazel_terser//:index.bzl", "terser_minified") - -_NG_ROLLUP_BUNDLE_OUTPUTS = { - "bundle": "%{name}.js", - "sourcemap": "%{name}.js.map", -} - -_NG_ROLLUP_MODULE_MAPPINGS_ATTR = "ng_rollup_module_mappings" - -def _ng_rollup_module_mappings_aspect_impl(target, ctx): - mappings = dict() - for dep in ctx.rule.attr.deps: - if hasattr(dep, _NG_ROLLUP_MODULE_MAPPINGS_ATTR): - for k, v in getattr(dep, _NG_ROLLUP_MODULE_MAPPINGS_ATTR).items(): - if k in mappings and mappings[k] != v: - fail(("duplicate module mapping at %s: %s maps to both %s and %s" % - (target.label, k, mappings[k], v)), "deps") - mappings[k] = v - if ((hasattr(ctx.rule.attr, "module_name") and ctx.rule.attr.module_name) or - (hasattr(ctx.rule.attr, "module_root") and ctx.rule.attr.module_root)): - mn = ctx.rule.attr.module_name - if not mn: - mn = target.label.name - mr = target.label.package - if target.label.workspace_root: - mr = "%s/%s" % (target.label.workspace_root, mr) - if ctx.rule.attr.module_root and ctx.rule.attr.module_root != ".": - if ctx.rule.attr.module_root.endswith(".ts"): - # This is the type-checking module mapping. Strip the trailing .d.ts - # as it doesn't belong in TypeScript's path mapping. - mr = "%s/%s" % (mr, ctx.rule.attr.module_root.replace(".d.ts", "")) - else: - mr = "%s/%s" % (mr, ctx.rule.attr.module_root) - if mn in mappings and mappings[mn] != mr: - fail(("duplicate module mapping at %s: %s maps to both %s and %s" % - (target.label, mn, mappings[mn], mr)), "deps") - mappings[mn] = mr - return struct(ng_rollup_module_mappings = mappings) - -ng_rollup_module_mappings_aspect = aspect( - _ng_rollup_module_mappings_aspect_impl, - attr_aspects = ["deps"], -) - -_NG_ROLLUP_BUNDLE_DEPS_ASPECTS = [esm5_outputs_aspect, ng_rollup_module_mappings_aspect, node_modules_aspect] - -_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, - ), - "esm5_sources": attr.bool( - doc = """Use esm5 input sources""", - default = True, - ), - "srcs": attr.label_list( - doc = """JavaScript source files from the workspace. - These can use ES2015 syntax and ES Modules (import/export)""", - allow_files = True, - ), - "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), - you can simply reference it by its relative name to the package directory: - - ``` - ng_rollup_bundle( - name = "bundle", - entry_point = ":main.js", - ) - ``` - - You can specify the entry point as a typescript file so long as you also include - the ts_library target in deps: - - ``` - ts_library( - name = "main", - srcs = ["main.ts"], - ) - - ng_rollup_bundle( - name = "bundle", - deps = [":main"] - entry_point = ":main.ts", - ) - ``` - - 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. - For example: - - ``` - filegroup( - name = "entry_file", - srcs = ["main.js"], - ) - - ng_rollup_bundle( - name = "bundle", - entry_point = ":entry_file", - ) - ``` - """, - mandatory = True, - allow_single_file = True, - ), - "deps": attr.label_list( - doc = """Other targets that provide JavaScript files. - Typically this will be `ts_library` or `ng_module` targets.""", - aspects = _NG_ROLLUP_BUNDLE_DEPS_ASPECTS, - ), - "format": attr.string( - doc = """"Specifies the format of the generated bundle. One of the following: - -- `amd`: Asynchronous Module Definition, used with module loaders like RequireJS -- `cjs`: CommonJS, suitable for Node and other bundlers -- `esm`: Keep the bundle as an ES module file, suitable for other bundlers and inclusion as a `