refactor(dev-infra): ng_rollup_bundle rule should leverage `@bazel/rollup` (#37623)

Refactors the `ng_rollup_bundle` rule to a macro that relies on
the `@bazel/rollup` package. This means that the rule no longer
deals with custom ESM5 flavour output, but rather only builds
prodmode ES2015 output. This matches the common build output
in Angular projects, and optimizations done in CLI where
ES2015 is the default optimization input.

The motiviation for this change is:

* Not duplicating rollup Bazel rules. Instead leveraging the official
rollup rule.
* Not dealing with a third TS output flavor in Bazel.The ESM5 flavour has the
potential of slowing down local development (as it requires compilation replaying)
* Updating the rule to be aligned with current CLI optimizations.

This also _fixes_ a bug that surfaced in the old rollup bundle rule.
Code that is unused, is not removed properly. The new rule fixes this by
setting the `toplevel` flag. This instructs terser to remove unused
definitions at top-level. This matches the optimization applied in CLI
projects. Notably the CLI doesn't need this flag, as code is always
wrapped by Webpack. Hence, the unused code eliding runs by default.

PR Close #37623
This commit is contained in:
Paul Gschwendtner 2020-06-17 10:37:36 +02:00 committed by Misko Hevery
parent 6898eab946
commit 1601ee6f6a
30 changed files with 297 additions and 761 deletions

View File

@ -0,0 +1 @@
package(default_visibility = ["//visibility:public"])

View File

@ -0,0 +1,45 @@
"""Implementation of the expand_template rule """
def expand_template_impl(ctx):
substitutions = dict()
for k in ctx.attr.configuration_env_vars:
if k in ctx.var.keys():
substitutions["TMPL_%s" % k] = ctx.var[k]
for k in ctx.attr.substitutions:
substitutions[k] = ctx.expand_location(ctx.attr.substitutions[k], targets = ctx.attr.data)
ctx.actions.expand_template(
template = ctx.file.template,
output = ctx.outputs.output_name,
substitutions = substitutions,
)
"""Rule that can be used to substitute variables in a given template file."""
expand_template = rule(
implementation = expand_template_impl,
attrs = {
"configuration_env_vars": attr.string_list(
default = [],
doc = "Bazel configuration variables which should be exposed to the template.",
),
"output_name": attr.output(
mandatory = True,
doc = "File where the substituted template is written to.",
),
"substitutions": attr.string_dict(
mandatory = True,
doc = "Dictionary of substitutions that should be available to the template. Dictionary key represents the placeholder in the template.",
),
"data": attr.label_list(
doc = """Data dependencies for location expansion.""",
allow_files = True,
),
"template": attr.label(
mandatory = True,
allow_single_file = True,
doc = "File used as template.",
),
},
)

View File

@ -132,7 +132,7 @@ def component_benchmark(
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"], bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
port = 4200, port = 4200,
static_files = assets + styles, static_files = assets + styles,
deps = [":" + app_main + ".min_debug.es2015.js"], deps = [":" + app_main + ".min_debug.js"],
additional_root_paths = ["//dev-infra/benchmark/component_benchmark/defaults"], additional_root_paths = ["//dev-infra/benchmark/component_benchmark/defaults"],
serving_path = "/app_bundle.js", serving_path = "/app_bundle.js",
) )

View File

@ -3,7 +3,7 @@ package(default_visibility = ["//visibility:public"])
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
exports_files([ exports_files([
"rollup.config.js", "rollup.config-tmpl.js",
"terser_config.json", "terser_config.json",
]) ])

View File

@ -3,414 +3,90 @@
# Use of this source code is governed by an MIT-style license that can be # 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 # 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//: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") load("@npm_bazel_terser//:index.bzl", "terser_minified")
load("@npm_bazel_rollup//:index.bzl", "rollup_bundle")
load("//dev-infra/bazel:expand_template.bzl", "expand_template")
_NG_ROLLUP_BUNDLE_OUTPUTS = { def ng_rollup_bundle(
"bundle": "%{name}.js", name,
"sourcemap": "%{name}.js.map", entry_point,
} deps = [],
license_banner = None,
build_optimizer = True,
visibility = None,
format = "iife",
globals = {},
**kwargs):
"""Rollup with Build Optimizer on target prodmode output (ESM2015).
_NG_ROLLUP_MODULE_MAPPINGS_ATTR = "ng_rollup_module_mappings" This provides an extension of the [rollup_bundle] rule that works better for Angular apps.
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 `<script type=module>` tag in modern browsers
- `iife`: A self-executing function, suitable for inclusion as a `<script>` tag. (If you want to create a bundle for your application, you probably want to use this.)
- `umd`: Universal Module Definition, works as amd, cjs and iife all in one
- `system`: Native format of the SystemJS loader
""",
values = ["amd", "cjs", "esm", "iife", "umd", "system"],
default = "esm",
),
"global_name": attr.string(
doc = """A name given to this package when referenced as a global variable.
This name appears in the bundle module incantation at the beginning of the file,
and governs the global symbol added to the global context (e.g. `window`) as a side-
effect of loading the UMD/IIFE JS bundle.
Rollup doc: "The variable name, representing your iife/umd bundle, by which other scripts on the same page can access it."
This is passed to the `output.name` setting in Rollup.""",
),
"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"],
),
"_rollup": attr.label(
executable = True,
cfg = "host",
default = Label("//dev-infra/benchmark/ng_rollup_bundle:rollup_with_build_optimizer"),
),
"_rollup_config_tmpl": attr.label(
default = Label("//dev-infra/benchmark/ng_rollup_bundle:rollup.config.js"),
allow_single_file = True,
),
}
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
# Avoid using non-normalized paths (workspace/../other_workspace/path)
def _to_manifest_path(ctx, file):
if file.short_path.startswith("../"):
return file.short_path[3:]
else:
return ctx.workspace_name + "/" + file.short_path
# Expand entry_point into runfiles and strip the file extension
def _esm5_entry_point_path(ctx):
return _to_manifest_path(ctx, ctx.file.entry_point)[:-(len(ctx.file.entry_point.extension) + 1)]
def _no_ext(f):
return f.short_path[:-len(f.extension) - 1]
def _resolve_js_input(f, inputs):
if f.extension == "js" or f.extension == "mjs":
return f
# look for corresponding js file in inputs
no_ext = _no_ext(f)
for i in inputs:
if i.extension == "js" or i.extension == "mjs":
if _no_ext(i) == no_ext:
return i
fail("Could not find corresponding javascript entry point for %s. Add the %s.js to your deps." % (f.path, no_ext))
def _write_rollup_config(ctx, root_dir, build_optimizer, filename = "_%s.rollup.conf.js"):
"""Generate a rollup config file.
Args:
ctx: Bazel rule execution context
root_dir: root directory for module resolution
build_optimizer: whether to enable Build Optimizer plugin
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_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" %
(dep.label, k, mappings[k], v)), "deps")
mappings[k] = v
globals = {}
external = []
if ctx.attr.globals:
globals = ctx.attr.globals.items()
external = ctx.attr.globals.keys()
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_build_optimizer": "true" if build_optimizer else "false",
"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,
"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",
},
)
return config
def _filter_js_inputs(all_inputs):
all_inputs_list = all_inputs.to_list() if type(all_inputs) == type(depset()) else all_inputs
return [
f
for f in all_inputs_list
if f.path.endswith(".js") or f.path.endswith(".mjs") or f.path.endswith(".json")
]
def _run_rollup(ctx, entry_point_path, sources, config):
args = ctx.actions.args()
args.add("--config", config.path)
args.add("--input", entry_point_path)
args.add("--output.file", ctx.outputs.bundle)
args.add("--output.name", ctx.attr.global_name if ctx.attr.global_name else ctx.label.name)
args.add("--output.format", ctx.attr.format)
args.add("--output.sourcemap")
args.add("--output.sourcemapFile", ctx.outputs.sourcemap)
# We will produce errors as needed. Anything else is spammy: a well-behaved
# bazel rule prints nothing on success.
args.add("--silent")
args.add("--preserveSymlinks")
direct_inputs = [config]
# Also include files from npm fine grained deps as inputs.
# These deps are identified by the NpmPackageInfo provider.
for d in ctx.attr.deps:
if NpmPackageInfo in d:
# Note: we can't avoid calling .to_list() on sources
direct_inputs.extend(_filter_js_inputs(d[NpmPackageInfo].sources.to_list()))
if ctx.file.license_banner:
direct_inputs.append(ctx.file.license_banner)
if ctx.version_file:
direct_inputs.append(ctx.version_file)
ctx.actions.run(
progress_message = "Bundling JavaScript %s [rollup]" % ctx.outputs.bundle.short_path,
executable = ctx.executable._rollup,
inputs = depset(direct_inputs, transitive = [sources]),
outputs = [ctx.outputs.bundle, ctx.outputs.sourcemap],
arguments = [args],
)
def _ng_rollup_bundle_impl(ctx):
if ctx.attr.esm5_sources:
# Use esm5 sources and build optimzier if ctx.attr.build_optimizer is set
rollup_config = _write_rollup_config(ctx, build_optimizer = ctx.attr.build_optimizer, root_dir = "/".join([ctx.bin_dir.path, ctx.label.package, esm5_root_dir(ctx)]))
_run_rollup(ctx, _esm5_entry_point_path(ctx), flatten_esm5(ctx), rollup_config)
else:
# Use esm2015 sources and no build optimzier
rollup_config = _write_rollup_config(ctx, build_optimizer = False, root_dir = ctx.bin_dir.path)
esm2015_files_depsets = []
for dep in ctx.attr.deps:
if JSEcmaScriptModuleInfo in dep:
esm2015_files_depsets.append(dep[JSEcmaScriptModuleInfo].sources)
esm2015_files = depset(transitive = esm2015_files_depsets)
entry_point_path = _to_manifest_path(ctx, _resolve_js_input(ctx.file.entry_point, esm2015_files.to_list()))
_run_rollup(ctx, entry_point_path, esm2015_files, rollup_config)
return DefaultInfo(files = depset([ctx.outputs.bundle, ctx.outputs.sourcemap]))
_ng_rollup_bundle = rule(
implementation = _ng_rollup_bundle_impl,
attrs = _NG_ROLLUP_BUNDLE_ATTRS,
outputs = _NG_ROLLUP_BUNDLE_OUTPUTS,
)
"""
Run [Rollup] with the [Build Optimizer] plugin and use esm5 inputs.
[Rollup]: https://rollupjs.org/
[Build Optimizer]: https://www.npmjs.com/package/@angular-devkit/build-optimizer
"""
def ng_rollup_bundle(name, **kwargs):
"""Rollup with Build Optimizer on esm5 inputs.
This provides a variant of the [legacy rollup_bundle] rule that works better for Angular apps.
Runs [rollup], [terser_minified] and [brotli] to produce a number of output bundles. Runs [rollup], [terser_minified] and [brotli] to produce a number of output bundles.
es5 : "%{name}.js" es2015 : "%{name}.js"
es5 minified : "%{name}.min.js" es2015 minified : "%{name}.min.js"
es5 minified (compressed) : "%{name}.min.js.br", es2015 minified (compressed) : "%{name}.min.js.br",
es5 minified (debug) : "%{name}.min_debug.js" es2015 minified (debug) : "%{name}.min_debug.js"
es2015 : "%{name}.es2015.js"
es2015 minified : "%{name}.min.es2015.js"
es2015 minified (compressed) : "%{name}.min.js.es2015.br",
es2015 minified (debug) : "%{name}.min_debug.es2015.js"
It registers `@angular-devkit/build-optimizer` as a rollup plugin, to get It registers `@angular-devkit/build-optimizer` as a rollup plugin by default. This helps
better optimization. It also uses ESM5 format inputs, as this is what with further optimization. See https://github.com/angular/angular-cli/tree/master/packages/angular_devkit/build_optimizer.
build-optimizer is hard-coded to look for and transform.
[legacy rollup_bundle]: https://github.com/bazelbuild/rules_nodejs/blob/0.38.3/internal/rollup/rollup_bundle.bzl [rollup_bundle]: https://github.com/bazelbuild/rules_nodejs/blob/1.x/packages/rollup/src/rollup_bundle.bzl
[rollup]: https://rollupjs.org/guide/en/ [rollup]: https://rollupjs.org/guide/en/
[terser_minified]: https://bazelbuild.github.io/rules_nodejs/Terser.html [terser_minified]: https://bazelbuild.github.io/rules_nodejs/Terser.html
[brotli]: https://brotli.org/ [brotli]: https://brotli.org/
""" """
format = kwargs.pop("format", "iife")
build_optimizer = kwargs.pop("build_optimizer", True)
visibility = kwargs.pop("visibility", None)
# Common arguments for all terser_minified targets config_data = [license_banner] if license_banner else []
common_terser_args = {
# As of terser 4.3.4 license comments are preserved by default. See expand_template(
# https://github.com/terser/terser/blob/master/CHANGELOG.md. We want to name = "%s_rollup_config" % name,
# maintain the comments off behavior. We pass the --comments flag with template = "//dev-infra/benchmark/ng_rollup_bundle:rollup.config-tmpl.js",
# a regex that always evaluates to false to do this. output_name = "%s_rollup_config.js" % name,
"args": ["--comments", "/bogus_string_to_suppress_all_comments^/"], configuration_env_vars = ["angular_ivy_enabled"],
data = config_data,
substitutions = {
"TMPL_build_optimizer": "true" if build_optimizer else "false",
"TMPL_banner_file": "\"$(execpath %s)\"" % license_banner if license_banner else "undefined",
"TMPL_external": ", ".join(["'%s'" % e for e in globals.keys()]),
"TMPL_globals": ", ".join(["'%s': '%s'" % (g, g) for g in globals]),
},
visibility = visibility,
)
rollup_bundle(
name = name,
config_file = "%s_rollup_config" % name,
entry_points = {
(entry_point): name,
},
visibility = visibility,
deps = config_data + deps + [
"@npm//rollup-plugin-node-resolve",
"@npm//rollup-plugin-sourcemaps",
"@npm//rollup-plugin-commonjs",
"@npm//@angular-devkit/build-optimizer",
],
silent = True,
format = format,
sourcemap = "true",
**kwargs
)
common_terser_options = {
"visibility": visibility,
"config_file": "//dev-infra/benchmark/ng_rollup_bundle:terser_config.json", "config_file": "//dev-infra/benchmark/ng_rollup_bundle:terser_config.json",
# TODO: Enable source maps for better debugging when `@bazel/terser` pre-declares
# JS and map outputs. Tracked with: DEV-120
"sourcemap": False, "sourcemap": False,
} }
# TODO(gregmagolan): reduce this macro to just use the new @bazel/rollup rollup_bundle terser_minified(name = name + ".min", src = name + ".js", **common_terser_options)
# once esm5 inputs are no longer needed. _ng_rollup_bundle is just here for esm5 support
# and once that requirement is removed for Angular 10 then there is nothing that rule is doing
# that the new @bazel/rollup rollup_bundle rule can't do.
_ng_rollup_bundle(
name = name,
build_optimizer = build_optimizer,
format = format,
visibility = visibility,
**kwargs
)
terser_minified(name = name + ".min", src = name, visibility = visibility, **common_terser_args)
native.filegroup(name = name + ".min.js", srcs = [name + ".min"], visibility = visibility) native.filegroup(name = name + ".min.js", srcs = [name + ".min"], visibility = visibility)
terser_minified(name = name + ".min_debug", src = name, debug = True, visibility = visibility, **common_terser_args) terser_minified(name = name + ".min_debug", src = name + ".js", debug = True, **common_terser_options)
native.filegroup(name = name + ".min_debug.js", srcs = [name + ".min_debug"], visibility = visibility) native.filegroup(name = name + ".min_debug.js", srcs = [name + ".min_debug"], visibility = visibility)
npm_package_bin( npm_package_bin(
name = "_%s_brotli" % name, name = "_%s_brotli" % name,
tool = "//dev-infra/benchmark/brotli-cli", tool = "//dev-infra/benchmark/brotli-cli",
@ -422,50 +98,3 @@ def ng_rollup_bundle(name, **kwargs):
], ],
visibility = visibility, visibility = visibility,
) )
_ng_rollup_bundle(
name = name + ".es2015",
esm5_sources = False,
format = format,
visibility = visibility,
**kwargs
)
terser_minified(name = name + ".min.es2015", src = name + ".es2015", visibility = visibility, **common_terser_args)
native.filegroup(name = name + ".min.es2015.js", srcs = [name + ".min.es2015"], visibility = visibility)
terser_minified(name = name + ".min_debug.es2015", src = name + ".es2015", debug = True, visibility = visibility, **common_terser_args)
native.filegroup(name = name + ".min_debug.es2015.js", srcs = [name + ".min_debug.es2015"], visibility = visibility)
npm_package_bin(
name = "_%s_es2015_brotli" % name,
tool = "//dev-infra/benchmark/brotli-cli",
data = [name + ".min.es2015.js"],
outs = [name + ".min.es2015.js.br"],
args = [
"--output=$(execpath %s.min.es2015.js.br)" % name,
"$(execpath %s.min.es2015.js)" % name,
],
visibility = visibility,
)
def ls_rollup_bundle(name, **kwargs):
"""A variant of ng_rollup_bundle for the language-service bundle
ls_rollup_bundle uses esm5 inputs, outputs AMD and does not use the build optimizer.
"""
visibility = kwargs.pop("visibility", None)
# Note: the output file is called "umd.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.
ng_rollup_bundle(
name = name + ".umd",
build_optimizer = False,
format = "amd",
visibility = visibility,
**kwargs
)
native.alias(
name = name,
actual = name + ".umd",
visibility = visibility,
)

View File

@ -0,0 +1,89 @@
/**
* @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
*/
// Rollup configuration
// GENERATED BY Bazel
const buildOptimizer =
require('@angular-devkit/build-optimizer/src/build-optimizer/rollup-plugin.js');
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);
}
// Substitutions from the `ng_rollup_bundle` macro. We want to conditionally toggle
// build optimizer, support optional banner files, and generally respect the current
// compilation mode (i.e. Ivy or View Engine) as that affects module resolution.
const useBuildOptimizer = TMPL_build_optimizer;
const bannerFile = TMPL_banner_file;
const ivyEnabled = 'TMPL_angular_ivy_enabled' === 'True';
// `bazel_stamp_file` is a substitution that is applied by `@bazel/rollup`.
const stampDataFile = bazel_stamp_file;
log_verbose(`running with
cwd: ${process.cwd()}
useBuildOptimizer: ${useBuildOptimizer}
bannerFile: ${bannerFile}
stampDataFile: ${stampDataFile}
ivyEnabled: ${ivyEnabled}
`);
const plugins = [
nodeResolve({
// 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 ? ['module_ivy_ngcc', 'main_ivy_ngcc', 'module', 'main'] :
['module', 'main'],
}),
commonjs({ignoreGlobal: true}),
sourcemaps(),
];
if (useBuildOptimizer) {
plugins.unshift(buildOptimizer.default({
sideEffectFreeModules: [],
}));
}
module.exports = {
plugins,
external: [TMPL_external],
output: {
globals: {TMPL_globals},
banner: extractBannerIfConfigured(),
}
};
/** Extracts the top-level bundle banner if specified. */
function extractBannerIfConfigured() {
if (!bannerFile) {
return undefined;
}
let banner = fs.readFileSync(bannerFile, 'utf8');
if (stampDataFile) {
const versionTag = fs.readFileSync(stampDataFile, 'utf8')
.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);
}
}
return banner;
}

View File

@ -1,212 +0,0 @@
/**
* @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
*/
// Rollup configuration
// GENERATED BY Bazel
const buildOptimizer = require(
'npm/node_modules/@angular-devkit/build-optimizer/src/build-optimizer/rollup-plugin.js');
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 useBuildOptimzier = TMPL_build_optimizer;
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';
const ivyEnabled = TMPL_ivy_enabled;
log_verbose(`running with
cwd: ${process.cwd()}
workspaceName: ${workspaceName}
useBuildOptimzier: ${useBuildOptimzier}
rootDir: ${rootDir}
bannerFile: ${bannerFile}
stampData: ${stampData}
moduleMappings: ${JSON.stringify(moduleMappings)}
nodeModulesRoot: ${nodeModulesRoot}
ivyEnabled: ${ivyEnabled}
`);
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) {
function tryImportee(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;
}
}
// Attempt in the following order {importee}.mjs, {importee}/index.mjs,
// {importee}, {importee}.js, {importee}/index.js. If an .mjs file is
// available it should be resolved as rollup cannot handle the .js files
// generated by ts_library as they are not esm. When rolling up esm5 files
// these are re-rooted so it is not an issue.
// TODO(gregmagolan): clean this up in the future as the .mjs es2015 outputs
// along side the .js es5 outputs from ts_library creates this unusual situation for
// which we can't rely on standard node module resolution to do the right thing.
// In the future ts_library (or equivalent) should only produce a single flavor of
// output and ng_rollup_bundle should also just use the use the vanilla rollup_bundle
// rule without the need for a custom bazel resolver.
return tryImportee(`${importee}.mjs`) || tryImportee(`${importee}/index.mjs`) ||
tryImportee(importee) || tryImportee(`${importee}.js`) ||
tryImportee(`${importee}/index.js`);
}
// 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;
}
// 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({
// 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}
}),
commonjs({ignoreGlobal: true}),
sourcemaps(),
];
if (useBuildOptimzier) {
plugins = [
buildOptimizer.default({
sideEffectFreeModules: [
'.esm5/packages/core/src',
'.esm5/packages/common/src',
'.esm5/packages/compiler/src',
'.esm5/packages/platform-browser/src',
]
}),
].concat(plugins);
}
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 config = {
plugins,
external: [TMPL_external],
output: {
globals: {TMPL_globals},
banner,
}
};
module.exports = config;

View File

@ -1,12 +1,18 @@
{ {
"compress": { "output": {
"global_defs": {"ngDevMode": false, "ngI18nClosureMode": false, "ngJitMode": false}, "ecma": "es2015",
"keep_fnames": "bazel_no_debug", "comments": false,
"passes": 3, "beautify": "bazel_debug"
"pure_getters": true,
"reduce_funcs": "bazel_no_debug",
"reduce_vars": "bazel_no_debug",
"sequences": "bazel_no_debug"
}, },
"compress": {
"global_defs": {
"ngDevMode": false,
"ngI18nClosureMode": false,
"ngJitMode": false
},
"passes": 3,
"pure_getters": true
},
"toplevel": true,
"mangle": "bazel_no_debug" "mangle": "bazel_no_debug"
} }

View File

@ -32,7 +32,7 @@ ts_devserver(
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"], bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
port = 4200, port = 4200,
static_files = ["index.html"], static_files = ["index.html"],
deps = [":bundle.min_debug.es2015.js"], deps = [":bundle.min_debug.js"],
) )
benchmark_test( benchmark_test(

View File

@ -45,7 +45,7 @@ ts_devserver(
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"], bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
port = 4200, port = 4200,
static_files = ["index.html"], static_files = ["index.html"],
deps = [":bundle.min_debug.es2015.js"], deps = [":bundle.min_debug.js"],
) )
ts_devserver( ts_devserver(

View File

@ -29,7 +29,7 @@ ts_devserver(
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"], bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
port = 4200, port = 4200,
static_files = ["index.html"], static_files = ["index.html"],
deps = [":bundle.min_debug.es2015.js"], deps = [":bundle.min_debug.js"],
) )
benchmark_test( benchmark_test(

View File

@ -35,7 +35,7 @@ ts_devserver(
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"], bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
port = 4200, port = 4200,
static_files = ["index.html"], static_files = ["index.html"],
deps = [":bundle.min_debug.es2015.js"], deps = [":bundle.min_debug.js"],
) )
benchmark_test( benchmark_test(

View File

@ -29,7 +29,7 @@ ts_devserver(
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"], bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
port = 4200, port = 4200,
static_files = ["index.html"], static_files = ["index.html"],
deps = [":bundle.min_debug.es2015.js"], deps = [":bundle.min_debug.js"],
) )
benchmark_test( benchmark_test(

View File

@ -35,7 +35,7 @@ ts_devserver(
bootstrap = ["//packages/zone.js/bundles:zone.umd.js"], bootstrap = ["//packages/zone.js/bundles:zone.umd.js"],
port = 4200, port = 4200,
static_files = ["index.html"], static_files = ["index.html"],
deps = [":bundle.min_debug.es2015.js"], deps = [":bundle.min_debug.js"],
) )
benchmark_test( benchmark_test(

View File

@ -28,8 +28,8 @@ ng_rollup_bundle(
ts_devserver( ts_devserver(
name = "prodserver", name = "prodserver",
static_files = [ static_files = [
":bundle.min_debug.es2015.js", ":bundle.min_debug.js",
":bundle.min.es2015.js", ":bundle.min.js",
"//packages/zone.js/bundles:zone.umd.js", "//packages/zone.js/bundles:zone.umd.js",
"index.html", "index.html",
], ],

View File

@ -28,7 +28,7 @@
} }
// zone.js must be loaded and processed before Angular bundle gets executed // zone.js must be loaded and processed before Angular bundle gets executed
loadScript('/npm/node_modules/zone.js/bundles/zone.umd.js').then(function () { loadScript('/npm/node_modules/zone.js/bundles/zone.umd.js').then(function () {
loadScript(document.location.search.endsWith('debug') ? 'bundle.min_debug.es2015.js' : 'bundle.min.es2015.js'); loadScript(document.location.search.endsWith('debug') ? 'bundle.min_debug.js' : 'bundle.min.js');
}); });
} }
}); });

View File

@ -133,7 +133,7 @@
"puppeteer": "3.3.0", "puppeteer": "3.3.0",
"reflect-metadata": "^0.1.3", "reflect-metadata": "^0.1.3",
"requirejs": "^2.3.6", "requirejs": "^2.3.6",
"rollup": "~1.25.0", "rollup": "^2.16.1",
"rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-sourcemaps": "^0.4.2", "rollup-plugin-sourcemaps": "^0.4.2",

View File

@ -146,6 +146,8 @@ if (bannerFile) {
} }
} }
// Transform that is enabled for UMD bundle processing. It transforms existing ES2015
// prodmode output to ESM5 so that the resulting UMD bundles are using ES5 format.
const downlevelToEs5Plugin = { const downlevelToEs5Plugin = {
name: 'downlevel-to-es5', name: 'downlevel-to-es5',
transform: (code, filePath) => { transform: (code, filePath) => {
@ -158,7 +160,6 @@ const downlevelToEs5Plugin = {
importHelpers: true, importHelpers: true,
mapRoot: path.dirname(filePath), mapRoot: path.dirname(filePath),
}; };
const {outputText, sourceMapText} = ts.transpileModule(code, {compilerOptions}); const {outputText, sourceMapText} = ts.transpileModule(code, {compilerOptions});
return { return {
code: outputText, code: outputText,
@ -181,6 +182,7 @@ const plugins = [
sourcemaps(), sourcemaps(),
]; ];
// If downleveling to ES5 is enabled, set up the downlevel rollup plugin.
if (downlevelToEs5) { if (downlevelToEs5) {
plugins.push(downlevelToEs5Plugin); plugins.push(downlevelToEs5Plugin);
} }

View File

@ -1,13 +1,5 @@
{ {
"name": "example", "name": "example-with-ts-library",
"version": "0.0.0-PLACEHOLDER", "version": "0.0.0-PLACEHOLDER",
"main": "./bundles/example.umd.js",
"fesm5": "./fesm5/example.js",
"fesm2015": "./fesm2015/example.js",
"esm5": "./esm5/index.js",
"esm2015": "./esm2015/index.js",
"typings": "./index.d.ts",
"module": "./fesm5/example.js",
"es2015": "./fesm2015/example.js",
"schematics": "Custom property that should be preserved." "schematics": "Custom property that should be preserved."
} }

View File

@ -6,7 +6,7 @@ ng_module(
name = "portal", name = "portal",
srcs = glob(["*.ts"]), srcs = glob(["*.ts"]),
bundle_dts = False, bundle_dts = False,
module_name = "example/portal", module_name = "example-with-ts-library/portal",
deps = [ deps = [
"//packages/core", "//packages/core",
"@npm//@types", "@npm//@types",

View File

@ -5,5 +5,5 @@ package(default_visibility = ["//packages/bazel/test:__subpackages__"])
ts_library( ts_library(
name = "utils", name = "utils",
srcs = glob(["*.ts"]), srcs = glob(["*.ts"]),
module_name = "example/utils", module_name = "example-with-ts-library/utils",
) )

View File

@ -46,9 +46,6 @@ utils
utils/package.json utils/package.json
utils/testing.d.ts utils/testing.d.ts
utils.d.ts utils.d.ts
with-ts-library
with-ts-library/package.json
with-ts-library.d.ts
--- README.md --- --- README.md ---
Angular Angular
@ -71,8 +68,8 @@ License: MIT
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) :
typeof define === 'function' && define.amd ? define('example/portal', ['exports', '@angular/core'], factory) : typeof define === 'function' && define.amd ? define('example-with-ts-library/portal', ['exports', '@angular/core'], factory) :
(global = global || self, factory((global.example = global.example || {}, global.example.portal = {}), global.ng.core)); (global = global || self, factory((global.exampleWithTsLibrary = global.exampleWithTsLibrary || {}, global.exampleWithTsLibrary.portal = {}), global.ng.core));
}(this, (function (exports, core) { 'use strict'; }(this, (function (exports, core) { 'use strict';
/** /**
@ -120,14 +117,14 @@ License: MIT
* (c) 2010-2020 Google LLC. https://angular.io/ * (c) 2010-2020 Google LLC. https://angular.io/
* License: MIT * License: MIT
*/ */
!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example/portal",["exports","@angular/core"],o):o(((e=e||self).example=e.example||{},e.example.portal={}),e.ng.core)}(this,(function(e,o){"use strict"; !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@angular/core")):"function"==typeof define&&define.amd?define("example-with-ts-library/portal",["exports","@angular/core"],r):r(((e=e||self).exampleWithTsLibrary=e.exampleWithTsLibrary||{},e.exampleWithTsLibrary.portal={}),e.ng.core)}(this,(function(e,r){"use strict";
/** /**
* @license * @license
* Copyright Google LLC All Rights Reserved. * Copyright Google LLC All Rights Reserved.
* *
* Use of this source code is governed by an MIT-style license that can be * 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 * found in the LICENSE file at https://angular.io/license
*/var t;(t=function t(){}).decorators=[{type:o.NgModule,args:[{}]}], */var t;(t=function t(){}).decorators=[{type:r.NgModule,args:[{}]}],
/** /**
* @license * @license
* Copyright Google LLC All Rights Reserved. * Copyright Google LLC All Rights Reserved.
@ -147,8 +144,8 @@ e.PortalModule=t,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})}));
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define('example/utils', ['exports'], factory) : typeof define === 'function' && define.amd ? define('example-with-ts-library/utils', ['exports'], factory) :
(global = global || self, factory((global.example = global.example || {}, global.example.utils = {}))); (global = global || self, factory((global.exampleWithTsLibrary = global.exampleWithTsLibrary || {}, global.exampleWithTsLibrary.utils = {})));
}(this, (function (exports) { 'use strict'; }(this, (function (exports) { 'use strict';
/** /**
@ -185,7 +182,7 @@ e.PortalModule=t,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})}));
* (c) 2010-2020 Google LLC. https://angular.io/ * (c) 2010-2020 Google LLC. https://angular.io/
* License: MIT * 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-with-ts-library/utils",["exports"],t):t(((e=e||self).exampleWithTsLibrary=e.exampleWithTsLibrary||{},e.exampleWithTsLibrary.utils={}))}(this,(function(e){"use strict";
/** /**
* @license * @license
* Copyright Google LLC All Rights Reserved. * Copyright Google LLC All Rights Reserved.
@ -200,7 +197,7 @@ e.PortalModule=t,e.a=1,Object.defineProperty(e,"__esModule",{value:!0})}));
* Use of this source code is governed by an MIT-style license that can be * 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 * 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,i){e.dispatchEvent(i)},Object.defineProperty(e,"__esModule",{value:!0})}));
--- bundles/example-with-ts-library.umd.js --- --- bundles/example-with-ts-library.umd.js ---
@ -450,17 +447,15 @@ export declare const VERSION = "0.0.0";
--- package.json --- --- package.json ---
{ {
"name": "example", "name": "example-with-ts-library",
"version": "0.0.0", "version": "0.0.0",
"main": "./bundles/example.umd.js", "schematics": "Custom property that should be preserved.",
"fesm5": "./fesm5/example.js", "main": "./bundles/example-with-ts-library.umd.js",
"fesm2015": "./fesm2015/example.js", "fesm2015": "./fesm2015/example-with-ts-library.js",
"esm5": "./esm5/index.js",
"esm2015": "./esm2015/index.js", "esm2015": "./esm2015/index.js",
"typings": "./index.d.ts", "typings": "./index.d.ts",
"module": "./fesm5/example.js", "module": "./fesm2015/example-with-ts-library.js",
"es2015": "./fesm2015/example.js", "es2015": "./fesm2015/example-with-ts-library.js"
"schematics": "Custom property that should be preserved."
} }
--- portal/index.d.ts --- --- portal/index.d.ts ---
@ -478,8 +473,8 @@ export * from './portal-module';
--- portal/package.json --- --- portal/package.json ---
{ {
"name": "example/portal", "name": "example-with-ts-library/portal",
"main": "../bundles/example-portal.umd.js", "main": "../bundles/example-with-ts-library-portal.umd.js",
"fesm2015": "../fesm2015/portal.js", "fesm2015": "../fesm2015/portal.js",
"esm2015": "../esm2015/portal/portal.js", "esm2015": "../esm2015/portal/portal.js",
"typings": "./portal.d.ts", "typings": "./portal.d.ts",
@ -511,7 +506,7 @@ export * from './index';
--- portal/portal.metadata.json --- --- portal/portal.metadata.json ---
{"__symbolic":"module","version":4,"metadata":{"PortalModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":10,"character":1},"arguments":[{}]}],"members":{}},"a":1},"origins":{"PortalModule":"./portal-module","a":"./portal-module"},"importAs":"example/portal"} {"__symbolic":"module","version":4,"metadata":{"PortalModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":10,"character":1},"arguments":[{}]}],"members":{}},"a":1},"origins":{"PortalModule":"./portal-module","a":"./portal-module"},"importAs":"example-with-ts-library/portal"}
--- portal.d.ts --- --- portal.d.ts ---
@ -526,7 +521,7 @@ export * from './portal/portal';
--- portal.metadata.json --- --- portal.metadata.json ---
{"__symbolic":"module","version":3,"metadata":{},"exports":[{"from":"./portal/portal"}],"flatModuleIndexRedirect":true,"importAs":"example/portal"} {"__symbolic":"module","version":3,"metadata":{},"exports":[{"from":"./portal/portal"}],"flatModuleIndexRedirect":true,"importAs":"example-with-ts-library/portal"}
--- utils/index.d.ts --- --- utils/index.d.ts ---
@ -544,8 +539,8 @@ export * from './testing';
--- utils/package.json --- --- utils/package.json ---
{ {
"name": "example/utils", "name": "example-with-ts-library/utils",
"main": "../bundles/example-utils.umd.js", "main": "../bundles/example-with-ts-library-utils.umd.js",
"fesm2015": "../fesm2015/utils.js", "fesm2015": "../fesm2015/utils.js",
"esm2015": "../esm2015/utils/index.js", "esm2015": "../esm2015/utils/index.js",
"typings": "./index.d.ts", "typings": "./index.d.ts",
@ -575,26 +570,3 @@ export declare function dispatchFakeEvent(el: HTMLElement, ev: Event): void;
export * from './utils/index'; export * from './utils/index';
--- with-ts-library/package.json ---
{
"name": "example-with-ts-library",
"main": "./bundles/example-with-ts-library.umd.js",
"fesm2015": "./fesm2015/example-with-ts-library.js",
"esm2015": "../esm2015/index.js",
"typings": "../index.d.ts",
"module": "./fesm2015/example-with-ts-library.js",
"es2015": "./fesm2015/example-with-ts-library.js"
}
--- with-ts-library.d.ts ---
/**
* @license Angular v0.0.0
* (c) 2010-2020 Google LLC. https://angular.io/
* License: MIT
*/
export * from './index';

View File

@ -1,19 +1,19 @@
### Build ### Build
``` ```
yarn bazel build //packages/core/test/render3/perf:${BENCHMARK}_lib.min_debug.es2015.js --config=ivy yarn bazel build //packages/core/test/render3/perf:${BENCHMARK}_lib.min_debug.js --config=ivy
``` ```
### Run ### Run
``` ```
node dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.es2015.js node dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.js
``` ```
### Profile ### Profile
``` ```
node --no-turbo-inlining --inspect-brk dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.es2015.js node --no-turbo-inlining --inspect-brk dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.js
``` ```
then connect with a debugger (the `--inspect-brk` option will make sure that benchmark execution doesn't start until a debugger is connected and the code execution is manually resumed). then connect with a debugger (the `--inspect-brk` option will make sure that benchmark execution doesn't start until a debugger is connected and the code execution is manually resumed).
@ -24,7 +24,7 @@ The actual benchmark code has calls that will start (`console.profile`) and stop
``` ```
yarn add deoptigate yarn add deoptigate
yarn deoptigate dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.es2015.js yarn deoptigate dist/bin/packages/core/test/render3/perf/${BENCHMARK}_lib.min_debug.js
``` ```
### Run All ### Run All
@ -83,4 +83,4 @@ To debug
- Follow the directions in `profile_in_browser.html` - Follow the directions in `profile_in_browser.html`
OR OR
- `yarn bazel build --config=ivy //packages/core/test/render3/perf:noop_change_detection` - `yarn bazel build --config=ivy //packages/core/test/render3/perf:noop_change_detection`
- `node --inspect-brk bazel-out/darwin-fastbuild/bin/packages/core/test/render3/perf/noop_change_detection.min_debug.es2015.js` - `node --inspect-brk bazel-out/darwin-fastbuild/bin/packages/core/test/render3/perf/noop_change_detection.min_debug.js`

View File

@ -30,7 +30,7 @@ const profileTests =
// build tests // build tests
shell.exec( shell.exec(
`yarn bazel build --config=ivy ` + `yarn bazel build --config=ivy ` +
profileTests.map((name) => `//packages/core/test/render3/perf:${name}_lib.min_debug.es2015.js`) profileTests.map((name) => `//packages/core/test/render3/perf:${name}_lib.min_debug.js`)
.join(' ')); .join(' '));
// profile tests // profile tests
@ -60,8 +60,7 @@ if (readPath) {
profileTests.forEach((name) => { profileTests.forEach((name) => {
// tslint:disable-next-line:no-console // tslint:disable-next-line:no-console
console.log('----------------', name, '----------------'); console.log('----------------', name, '----------------');
const log = const log = shell.exec(`node dist/bin/packages/core/test/render3/perf/${name}_lib.min_debug.js`);
shell.exec(`node dist/bin/packages/core/test/render3/perf/${name}_lib.min_debug.es2015.js`);
if (log.code != 0) throw new Error(log); if (log.code != 0) throw new Error(log);
const matches = log.stdout.match(/: ([\d\.]+) (.s)/); const matches = log.stdout.match(/: ([\d\.]+) (.s)/);
const runTime = times[name] || (times[name] = {name: name}); const runTime = times[name] || (times[name] = {name: name});

View File

@ -2,11 +2,11 @@
<script> <script>
let BASE = location.toString().split('packages/core/test/render3/perf')[0] let BASE = location.toString().split('packages/core/test/render3/perf')[0]
let BENCHMARK = location.search.split('=')[1]; let BENCHMARK = location.search.split('=')[1];
document.writeln('<' + 'script src="' + BASE + '/dist/bin/packages/core/test/render3/perf/' + BENCHMARK + '.min_debug.es2015.js"></' + 'script>'); document.writeln('<' + 'script src="' + BASE + '/dist/bin/packages/core/test/render3/perf/' + BENCHMARK + '.min_debug.js"></' + 'script>');
</script> </script>
<body> <body>
<ol> <ol>
<li>Build the benchmark using <tt>yarn bazel build //packages/core/test/render3/perf:${BENCHMARK}.min_debug.es2015.js --config=ivy</tt></li> <li>Build the benchmark using <tt>yarn bazel build //packages/core/test/render3/perf:${BENCHMARK}.min_debug.js --config=ivy</tt></li>
<li>Open this file using the <tt>file://</tt> protocol and add <tt>?benchmark=BENCHMARK</tt> to the URL.</li> <li>Open this file using the <tt>file://</tt> protocol and add <tt>?benchmark=BENCHMARK</tt> to the URL.</li>
<li> <li>
Note: You should likely run this in an incognito browser with the "no-turbo-inlining" flag.<br /> Note: You should likely run this in an incognito browser with the "no-turbo-inlining" flag.<br />

View File

@ -1,4 +1,4 @@
load("//dev-infra/benchmark/ng_rollup_bundle:ng_rollup_bundle.bzl", "ls_rollup_bundle") load("//packages/language-service/bundles:index.bzl", "ls_rollup_bundle")
ls_rollup_bundle( ls_rollup_bundle(
name = "language-service", name = "language-service",

View File

@ -0,0 +1,25 @@
load("//dev-infra/benchmark/ng_rollup_bundle:ng_rollup_bundle.bzl", "ng_rollup_bundle")
def ls_rollup_bundle(name, **kwargs):
"""
A variant of ng_rollup_bundle for the language-service bundle that
outputs in AMD format.
"""
visibility = kwargs.pop("visibility", None)
# Note: the output file is called "umd.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.
ng_rollup_bundle(
name = name + ".umd",
build_optimizer = False,
format = "amd",
visibility = visibility,
**kwargs
)
native.alias(
name = name,
actual = name + ".umd",
visibility = visibility,
)

View File

@ -26,7 +26,7 @@ genrule(
genrule( genrule(
name = "ngsw_worker_renamed", name = "ngsw_worker_renamed",
srcs = ["//packages/service-worker/worker:ngsw_worker.es2015.js"], srcs = ["//packages/service-worker/worker:ngsw_worker.js"],
outs = ["ngsw-worker.js"], outs = ["ngsw-worker.js"],
# Remove sourcemap since this file will be served in production site # Remove sourcemap since this file will be served in production site
# See https://github.com/angular/angular/issues/23596 # See https://github.com/angular/angular/issues/23596

View File

@ -19,14 +19,14 @@ def ng_benchmark(name, bundle):
nodejs_binary( nodejs_binary(
name = name, name = name,
data = [bundle], data = [bundle],
entry_point = bundle + ".min_debug.es2015.js", entry_point = bundle + ".min_debug.js",
tags = ["local", "manual"], # run benchmarks locally and never on CI tags = ["local", "manual"], # run benchmarks locally and never on CI
) )
nodejs_binary( nodejs_binary(
name = name + "_profile", name = name + "_profile",
data = [bundle], data = [bundle],
entry_point = bundle + ".min_debug.es2015.js", entry_point = bundle + ".min_debug.js",
args = ["--node_options=--no-turbo-inlining --node_options=--inspect-brk"], args = ["--node_options=--no-turbo-inlining --node_options=--inspect-brk"],
tags = ["local", "manual"], # run benchmarks locally and never on CI tags = ["local", "manual"], # run benchmarks locally and never on CI
) )

View File

@ -2160,11 +2160,6 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/estree@*":
version "0.0.44"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.44.tgz#980cc5a29a3ef3bea6ff1f7d021047d7ea575e21"
integrity sha512-iaIVzr+w2ZJ5HkidlZ3EJM8VTZb2MJLCjw3V+505yVts0gRC4UMvjw0d1HPtGqI/HQC/KdsYtayfzl+AXY2R8g==
"@types/estree@0.0.39": "@types/estree@0.0.39":
version "0.0.39" version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
@ -2577,11 +2572,6 @@ acorn@^6.1.1, acorn@^6.4.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
acorn@^7.1.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==
add-stream@^1.0.0: add-stream@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
@ -13310,6 +13300,13 @@ rollup@2.10.9:
optionalDependencies: optionalDependencies:
fsevents "~2.1.2" fsevents "~2.1.2"
rollup@^2.16.1:
version "2.16.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.16.1.tgz#97805e88071e2c6727bd0b64904976d14495c873"
integrity sha512-UYupMcbFtoWLB6ZtL4hPZNUTlkXjJfGT33Mmhz3hYLNmRj/cOvX2B26ZxDQuEpwtLdcyyyraBGQ7EfzmMJnXXg==
optionalDependencies:
fsevents "~2.1.2"
rollup@~1.11.3: rollup@~1.11.3:
version "1.11.3" version "1.11.3"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.11.3.tgz#6f436db2a2d6b63f808bf60ad01a177643dedb81" resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.11.3.tgz#6f436db2a2d6b63f808bf60ad01a177643dedb81"
@ -13319,15 +13316,6 @@ rollup@~1.11.3:
"@types/node" "^11.13.9" "@types/node" "^11.13.9"
acorn "^6.1.1" acorn "^6.1.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==
dependencies:
"@types/estree" "*"
"@types/node" "*"
acorn "^7.1.0"
router@^1.3.1: router@^1.3.1:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/router/-/router-1.3.5.tgz#cb2f47f74fd99a77fb3bc01cc947f46b79b1790f" resolved "https://registry.yarnpkg.com/router/-/router-1.3.5.tgz#cb2f47f74fd99a77fb3bc01cc947f46b79b1790f"