blob: bfc81da80fd6f82df2a90f35c5458df500463ffe [file] [log] [blame] [view]
spomorski97a932f2018-06-04 10:16:44 -07001---
2layout: documentation
3title: Building JavaScript Outputs
4---
5
6# Building JavaScript Outputs
7
8Bazel supports an incremental and customizable means of building and testing
Googlerd355b552019-04-24 11:33:05 -07009JavaScript outputs from JavaScript and TypeScript sources.
10
11It can also support build steps needed for frameworks like Angular.
spomorski97a932f2018-06-04 10:16:44 -070012
13**Note:** This document describes Bazel features and workflows that are useful,
14but the Bazel team has not fully verified and does not officially support
15these features and workflows.
16
spomorski03ca7d12018-06-05 11:32:48 -070017## Contents
spomorski97a932f2018-06-04 10:16:44 -070018
spomorski03ca7d12018-06-05 11:32:48 -070019* [Overview](#overview)
20* [Setting up your environment](#setting-up-your-environment)
21 * [Step 1: Installing Bazel](#step-1-installing-bazel)
22 * [Step 2: Installing iBazel](#step-2-installing-ibazel)
23 * [Step 3: Configuring the `bazel.rc` file](#step-3-configuring-the-bazel-rc-file)
Googlerd355b552019-04-24 11:33:05 -070024 * [Step 4: Setup linting (optional)](#step-4-linting)
spomorski03ca7d12018-06-05 11:32:48 -070025* [Building JavaScript inputs](#building-javascript)
26* [Building TypeScript inputs](#building-typescript)
27 * [Compiling TypeScript inputs (`ts_library`)](#compiling-typescript-inputs-ts_library)
28 * [Running a development server (`ts_devserver`)](#running-a-development-server-ts_devserver)
29 * [Testing TypeScript code (`ts_web_test`)](#testing-typescript-code-ts_web_test)
30* [Building Angular inputs](#building-angular-inputs)
31
32## Overview
spomorski97a932f2018-06-04 10:16:44 -070033
34Bazel rules for building JavaScript outputs are split into three layers, since
35you can use JavaScript without TypeScript, and TypeScript without Angular.
36This document assumes you are already familiar with Bazel and uses the
Googlerd355b552019-04-24 11:33:05 -070037[Angular for Bazel sample project](https://github.com/angular/angular-bazel-example)
spomorski97a932f2018-06-04 10:16:44 -070038to illustrate the recommended configuration. You can use the sample project as a
39starting point and add your own code to it to start building with Bazel.
spomorski97a932f2018-06-04 10:16:44 -070040
Jingwen Chen0f4544d2018-12-14 16:28:16 -080041If you're new to Bazel, take a look at the ["Getting
42Started"](getting-started.html) material before proceeding.
spomorski97a932f2018-06-04 10:16:44 -070043
spomorski03ca7d12018-06-05 11:32:48 -070044## Setting up your environment
spomorski97a932f2018-06-04 10:16:44 -070045
46To set up your environment for building JavaScript outputs with Bazel, do the
47following:
48
spomorski03ca7d12018-06-05 11:32:48 -070049### Step 1: Installing Bazel
spomorski97a932f2018-06-04 10:16:44 -070050
Googlerd355b552019-04-24 11:33:05 -070051You can either [Install Bazel](install.html) following the same steps that you
52would for backend development, or you can install NodeJS with npm and run
53`npm install -g @bazel/bazel`.
spomorski97a932f2018-06-04 10:16:44 -070054
spomorski03ca7d12018-06-05 11:32:48 -070055### Step 2: Installing iBazel
spomorski97a932f2018-06-04 10:16:44 -070056
57iBazel, or iterative Bazel, is a "watchdog" version of Bazel that automatically
58runs whenever your source files change. Use it to auto-run your tests and
59auto-refresh the code served by the development server.
60
61[Install iBazel](https://github.com/bazelbuild/bazel-watcher) globally using
62your package manager of choice. The global installation is required so that
63iBazel is in your PATH variable. Also install a specific version of iBazel into
64your project so that your whole team updates together. For example:
65
66```
67npm install --save-dev @bazel/ibazel
68npm install --global @bazel/ibazel
69```
70or
71
72```
73yarn add -D @bazel/ibazel
74yarn global add @bazel/ibazel
75```
76
77To use `ibazel`, simply replace `bazel` with `ibazel` in your Bazel commands.
78
spomorski03ca7d12018-06-05 11:32:48 -070079### Step 3: Configuring the `bazel.rc` file
spomorski97a932f2018-06-04 10:16:44 -070080
81Any Bazel build flag or option that can be placed on the command line can also
wyv3a634fa2020-05-15 06:47:26 -070082be set in the project's [`bazel.rc` file](guide.html#bazelrc)
spomorski97a932f2018-06-04 10:16:44 -070083so that it is applied every time Bazel builds or tests the project.
84
85Based on how you want to share Bazel settings across your project and team(s),
86you can use any combination of the following techniques:
87
88* **To use the same Bazel settings for the project**, create a `tools/bazel.rc`
89 file at the root of the Bazel workspace. Adding it to the workspace will
90 check the file into version control and propagate it to others working on
91 the project as well as the CI system.
92
93* **To personalize Bazel settings for the project but not share them,**
94 create a `.bazel.rc` file at the root of the project and add the file to
95 your `.gitignore` list.
96
97* **To personalize Bazel settings for all of your projects on your
98 local machine,** create a `.bazel.rc` file in your home directory.
99
100Here's an example `tools/bazel.rc` file to share with your team. Modify this
101template as needed.
102
103```
104###############################
105# Directory structure #
106###############################
107
Googlerd355b552019-04-24 11:33:05 -0700108# Artifacts are typically placed in a directory called "dist"
spomorski97a932f2018-06-04 10:16:44 -0700109# Be aware that this setup will still create a bazel-out symlink in
Googlerd355b552019-04-24 11:33:05 -0700110# your project directory, which you must exclude from version control and your
spomorski97a932f2018-06-04 10:16:44 -0700111# editor's search path.
Googlerd355b552019-04-24 11:33:05 -0700112build --symlink_prefix=dist/
spomorski97a932f2018-06-04 10:16:44 -0700113
114###############################
115# Output #
116###############################
117
118# A more useful default output mode for bazel query, which
119# prints "ng_module rule //foo:bar" instead of just "//foo:bar".
120query --output=label_kind
121
122# By default, failing tests don't print any output, it's logged to a
123# file instead.
spomorski97a932f2018-06-04 10:16:44 -0700124test --test_output=errors
125
spomorski97a932f2018-06-04 10:16:44 -0700126###############################
127# Typescript / Angular / Sass #
128###############################
129# Make TypeScript and Angular compilation fast, by keeping a few
130# copies of the compiler running as daemons, and cache SourceFile
131# ASTs to reduce parse time.
132build --strategy=TypeScriptCompile=worker --strategy=AngularTemplateCompile=worker
133
134# Enable debugging tests with --config=debug
135test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
136```
137
Googlerd355b552019-04-24 11:33:05 -0700138### Step 4: Linting
spomorski97a932f2018-06-04 10:16:44 -0700139
Googlerd355b552019-04-24 11:33:05 -0700140Add the `buildifier` dependency to your project:
spomorski97a932f2018-06-04 10:16:44 -0700141
Googlerd355b552019-04-24 11:33:05 -0700142```sh
143npm install --save-dev @bazel/buildifier
144```
145
146or if you prefer Yarn,
147
148```sh
149yarn add -D @bazel/buildifier
150```
151
152then add scripts to your `package.json` that run Buildifier.
153We've selected a set of enabled warnings here, you could add and remove from
154this list.
155
156```json
157"scripts": {
158 "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",
159 "bazel:lint": "yarn bazel:format --lint=warn",
160 "bazel:lint-fix": "yarn bazel:format --lint=fix"
161}
162```
163
164> The Bazel team is aware that this configuration is not ergonomic. Follow https://github.com/bazelbuild/buildtools/issues/479
165
166> Also the Buildifier tool is not available on Windows. Follow https://github.com/bazelbuild/buildtools/issues/375
spomorski97a932f2018-06-04 10:16:44 -0700167
spomorski03ca7d12018-06-05 11:32:48 -0700168## Building JavaScript
spomorski97a932f2018-06-04 10:16:44 -0700169
Attila Ol?hf3556152018-11-26 13:18:26 -0800170Use the [`rules_nodejs`](https://github.com/bazelbuild/rules_nodejs)
spomorski97a932f2018-06-04 10:16:44 -0700171rules to build NodeJS applications and execute JavaScript code within Bazel. You
172can execute JavaScript tools in the Bazel toolchain, binary programs, or tests.
173The NodeJS rules add the NodeJS runtime to your Bazel project.
174
Googlerd355b552019-04-24 11:33:05 -0700175See the documentation on that site for setup steps and to configure targets.
spomorski97a932f2018-06-04 10:16:44 -0700176
spomorski03ca7d12018-06-05 11:32:48 -0700177## Building TypeScript
spomorski97a932f2018-06-04 10:16:44 -0700178
Googlerd355b552019-04-24 11:33:05 -0700179See the https://www.npmjs.com/package/@bazel/typescript package.
spomorski97a932f2018-06-04 10:16:44 -0700180
181
spomorski03ca7d12018-06-05 11:32:48 -0700182### Compiling TypeScript inputs (`ts_library`)
spomorski97a932f2018-06-04 10:16:44 -0700183
184The `ts_library` rule compiles one package of TypeScript code at a time. Each
185library compiles independently using the `.d.ts` declaration files from its
186dependencies. Thus, Bazel will only rebuild a package if the API the package
187depends on changes.
188
189The `ts_library `rule, by default, outputs a `.d.ts` file for each `.ts` source
190file input into it, plus an ES5 (devmode) `.js` file to be used as inputs for
191rule targets that depend on the current target, including transitively.
192
193**Tip:** You can try out the `ts_library` rule by running bazel build src in
194the [sample project](https://github.com/alexeagle/angular-bazel-example/wiki).
195
196**Note:** We recommend standardizing your TypeScript settings into a single
197`tsconfig.json` file or as few `tsconfig.json` files as possible.
198
199Note the following:
200
201* Bazel controls parts of the `tsconfig.json `file that define locations of
202 input and output files, manage dependencies on typings, and produce
203 JavaScript output that's readable by downstream tooling. Currently, this
204 format is unbundled UMD modules, wrapping noth named (non-anonymous) AMD
205 modules and `commonjs` modules.
206
207* Bazel may introduce new requirements for your TypeScript code. For example,
208 Bazel uses the `-declarations` flag to produce `.d.ts` outputs required by
209 dependent rule targets; your code may require adjustment to not produce
210 errors when the `-declarations` flag is in use.
211
212* If your TypeScript builds are slow, consider granularizing the affected rule
213 target(s) into smaller sub-targets and declaring dependencies between them
214 appropriately.
215
spomorski03ca7d12018-06-05 11:32:48 -0700216### Running a development server (`ts_devserver`)
spomorski97a932f2018-06-04 10:16:44 -0700217
218The `ts_devserver` rule brings up a development server from your application
219sources. It's intended for use with the `ibazel run` command so that the server
220picks up your code changes immediately. The rule injects a `livereload` script
221into the browser, which causes the page to auto-refresh with the latest changes
222at the completion of each build.
223
224**Tip:** You can test-drive the development server feature by running
225`ibazel run src: devserver` on the [sample project](https://github.com/alexeagle/angular-bazel-example/wiki).
226
227
spomorski03ca7d12018-06-05 11:32:48 -0700228### Testing TypeScript code (`ts_web_test`)
spomorski97a932f2018-06-04 10:16:44 -0700229
230Use the `ts_web_test` rule to execute the Karma test runner. This rule works
231best with ibazel so that both the test runner and the browser pick up your
232changes at the completion of each build. For faster builds, Bazel bundles your
233code and its dependencies into a single JavaScript file delivered to the browser
234when the test runner executes.
235
236If you need to match lots of tests with a target pattern such as bazel test //…
237or using CI, run the `ts_web_test` rule with the regular `bazel test` command
238instead. Bazel will then launch a headless Chrome instance and exit after a
239single run.
240
241**Tip:** You can test-drive the `ts_web_test` rule by running `ibazel run` or
242`bazel run` on the `src/hello-world:test` target in the [sample project](https://github.com/alexeagle/angular-bazel-example/wiki).
243
244
spomorski03ca7d12018-06-05 11:32:48 -0700245## Building Angular inputs
spomorski97a932f2018-06-04 10:16:44 -0700246
spomorski03ca7d12018-06-05 11:32:48 -0700247Bazel 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 -0700248