In the following post I will show an example where I use Bazel to build an Angular application and a nodejs api.
The application used for this demo is a modified version of Alex Eagle’s Bazel demo.
You can find the modified version here.
The application consists of two parts: An Angular application and a node express api.
Angular Application
I modified the original Angular application to make an http request to fetch a headline from the api.
The main component can be found below:
@Component({
selector: 'hello-world-app',
template: `
<h1>{{headline | async}}</h1>
<div>{{name}}</div>
<input type="text" [value]="name" (input)="name = $event.target.value"/>
`,
styleUrls: ['./hello-world-styles.css']
})
export class HelloWorldComponent implements OnInit {
name = "Hello";
headline: Observable<string>;
constructor(private http: Http) {}
ngOnInit() {
this.headline = this.http.get('http://localhost:9000/hello-world')
.map(res => res.json());
}
}
The application and Bazel build process is otherwise unchanged from the original setup.
API
The api is super simple as seen below:
import * as express from 'express';
import {HelloWorldService} from './hello-world.service';
const app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
const helloWorldService = new HelloWorldService();
app.get('/hello-world', (req, res) => res.json(helloWorldService.getMessage()))
app.listen(9000, () => console.log('Example app listening on port 9000!'))
The api is written in Typescript.
Transpiling Typescript to JavaScript in Bazel can be done by adding the ts_library Bazel rule.
Next I am using the nodejs_binary rule to run the api after it’s transpiled.
The full BUILD.bazel file can be found below:
load("@build_bazel_rules_nodejs//:defs.bzl", "rollup_bundle", "nodejs_binary")
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
ts_library(
name = "ts_server",
srcs = glob(["*.ts"]),
)
nodejs_binary(
name = "api",
data = ["//src/api:ts_server"],
entry_point = "../server.js",
)
I now have two Bazel rules to build and run.
In order to run both at the same time I trigger parallel Bazel run commands by using concurrently.
I use an npm script task to wrap the two iBazel commands:
concurrently \"ibazel run //src:devserver\" \"ibazel run //src:api\"
To run the project all you need is npm run start.
When you execute the command, both apps will start.
Since I am using iBazel the applications will refresh whenever any of the source files are modified.