blob: 012cbda28efcedeb1cb5a791c07dc78c89eb1f1e [file] [log] [blame] [view]
spomorski97a932f2018-06-04 10:16:44 -07001---
2layout: documentation
3title: Building JavaScript Outputs
4---
5
6# Building JavaScript Outputs
7
Googlercb395cb2020-12-21 10:33:20 -08008This page describes the features, rules, and workflows related to building
9and testing JavaScript outputs.
Googlerd355b552019-04-24 11:33:05 -070010
Googlercb395cb2020-12-21 10:33:20 -080011**Note:** The Bazel team has not fully verified and does not officially support
12the features and workflows described on this page.
spomorski97a932f2018-06-04 10:16:44 -070013
spomorski03ca7d12018-06-05 11:32:48 -070014## Overview
spomorski97a932f2018-06-04 10:16:44 -070015
Googlercb395cb2020-12-21 10:33:20 -080016Bazel supports an incremental and customizable means of building and
17testing JavaScript outputs from JavaScript and TypeScript sources. Bazel also
18supports build steps needed for frameworks such as Angular.
19
spomorski97a932f2018-06-04 10:16:44 -070020Bazel rules for building JavaScript outputs are split into three layers, since
21you can use JavaScript without TypeScript, and TypeScript without Angular.
Googlercb395cb2020-12-21 10:33:20 -080022This page assumes you are already familiar with Bazel and uses the
Googlerd355b552019-04-24 11:33:05 -070023[Angular for Bazel sample project](https://github.com/angular/angular-bazel-example)
spomorski97a932f2018-06-04 10:16:44 -070024to illustrate the recommended configuration. You can use the sample project as a
25starting point and add your own code to it to start building with Bazel.
spomorski97a932f2018-06-04 10:16:44 -070026
Jingwen Chen0f4544d2018-12-14 16:28:16 -080027If you're new to Bazel, take a look at the ["Getting
28Started"](getting-started.html) material before proceeding.
spomorski97a932f2018-06-04 10:16:44 -070029
spomorski03ca7d12018-06-05 11:32:48 -070030## Setting up your environment
spomorski97a932f2018-06-04 10:16:44 -070031
32To set up your environment for building JavaScript outputs with Bazel, do the
33following:
34
Googler817e2202020-11-20 19:14:47 -080035### Installing Bazel
spomorski97a932f2018-06-04 10:16:44 -070036
Googlerd355b552019-04-24 11:33:05 -070037You can either [Install Bazel](install.html) following the same steps that you
38would for backend development, or you can install NodeJS with npm and run
Vladimir Pouzanov7df37162021-01-27 07:19:40 -080039`npm install -g @bazel/bazelisk`.
spomorski97a932f2018-06-04 10:16:44 -070040
Googler817e2202020-11-20 19:14:47 -080041### Installing iBazel
spomorski97a932f2018-06-04 10:16:44 -070042
43iBazel, or iterative Bazel, is a "watchdog" version of Bazel that automatically
44runs whenever your source files change. Use it to auto-run your tests and
45auto-refresh the code served by the development server.
46
47[Install iBazel](https://github.com/bazelbuild/bazel-watcher) globally using
48your package manager of choice. The global installation is required so that
49iBazel is in your PATH variable. Also install a specific version of iBazel into
50your project so that your whole team updates together. For example:
51
52```
53npm install --save-dev @bazel/ibazel
54npm install --global @bazel/ibazel
55```
56or
57
58```
59yarn add -D @bazel/ibazel
60yarn global add @bazel/ibazel
61```
62
63To use `ibazel`, simply replace `bazel` with `ibazel` in your Bazel commands.
64
Googler817e2202020-11-20 19:14:47 -080065### Configuring the `bazel.rc` file
spomorski97a932f2018-06-04 10:16:44 -070066
67Any Bazel build flag or option that can be placed on the command line can also
wyv3a634fa2020-05-15 06:47:26 -070068be set in the project's [`bazel.rc` file](guide.html#bazelrc)
spomorski97a932f2018-06-04 10:16:44 -070069so that it is applied every time Bazel builds or tests the project.
70
71Based on how you want to share Bazel settings across your project and team(s),
72you can use any combination of the following techniques:
73
74* **To use the same Bazel settings for the project**, create a `tools/bazel.rc`
75 file at the root of the Bazel workspace. Adding it to the workspace will
76 check the file into version control and propagate it to others working on
77 the project as well as the CI system.
78
79* **To personalize Bazel settings for the project but not share them,**
80 create a `.bazel.rc` file at the root of the project and add the file to
81 your `.gitignore` list.
82
83* **To personalize Bazel settings for all of your projects on your
84 local machine,** create a `.bazel.rc` file in your home directory.
85
86Here's an example `tools/bazel.rc` file to share with your team. Modify this
87template as needed.
88
89```
90###############################
91# Directory structure #
92###############################
93
Googlerd355b552019-04-24 11:33:05 -070094# Artifacts are typically placed in a directory called "dist"
spomorski97a932f2018-06-04 10:16:44 -070095# Be aware that this setup will still create a bazel-out symlink in
Googlerd355b552019-04-24 11:33:05 -070096# your project directory, which you must exclude from version control and your
spomorski97a932f2018-06-04 10:16:44 -070097# editor's search path.
Googlerd355b552019-04-24 11:33:05 -070098build --symlink_prefix=dist/
spomorski97a932f2018-06-04 10:16:44 -070099
100###############################
101# Output #
102###############################
103
104# A more useful default output mode for bazel query, which
105# prints "ng_module rule //foo:bar" instead of just "//foo:bar".
106query --output=label_kind
107
108# By default, failing tests don't print any output, it's logged to a
109# file instead.
spomorski97a932f2018-06-04 10:16:44 -0700110test --test_output=errors
111
spomorski97a932f2018-06-04 10:16:44 -0700112###############################
113# Typescript / Angular / Sass #
114###############################
115# Make TypeScript and Angular compilation fast, by keeping a few
116# copies of the compiler running as daemons, and cache SourceFile
117# ASTs to reduce parse time.
118build --strategy=TypeScriptCompile=worker --strategy=AngularTemplateCompile=worker
119
120# Enable debugging tests with --config=debug
121test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
122```
123
Googlerd355b552019-04-24 11:33:05 -0700124### Step 4: Linting
spomorski97a932f2018-06-04 10:16:44 -0700125
Googlerd355b552019-04-24 11:33:05 -0700126Add the `buildifier` dependency to your project:
spomorski97a932f2018-06-04 10:16:44 -0700127
Googlerd355b552019-04-24 11:33:05 -0700128```sh
129npm install --save-dev @bazel/buildifier
130```
131
132or if you prefer Yarn,
133
134```sh
135yarn add -D @bazel/buildifier
136```
137
138then add scripts to your `package.json` that run Buildifier.
139We've selected a set of enabled warnings here, you could add and remove from
140this list.
141
142```json
143"scripts": {
144 "bazel:format": "find . -type f \\( -name \"*.bzl\" -or -name WORKSPACE -or -name BUILD -or -name BUILD.bazel \\) ! -path \"*/node_modules/*\" | xargs buildifier -v --warnings=attr-cfg,attr-license,attr-non-empty,attr-output-default,attr-single-file,constant-glob,ctx-actions,ctx-args,depset-iteration,depset-union,dict-concatenation,duplicated-name,filetype,git-repository,http-archive,integer-division,load,load-on-top,native-build,native-package,out-of-order-load,output-group,package-name,package-on-top,positional-args,redefined-variable,repository-name,same-origin-load,string-iteration,unsorted-dict-items,unused-variable",
145 "bazel:lint": "yarn bazel:format --lint=warn",
146 "bazel:lint-fix": "yarn bazel:format --lint=fix"
147}
148```
149
150> The Bazel team is aware that this configuration is not ergonomic. Follow https://github.com/bazelbuild/buildtools/issues/479
151
spomorski03ca7d12018-06-05 11:32:48 -0700152## Building JavaScript
spomorski97a932f2018-06-04 10:16:44 -0700153
Attila Ol?hf3556152018-11-26 13:18:26 -0800154Use the [`rules_nodejs`](https://github.com/bazelbuild/rules_nodejs)
spomorski97a932f2018-06-04 10:16:44 -0700155rules to build NodeJS applications and execute JavaScript code within Bazel. You
156can execute JavaScript tools in the Bazel toolchain, binary programs, or tests.
157The NodeJS rules add the NodeJS runtime to your Bazel project.
158
Googlerd355b552019-04-24 11:33:05 -0700159See the documentation on that site for setup steps and to configure targets.
spomorski97a932f2018-06-04 10:16:44 -0700160
spomorski03ca7d12018-06-05 11:32:48 -0700161## Building TypeScript
spomorski97a932f2018-06-04 10:16:44 -0700162
Googlerd355b552019-04-24 11:33:05 -0700163See the https://www.npmjs.com/package/@bazel/typescript package.
spomorski97a932f2018-06-04 10:16:44 -0700164
165
spomorski03ca7d12018-06-05 11:32:48 -0700166### Compiling TypeScript inputs (`ts_library`)
spomorski97a932f2018-06-04 10:16:44 -0700167
168The `ts_library` rule compiles one package of TypeScript code at a time. Each
169library compiles independently using the `.d.ts` declaration files from its
170dependencies. Thus, Bazel will only rebuild a package if the API the package
171depends on changes.
172
173The `ts_library `rule, by default, outputs a `.d.ts` file for each `.ts` source
174file input into it, plus an ES5 (devmode) `.js` file to be used as inputs for
175rule targets that depend on the current target, including transitively.
176
177**Tip:** You can try out the `ts_library` rule by running bazel build src in
178the [sample project](https://github.com/alexeagle/angular-bazel-example/wiki).
179
180**Note:** We recommend standardizing your TypeScript settings into a single
181`tsconfig.json` file or as few `tsconfig.json` files as possible.
182
183Note the following:
184
185* Bazel controls parts of the `tsconfig.json `file that define locations of
186 input and output files, manage dependencies on typings, and produce
187 JavaScript output that's readable by downstream tooling. Currently, this
188 format is unbundled UMD modules, wrapping noth named (non-anonymous) AMD
189 modules and `commonjs` modules.
190
191* Bazel may introduce new requirements for your TypeScript code. For example,
192 Bazel uses the `-declarations` flag to produce `.d.ts` outputs required by
193 dependent rule targets; your code may require adjustment to not produce
194 errors when the `-declarations` flag is in use.
195
196* If your TypeScript builds are slow, consider granularizing the affected rule
197 target(s) into smaller sub-targets and declaring dependencies between them
198 appropriately.
199
spomorski03ca7d12018-06-05 11:32:48 -0700200### Running a development server (`ts_devserver`)
spomorski97a932f2018-06-04 10:16:44 -0700201
202The `ts_devserver` rule brings up a development server from your application
203sources. It's intended for use with the `ibazel run` command so that the server
204picks up your code changes immediately. The rule injects a `livereload` script
205into the browser, which causes the page to auto-refresh with the latest changes
206at the completion of each build.
207
208**Tip:** You can test-drive the development server feature by running
209`ibazel run src: devserver` on the [sample project](https://github.com/alexeagle/angular-bazel-example/wiki).
210
211
spomorski03ca7d12018-06-05 11:32:48 -0700212### Testing TypeScript code (`ts_web_test`)
spomorski97a932f2018-06-04 10:16:44 -0700213
214Use the `ts_web_test` rule to execute the Karma test runner. This rule works
215best with ibazel so that both the test runner and the browser pick up your
216changes at the completion of each build. For faster builds, Bazel bundles your
217code and its dependencies into a single JavaScript file delivered to the browser
218when the test runner executes.
219
220If you need to match lots of tests with a target pattern such as bazel test //…
221or using CI, run the `ts_web_test` rule with the regular `bazel test` command
222instead. Bazel will then launch a headless Chrome instance and exit after a
223single run.
224
225**Tip:** You can test-drive the `ts_web_test` rule by running `ibazel run` or
226`bazel run` on the `src/hello-world:test` target in the [sample project](https://github.com/alexeagle/angular-bazel-example/wiki).
227
228
spomorski03ca7d12018-06-05 11:32:48 -0700229## Building Angular inputs
spomorski97a932f2018-06-04 10:16:44 -0700230
spomorski03ca7d12018-06-05 11:32:48 -0700231Bazel can build JavaScript outputs from Angular. For instructions, see [Building Angular with Bazel](https://github.com/alexeagle/angular-bazel-example/wiki/Angular-rules).
spomorski97a932f2018-06-04 10:16:44 -0700232