Skip to content

Commit

Permalink
Updates prerender_component() to accept JS source files.
Browse files Browse the repository at this point in the history
Refs #38, #39, #4.

This allows JS source files to be included in `prerender_component()` and related rules, both for prerendering HTML and as client side scripts. This mostly involved replacing the relevant `ts_library()` targets with `js_library()` targets to compile user code and avoid depending on it from a `ts_library()` which would require `*.d.ts` definitions that the user may not write.

I included support for `*.mjs` and `*.cjs` files, although I have had trouble getting ESM to work with rules_nodejs and `*.mjs` doesn't work for a lot of complicated reasons not related to `prerender_component()`.

Since we need to compile user code with either `ts_library()` or `js_library()`, it means that a given `prerender_component()` target can only compile *all* TypeScript or *all* JavaScript. This is an unfortunate requirement, but not also a reasonable ask of users, so I don't feel too bad for not supporting it.
  • Loading branch information
dgp1130 committed Aug 15, 2021
1 parent df68bd0 commit 76b3440
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 18 deletions.
15 changes: 15 additions & 0 deletions common/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//tools:jasmine.bzl", "jasmine_node_test")
load("//tools:publish.bzl", "publish_files")
load(":label_test.bzl", "label_test_suite")
load(":paths_test.bzl", "paths_test_suite")

publish_files(
name = "publish_files",
Expand Down Expand Up @@ -118,6 +119,20 @@ bzl_library(

label_test_suite(name = "label_test")

bzl_library(
name = "paths",
srcs = ["paths.bzl"],
visibility = ["//visibility:public"],
)

bzl_library(
name = "paths_test_lib",
srcs = ["paths_test.bzl"],
deps = [":paths"],
)

paths_test_suite(name = "paths_test")

ts_library(
name = "runfiles",
srcs = ["runfiles.ts"],
Expand Down
5 changes: 5 additions & 0 deletions common/paths.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Utilities based around file paths."""

def is_js_file(src):
"""Returns whether or not the given src path is a JavaScript file."""
return src.endswith(".js") or src.endswith(".mjs") or src.endswith(".cjs")
22 changes: 22 additions & 0 deletions common/paths_test.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Tests for `paths.bzl`."""

load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
load(":paths.bzl", "is_js_file")

def _is_js_file_impl(ctx):
env = unittest.begin(ctx)

asserts.equals(env, True, is_js_file("foo/bar/baz.js"))
asserts.equals(env, True, is_js_file("foo/bar/baz.mjs"))
asserts.equals(env, True, is_js_file("foo/bar/baz.cjs"))

asserts.equals(env, False, is_js_file("foo/bar/baz.ts"))
asserts.equals(env, False, is_js_file("foo/bar/baz.d.ts"))
asserts.equals(env, False, is_js_file("foo/bar/baz.test"))

return unittest.end(env)

_is_js_file_test = unittest.make(_is_js_file_impl)

def paths_test_suite(name):
unittest.suite(name, _is_js_file_test)
2 changes: 2 additions & 0 deletions packages/rules_prerender/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ bzl_library(
deps = [
":web_resources",
"//common:label",
"//common:paths",
],
)

Expand Down Expand Up @@ -96,6 +97,7 @@ bzl_library(
visibility = ["//:__pkg__"],
deps = [
":web_resources",
"//common:paths",
"//packages/renderer:build_vars",
],
)
Expand Down
47 changes: 34 additions & 13 deletions packages/rules_prerender/prerender_component.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Defines `prerender_component()` functionality."""

load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//common:label.bzl", "absolute")
load("//common:paths.bzl", "is_js_file")
load(":web_resources.bzl", "web_resources")

def prerender_component(
Expand Down Expand Up @@ -31,11 +33,14 @@ def prerender_component(
Args:
name: The name of this rule.
srcs: The TypeScript source files for use in prerendering.
srcs: The source files for use in prerendering. May be `*.ts` files or
`*.js`/`*.mjs`/`*.cjs`. All source files must be JavaScript, or all
source files must be TypeScript. However, mixing the two is not
allowed. `*.d.ts` files are also allowed in either case.
tsconfig: A label referencing a tsconfig.json file or `ts_config()`
target. Will be used to compile files in `srcs`.
target. Will be used to compile `*.ts` files in `srcs`.
data: See https://docs.bazel.build/versions/master/be/common-definitions.html.
lib_deps: `ts_library()` dependencies for the TypeScript source files.
lib_deps: Dependencies for the source files.
scripts: List of client-side JavaScript libraries which can be included
in the prerendered HTML.
styles: List of CSS files or `filegroup()`s of CSS files which can be
Expand Down Expand Up @@ -66,23 +71,39 @@ def prerender_component(
"""

prerender_lib = "%s_prerender" % name
ts_library(
name = prerender_lib,
srcs = srcs,
tsconfig = tsconfig,
data = data,
deps = lib_deps + ["%s_prerender" % absolute(dep) for dep in deps],
testonly = testonly,
visibility = visibility,
)
if all([src.endswith(".ts") or src.endswith(".d.ts") for src in srcs]):
ts_library(
name = prerender_lib,
srcs = srcs,
tsconfig = tsconfig,
data = data + styles,
deps = lib_deps + ["%s_prerender" % absolute(dep) for dep in deps],
testonly = testonly,
visibility = visibility,
)
elif all([is_js_file(src) or src.endswith(".d.ts") for src in srcs]):
js_library(
name = prerender_lib,
srcs = srcs + data + styles, # `data` is included in `srcs`.
deps = lib_deps + ["%s_prerender" % absolute(dep) for dep in deps],
testonly = testonly,
visibility = visibility,
)
else:
fail(" ".join("""
All sources must be TypeScript (`*.ts`) or all sources must be JavaScript
(`*.js` / `*.mjs` / `*.cjs`). It is not possible to use some JavaScript sources
and some TypeScript sources in the same component (excluding `*.d.ts` files,
which are always allowed).
""".strip().split("\n")))

native.alias(
name = "%s_prerender_for_test" % name,
actual = ":%s" % prerender_lib,
testonly = True,
)

ts_library(
js_library(
name = "%s_scripts" % name,
srcs = [],
deps = scripts + ["%s_scripts" % absolute(dep) for dep in deps],
Expand Down
12 changes: 8 additions & 4 deletions packages/rules_prerender/prerender_pages_unbundled.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Defines `prerender_pages_unbundled()` functionality."""

load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "nodejs_binary")
load("@npm//@bazel/typescript:index.bzl", "ts_library")
load("//common:label.bzl", "absolute", "file_path_of")
load(":entry_points.bzl", "script_entry_point", "style_entry_point")
Expand Down Expand Up @@ -116,7 +116,11 @@ def prerender_pages_unbundled(

# Execute the runner to generate annotated resources.
annotated = "%s_annotated" % name
js_src = ".ts".join(src.split(".ts")[:-1]) + ".js"
js_src = (
".ts".join(src.split(".ts")[:-1]) + ".js"
if src.endswith(".ts")
else src
)
prerender_resources(
name = annotated,
entry_point = file_path_of(absolute(js_src)),
Expand All @@ -136,7 +140,7 @@ def prerender_pages_unbundled(

# Generate the entry point importing all included scripts.
client_scripts = "%s_scripts" % name
script_entry = "%s.ts" % client_scripts
script_entry = "%s.js" % client_scripts
script_entry_point(
name = "%s_entry" % client_scripts,
metadata = metadata,
Expand All @@ -145,7 +149,7 @@ def prerender_pages_unbundled(
)

# Reexport all included scripts at `%{name}_scripts`.
ts_library(
js_library(
name = client_scripts,
srcs = [script_entry],
deps = [":%s" % component_scripts],
Expand Down
3 changes: 2 additions & 1 deletion packages/rules_prerender/prerender_resources.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Defines `prerender_resources()` functionality."""

load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
load("//common:paths.bzl", "is_js_file")
load("//packages/renderer:build_vars.bzl", "RENDERER_RUNTIME_DEPS")
load(":web_resources.bzl", "WebResourceInfo")

Expand Down Expand Up @@ -60,7 +61,7 @@ def prerender_resources(
visibility: See https://docs.bazel.build/versions/master/be/common-definitions.html.
"""
# Validate `entry_point`.
if "/" not in entry_point or not entry_point.endswith(".js"):
if "/" not in entry_point or not is_js_file(entry_point):
fail(("`entry_point` (%s) *must* be a workspace-relative path of the"
+ " format: \"path/to/pkg/file.js\"") % entry_point)

Expand Down

0 comments on commit 76b3440

Please sign in to comment.