blob: 080758fc951bc45363271ff8bf976f0ab0d7b53f [file] [log] [blame]
"""Helper macros for rendering parts of an Angular application at build time"""
load("@build_bazel_rules_nodejs//:index.bzl", _nodejs_binary = "nodejs_binary", _nodejs_test = "nodejs_test")
load("@npm//@bazel/typescript:index.bzl", _ts_library = "ts_library")
def _get_output_path(route, root_at):
return root_at + "/" + route + "/index.html"
def ng_prerender(name, index, prerender_roots = [], **kwargs):
"""
Helper macro for prerendering Angular routes to index files as part of the build
The outputs of this macro are:
%name% - all the rendered roots, plus the root route /
%name%.root - an alias referencing just the root index file
%name%.%route% - an alias referencing each rendered route, with / replaced by underscores
Args:
name: Rule name for the main output genrule
index: Label for the production index.html file with which to render into
prerender_roots: A list of roots that will be prerendered as part of this macro, the root route / is always rendered
"""
renderer_lib = "%s_renderer_lib" % name
_ts_library(
name = renderer_lib,
srcs = ["//src:prerender.ts"],
deps = [
"//src/app:app_server",
"@npm//@angular/platform-server",
"@npm//zone.js",
"@npm//domino",
"@npm//reflect-metadata",
"@npm//@types/node",
],
)
bin = "%s_bin" % renderer_lib
_nodejs_binary(
name = bin,
data = [
":%s" % renderer_lib,
"@npm//@angular/platform-server",
"@npm//zone.js",
"@npm//domino",
"@npm//reflect-metadata",
],
entry_point = "//src:prerender.ts",
templated_args = ["--nobazel_run_linker"],
)
root_at = "_prerender/" + native.package_name()
# we can't output "foo/index.html" since that collides with source files and will likely cross a package boundary
# so we output "_prerender/pkg_name/route/index.html"
prerender_root_outs = [_get_output_path(route, root_at) for route in prerender_roots]
root_index = "%s/index.html" % root_at
visibility = kwargs.pop("visibility", [])
native.genrule(
name = name,
srcs = [index],
outs = [root_index] + prerender_root_outs,
cmd = "$(location :%s) --index $(location %s) --outs $(OUTS) --routes / %s" % (bin, index, " ".join(prerender_roots)),
tools = [":%s" % bin],
message = "Prerendering Angular",
visibility = visibility,
tags = kwargs.pop("tags", []),
)
# convenience "output groups" from macro
native.alias(
name = "%s.root" % name,
actual = root_index,
visibility = visibility,
)
[
native.alias(
name = "%s.%s" % (name, route.replace("/", "_")),
actual = _get_output_path(route, root_at),
visibility = visibility,
)
for route in prerender_roots
]
def ng_prerender_test(name, index, route, expected_elements = [], **kwargs):
"""
Simple smoke test for a prerendered index file, as generated by ng_prerender
Args:
name: Rule name for the test
index: Label of the index file under test
route: The route that this index file belongs to
expected_elements: An optional array of expected elements that should appear in the index file
"""
_ts_library(
name = "%s_render_spec" % name,
srcs = ["//src:prerender-spec.ts"],
deps = [
"@npm//@types/node",
],
testonly = 1,
)
_nodejs_test(
name = name,
data = [
":%s_render_spec" % name,
index,
],
templated_args = ["--index $(location %s)" % index, "--route %s" % route, "--expected %s" % (" ".join(expected_elements))],
entry_point = "//src:prerender-spec.ts",
tags = kwargs.pop("tags", []),
)