Skip to content

Commit baa9aa8

Browse files
authored
feat: document the escape hatch from ts_library (#1247)
1 parent bccbcee commit baa9aa8

6 files changed

Lines changed: 108 additions & 21 deletions

File tree

examples/app/BUILD.bazel

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
load("@build_bazel_rules_nodejs//internal/web_package:web_package.bzl", "web_package")
22
load("@npm//http-server:index.bzl", "http_server")
3+
load("@npm//typescript:index.bzl", "tsc")
34
load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite")
45
load("@npm_bazel_rollup//:index.bzl", "rollup_bundle")
56
load("@npm_bazel_terser//:index.bzl", "terser_minified")
6-
load("@npm_bazel_typescript//:index.bzl", "ts_config", "ts_devserver", "ts_library")
7+
load("@npm_bazel_typescript//:index.bzl", "ts_devserver", "ts_library")
78

89
package(default_visibility = ["//visibility:public"])
910

@@ -46,20 +47,28 @@ http_server(
4647
templated_args = ["package"],
4748
)
4849

49-
ts_config(
50-
name = "tsconfig-test",
51-
src = "tsconfig-test.json",
52-
deps = [":tsconfig.json"],
53-
)
54-
55-
ts_library(
50+
# we could use ts_library here, but we use plain typescript to demonstrate that it works
51+
tsc(
5652
name = "e2e",
5753
testonly = 1,
58-
srcs = ["app.e2e-spec.ts"],
59-
tsconfig = ":tsconfig-test",
60-
deps = [
54+
# Remember that Bazel requires it know what outputs are created ahead of time
55+
# so that it can construct a dependency graph.
56+
outs = [
57+
"app.e2e-spec.js",
58+
],
59+
args = [
60+
"-p",
61+
"$(location tsconfig-test.json)",
62+
"--outDir",
63+
# $@ is a shorthand for the dist/bin directory where Bazel requires we write outputs
64+
"$@",
65+
],
66+
data = [
67+
"app.e2e-spec.ts",
68+
"tsconfig.json",
69+
"tsconfig-test.json",
6170
"@npm//@types/jasmine",
62-
"@npm//jasmine",
71+
"@npm//@types/node",
6372
"@npm//protractor",
6473
],
6574
)

examples/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"rollup": "1.20.3",
1212
"stylus": "^0.54.7",
1313
"terser": "4.3.1",
14-
"typescript": "2.7.x"
14+
"typescript": "3.6.3"
1515
},
1616
"scripts": {
1717
"test": "bazel test ..."

examples/app/tsconfig-test.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33

44
"compilerOptions": {
55
"types": ["jasmine", "node"]
6-
}
6+
},
7+
"include": ["*-spec.ts"]
78
}

examples/app/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,10 +1339,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
13391339
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
13401340
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
13411341

1342-
typescript@2.7.x:
1343-
version "2.7.2"
1344-
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836"
1345-
integrity sha512-p5TCYZDAO0m4G344hD+wx/LATebLWZNkkh2asWUFqSsD2OrDNhbAHuSjobrmsUmdzjJjEeZVU9g1h3O6vpstnw==
1342+
typescript@3.6.3:
1343+
version "3.6.3"
1344+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.3.tgz#fea942fabb20f7e1ca7164ff626f1a9f3f70b4da"
1345+
integrity sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==
13461346

13471347
union@~0.4.3:
13481348
version "0.4.6"

internal/node/npm_package_bin.bzl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ _ATTRS = {
2020
# because the output_dir is a tree artifact
2121
# so we weren't able to give it a label
2222
def _expand_location(ctx, s):
23-
s = s.replace("$@", "/".join([ctx.bin_dir.path, ctx.label.package, ctx.attr.name]))
23+
outdir_segments = [ctx.bin_dir.path, ctx.label.package]
24+
if ctx.attr.output_dir:
25+
# We'll write into a newly created directory named after the rule
26+
outdir_segments.append(ctx.attr.name)
27+
28+
# The list comprehension removes empty segments like if we are in the root package
29+
s = s.replace("$@", "/".join([o for o in outdir_segments if o]))
2430
return ctx.expand_location(s, targets = ctx.attr.data)
2531

2632
def _impl(ctx):
@@ -53,7 +59,7 @@ _npm_package_bin = rule(
5359
)
5460

5561
def npm_package_bin(tool = None, package = None, package_bin = None, data = [], outs = [], args = [], output_dir = False, **kwargs):
56-
"""Run an arbitrary npm package binary (anything under node_modules/.bin/*) under Bazel.
62+
"""Run an arbitrary npm package binary (e.g. a program under node_modules/.bin/*) under Bazel.
5763
5864
It must produce outputs. If you just want to run a program with `bazel run`, use the nodejs_binary rule.
5965
@@ -69,13 +75,14 @@ def npm_package_bin(tool = None, package = None, package_bin = None, data = [],
6975
outs: similar to [genrule.outs](https://docs.bazel.build/versions/master/be/general.html#genrule.outs)
7076
output_dir: set to True if you want the output to be a directory
7177
Exactly one of `outs`, `output_dir` may be used.
72-
If you output a directory, there can only be one output, which will be named the same as the target.
78+
If you output a directory, there can only be one output, which will be a directory named the same as the target.
7379
7480
args: Command-line arguments to the tool.
7581
7682
Subject to 'Make variable' substitution.
7783
Can use $(location) expansion. See https://docs.bazel.build/versions/master/be/make-variables.html
7884
You may also refer to the location of the output_dir with the special `$@` replacement, like genrule.
85+
If output_dir=False then $@ will refer to the output directory for this package.
7986
8087
package: an npm package whose binary to run, like "terser". Assumes your node_modules are installed in a workspace called "npm"
8188
package_bin: the "bin" entry from `package` that should be run. By default package_bin is the same string as `package`

packages/typescript/docs/install.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,45 @@ The TypeScript rules integrate the TypeScript compiler with Bazel.
77
Looking for Karma rules `ts_web_test` and `karma_web_test`?
88
These are now documented in the README at https://npmjs.com/package/@bazel/karma
99

10+
## Alternatives
11+
12+
This package provides Bazel wrappers around the TypeScript compiler, and are how we compile TS code at Google.
13+
14+
These rules are opinionated, for example:
15+
16+
- Your TS code must compile under the `--declaration` flag so that downstream libraries depend only on types, not implementation. This makes Bazel faster by avoiding cascading rebuilds in cases where the types aren't changed.
17+
- We control the output format and module syntax so that downstream rules can rely on them.
18+
19+
They are also fast and optimized:
20+
21+
- We keep a running TypeScript compile running as a daemon, using Bazel workers. This process avoids re-parse and re-JIT of the >1MB `typescript.js` and keeps cached bound ASTs for input files which saves time.
22+
23+
We understand this is a tradeoff. If you want to use the plain TypeScript compiler provided by the TS team at Microsoft, you can do this by calling its CLI directly. For example,
24+
25+
```python
26+
load("@npm//typescript:index.bzl", "tsc")
27+
28+
srcs = glob(["*.ts"])
29+
deps = ["@npm//@types/node"]
30+
31+
tsc(
32+
name = "compile",
33+
data = srcs + deps,
34+
outs = [s.replace(".ts", ext) for ext in [".js", ".d.ts"] for s in srcs],
35+
args = [
36+
"--outDir",
37+
"$@",
38+
"--lib",
39+
"es2017,dom",
40+
"--downlevelIteration",
41+
"--declaration",
42+
] + [
43+
"$(location %s)" % s
44+
for s in srcs
45+
],
46+
)
47+
```
48+
1049
## Installation
1150

1251
Add a devDependency on `@bazel/typescript`
@@ -208,6 +247,37 @@ directory. See the notes about the `tsconfig` attribute in the [ts_library API d
208247
209248
[ts_library API docs]: http://tsetse.info/api/build_defs.html#ts_library
210249

250+
## Accessing JavaScript outputs
251+
252+
The default output of the `ts_library` rule is the `.d.ts` files.
253+
This is for a couple reasons:
254+
255+
- help ensure that downstream rules which access default outputs will not require
256+
a cascading re-build when only the implementation changes but not the types
257+
- make you think about whether you want the devmode (named UMD) or prodmode outputs
258+
259+
You can access the JS output by adding a `filegroup` rule after the `ts_library`,
260+
for example
261+
262+
```python
263+
ts_library(
264+
name = "compile",
265+
srcs = ["thing.ts"],
266+
)
267+
268+
filegroup(
269+
name = "thing.js",
270+
srcs = ["compile"],
271+
# Change to es6_sources to get the 'prodmode' JS
272+
output_group = "es5_sources",
273+
)
274+
275+
my_rule(
276+
name = "uses_js",
277+
deps = ["thing.js"],
278+
)
279+
```
280+
211281
## Serving TypeScript for development
212282

213283
There are two choices for development mode:

0 commit comments

Comments
 (0)