Skip to content

Commit

Permalink
feat(bazel): change ng_package rule to APF v6
Browse files Browse the repository at this point in the history
Angular Package Format v6 stops bundling files in the esm5 and esm2015
directories, now that Webpack 4 can tree-shake per-file.

Adds some missing files like package.json to make packages closer to
what we publish today.

Refactor ng_package to be a type of npm_package and re-use the packaging
action from that rule.
  • Loading branch information
alexeagle committed Mar 15, 2018
1 parent d509bd6 commit 7bc9ee2
Show file tree
Hide file tree
Showing 42 changed files with 335 additions and 138 deletions.
6 changes: 3 additions & 3 deletions WORKSPACE
Expand Up @@ -2,9 +2,9 @@ workspace(name = "angular")

http_archive(
name = "build_bazel_rules_nodejs",
url = "https://github.com/bazelbuild/rules_nodejs/archive/f03c8b5df155da2a640b6775afdd4fe4aa6fec72.zip",
strip_prefix = "rules_nodejs-f03c8b5df155da2a640b6775afdd4fe4aa6fec72",
sha256 = "9d541f49af8cf60c73efb102186bfa5670ee190a088ce52638dcdf90cd9e2de6",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.3.zip",
strip_prefix = "rules_nodejs-0.5.3",
sha256 = "17a5515f59777b00cb25dbc710017a14273f825029b2ec60e0969d28914870be",
)

load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
Expand Down
6 changes: 3 additions & 3 deletions integration/bazel/WORKSPACE
Expand Up @@ -2,9 +2,9 @@ workspace(name = "bazel_integration_test")

http_archive(
name = "build_bazel_rules_nodejs",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.0.zip",
strip_prefix = "rules_nodejs-0.5.0",
sha256 = "06aabb253c3867d51724386ac5622a0a238bbd82e2c70ce1d09ee3ceac4c31d6",
url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.3.zip",
strip_prefix = "rules_nodejs-0.5.3",
sha256 = "17a5515f59777b00cb25dbc710017a14273f825029b2ec60e0969d28914870be",
)

load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
Expand Down
6 changes: 5 additions & 1 deletion packages/animations/BUILD.bazel
Expand Up @@ -18,7 +18,11 @@ ng_module(

ng_package(
name = "npm_package",
srcs = ["package.json"],
srcs = [
"package.json",
"//packages/animations/browser:package.json",
"//packages/animations/browser/testing:package.json",
],
entry_point = "packages/animations/index.js",
secondary_entry_points = [
"browser",
Expand Down
2 changes: 2 additions & 0 deletions packages/animations/browser/BUILD.bazel
@@ -1,5 +1,7 @@
package(default_visibility = ["//visibility:public"])

exports_files(["package.json"])

load("//tools:defaults.bzl", "ng_module")

ng_module(
Expand Down
2 changes: 2 additions & 0 deletions packages/animations/browser/testing/BUILD.bazel
@@ -1,5 +1,7 @@
package(default_visibility = ["//visibility:public"])

exports_files(["package.json"])

load("//tools:defaults.bzl", "ng_module")

ng_module(
Expand Down
4 changes: 2 additions & 2 deletions packages/bazel/BUILD.bazel
@@ -1,4 +1,4 @@
load("@build_bazel_rules_nodejs//:defs.bzl", "npm_package")
load("//tools:defaults.bzl", "npm_package")

genrule(
name = "workspace",
Expand All @@ -9,6 +9,7 @@ genrule(
npm_package(
name = "npm_package",
srcs = [
"BUILD.bazel",
"index.bzl",
"package.json",
"//packages/bazel/src:package_assets",
Expand All @@ -18,6 +19,5 @@ npm_package(
"//packages/bazel/": "//",
"angular/packages/bazel/": "angular/",
},
stamp_data = "//tools:stamp_data",
deps = [":workspace"],
)
3 changes: 3 additions & 0 deletions packages/bazel/package.json
Expand Up @@ -18,5 +18,8 @@
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.git"
},
"ng-update": {
"packageGroup": "NG_UPDATE_PACKAGE_GROUP"
}
}
1 change: 1 addition & 0 deletions packages/bazel/src/esm5.bzl
Expand Up @@ -77,6 +77,7 @@ def _esm5_outputs_aspect(target, ctx):
arguments = [tsconfig.path],
executable = target.typescript.replay_params.compiler,
execution_requirements = {
# TODO(alexeagle): enable worker mode for these compilations
"supports-workers": "0",
},
)
Expand Down
3 changes: 2 additions & 1 deletion packages/bazel/src/ng_module.bzl
Expand Up @@ -246,6 +246,7 @@ def _write_bundle_index(ctx):
tsconfig_file = ctx.actions.declare_file("%s.tsconfig.json" % basename)
metadata_file = ctx.actions.declare_file("%s.metadata.json" % basename)
tstyping_file = ctx.actions.declare_file("%s.d.ts" % basename)
js_file = ctx.actions.declare_file("%s.js" % basename)

tsconfig = dict(tsc_wrapped_tsconfig(ctx, ctx.files.srcs, ctx.files.srcs), **{
"angularCompilerOptions": {
Expand All @@ -271,7 +272,7 @@ def _write_bundle_index(ctx):

ctx.actions.write(tsconfig_file, json_marshal(tsconfig))

outputs = [metadata_file, tstyping_file]
outputs = [metadata_file, tstyping_file, js_file]

ctx.action(
progress_message = "Producing metadata for bundle %s" % ctx.label.name,
Expand Down
83 changes: 60 additions & 23 deletions packages/bazel/src/ng_package/ng_package.bzl
Expand Up @@ -11,6 +11,11 @@ load("@build_bazel_rules_nodejs//:internal/rollup/rollup_bundle.bzl",
"rollup_module_mappings_aspect",
"run_uglify",
"ROLLUP_ATTRS")
load("@build_bazel_rules_nodejs//:internal/npm_package/npm_package.bzl",
"NPM_PACKAGE_ATTRS",
"NPM_PACKAGE_OUTPUTS",
"create_package")
load("@build_bazel_rules_nodejs//:internal/node.bzl", "sources_aspect")
load("//packages/bazel/src:esm5.bzl", "esm5_outputs_aspect", "ESM5Info")

# TODO(alexeagle): this list is incomplete, add more as material ramps up
Expand Down Expand Up @@ -198,10 +203,10 @@ def _rollup(ctx, rollup_config, entry_point, inputs, js_output, format = "es"):
args.add(externals, join_with=",")

other_inputs = [ctx.executable._rollup, rollup_config]
if ctx.file.stamp_data:
other_inputs.append(ctx.file.stamp_data)
if ctx.file.license_banner:
other_inputs.append(ctx.file.license_banner)
if ctx.file.stamp_data:
other_inputs.append(ctx.file.stamp_data)
ctx.actions.run(
progress_message = "Angular Packaging: rolling up %s" % ctx.label.name,
mnemonic = "AngularPackageRollup",
Expand All @@ -220,12 +225,14 @@ def _rollup(ctx, rollup_config, entry_point, inputs, js_output, format = "es"):
def _flatten_paths(directory):
result = []
for f in directory:
result.extend([f.js.path, f.map.path])
result.append(f.js.path)
if f.map:
result.append(f.map.path)
return result

# ng_package produces package that is npm-ready.
def _ng_package_impl(ctx):
npm_package_directory = ctx.actions.declare_directory(ctx.label.name)
npm_package_directory = ctx.actions.declare_directory("%s.ng_pkg" % ctx.label.name)

esm_2015_files = collect_es6_sources(ctx)

Expand All @@ -248,6 +255,15 @@ def _ng_package_impl(ctx):
esm5 = []
bundles = []

# For Angular Package Format v6, we put all the individual .js files in the
# esm5/ and esm2015/ folders.
for f in esm5_sources.to_list():
if f.path.endswith(".js"):
esm5.append(struct(js = f, map = None))
for f in esm_2015_files.to_list():
if f.path.endswith(".js"):
esm2015.append(struct(js = f, map = None))

for entry_point in [""] + ctx.attr.secondary_entry_points:
es2015_entry_point = "/".join([p for p in [
ctx.bin_dir.path,
Expand Down Expand Up @@ -279,8 +295,12 @@ def _ng_package_impl(ctx):
min_output = ctx.outputs.umd_min

config = write_rollup_config(ctx, [], root_dirs)
esm2015.append(_rollup(ctx, config, es2015_entry_point, esm_2015_files, fesm2015_output))
esm5.append(_rollup(ctx, config, es5_entry_point, esm5_sources, fesm5_output))

# Currently we don't include these rollup "FESM" files in the package.
# They are only accessible as named outputs from the rule.
_rollup(ctx, config, es2015_entry_point, esm_2015_files, fesm2015_output)
_rollup(ctx, config, es5_entry_point, esm5_sources, fesm5_output)

bundles.append(_rollup(ctx, config, es5_entry_point, esm5_sources, umd_output, format = "umd"))
uglify_sourcemap = run_uglify(ctx, umd_output, min_output,
config_name = entry_point.replace("/", "_"))
Expand All @@ -294,20 +314,19 @@ def _ng_package_impl(ctx):
args.use_param_file("%s", use_always = True)
args.add(npm_package_directory.path)
args.add(ctx.label.package)
args.add(primary_entry_point_name(ctx.attr.name, ctx.attr.entry_point))
args.add(ctx.attr.secondary_entry_points, join_with=",")
args.add([ctx.bin_dir.path, ctx.label.package], join_with="/")
args.add(ctx.file.readme_md.path if ctx.file.readme_md else "")
args.add(_flatten_paths(esm2015), join_with=",")
args.add(_flatten_paths(esm5), join_with=",")
args.add(_flatten_paths(bundles), join_with=",")
args.add([s.path for s in ctx.files.srcs], join_with=",")
args.add(ctx.file.stamp_data.path if ctx.file.stamp_data else "")
args.add(ctx.file.license_banner.path if ctx.file.license_banner else "")

other_inputs = (metadata_files.to_list() +
[f.js for f in esm2015 + esm5 + bundles] +
[f.map for f in esm2015 + esm5 + bundles])
if ctx.file.stamp_data:
other_inputs.append(ctx.file.stamp_data)
[f.map for f in esm2015 + esm5 + bundles if f.map])
if ctx.file.readme_md:
other_inputs.append(ctx.file.readme_md)
if ctx.file.license_banner:
Expand All @@ -323,24 +342,32 @@ def _ng_package_impl(ctx):
ctx.files.srcs +
other_inputs,
outputs = [npm_package_directory],
executable = ctx.executable._packager,
executable = ctx.executable._ng_packager,
arguments = [args],
)

devfiles = depset()
if ctx.attr.include_devmode_srcs:
for d in ctx.attr.deps:
devfiles = depset(transitive = [devfiles, d.files, d.node_sources])

package_dir = create_package(ctx, devfiles.to_list(), [npm_package_directory])
return struct(
files = depset([npm_package_directory])
files = depset([package_dir])
)

NG_PACKAGE_ATTRS = dict(ROLLUP_ATTRS, **{
NG_PACKAGE_ATTRS = dict(NPM_PACKAGE_ATTRS, **dict(ROLLUP_ATTRS, **{
"srcs": attr.label_list(allow_files = True),
"deps": attr.label_list(aspects = [
rollup_module_mappings_aspect,
esm5_outputs_aspect,
sources_aspect,
]),
"include_devmode_srcs": attr.bool(default = False),
"readme_md": attr.label(allow_single_file = FileType([".md"])),
"globals": attr.string_dict(default={}),
"secondary_entry_points": attr.string_list(),
"_packager": attr.label(
"_ng_packager": attr.label(
default=Label("//packages/bazel/src/ng_package:packager"),
executable=True, cfg="host"),
"_rollup": attr.label(
Expand All @@ -352,22 +379,32 @@ NG_PACKAGE_ATTRS = dict(ROLLUP_ATTRS, **{
"_uglify": attr.label(
default=Label("@build_bazel_rules_nodejs//internal/rollup:uglify"),
executable=True, cfg="host"),
})
}))

# Angular wants these named after the entry_point,
# eg. for //packages/core it looks like "packages/core/index.js", we want
# core.js produced by this rule.
# Currently we just borrow the entry point for this, if it looks like
# some/path/to/my/package/index.js
# we assume the files should be named "package.*.js"
def primary_entry_point_name(name, entry_point):
return entry_point.split("/")[-2] if entry_point.find("/") >=0 else name

def ng_package_outputs(name, entry_point):
# Angular wants these named after the entry_point,
# eg. for //packages/core it looks like "packages/core/index.js", we want
# core.js produced by this rule.
# Currently we just borrow the entry point for this, if it looks like
# some/path/to/my/package/index.js
# we assume the files should be named "package.*.js"
basename = entry_point.split("/")[-2] if entry_point.find("/") >=0 else name
return {
basename = primary_entry_point_name(name, entry_point)
outputs = {
"fesm5": "fesm5/%s.js" % basename,
"fesm2015": "fesm2015/%s.js" % basename,
"umd": "%s.umd.js" % basename,
"umd_min": "%s.umd.min.js" % basename,
}
for key in NPM_PACKAGE_OUTPUTS:
# NPM_PACKAGE_OUTPUTS is a "normal" dict-valued outputs so it looks like
# "pack": "%{name}.pack",
# But this is a function-valued outputs.
# Bazel won't replace the %{name} token so we have to do it.
outputs[key] = NPM_PACKAGE_OUTPUTS[key].replace("%{name}", name)
return outputs

ng_package = rule(
implementation = _ng_package_impl,
Expand Down

0 comments on commit 7bc9ee2

Please sign in to comment.