Skip to content

Latest commit

 

History

History
82 lines (61 loc) · 4.23 KB

README.md

File metadata and controls

82 lines (61 loc) · 4.23 KB

Case 5: Vite + React + TypeScript + Bazel

In this case we use Vite to build a TypeScript React app, and Bazel to build the app and run tests.
The approach in this example also works with local development through pnpm as developers are used to.

We use rules_js to handle the JavaScript ecosystem in Bazel.

Bazel only handles packages from the pnpm-lock.yaml at the workspace root, so when you make changes to package.json remember to run pnpm install afterward. To see the setup for pnpm, check the npm_translate_lock function in MODULE.bazel at root.

In the BUILD.bazel file for this case, there are some new concepts:

load("@npm//:defs.bzl", "npm_link_all_packages")
load("@npm//workshop/case5:typescript/package_json.bzl", typescript_bin = "bin")

npm_link_all_packages(name = "node_modules")

The @npm// namespace is generated by the npm_translate_lock function in the root MODULE.bazel. This namespace contains generated Starlark targets for all packages in the pnpm-lock.yaml file.

The typescript_bin = "bin" in the load statement is a reference to the bin field in the package.json for the typescript package. This makes it possible to run the tsc directly in Bazel with typescript_bin.tsc. There are also some other targets which are generated, like typescript_bin.tsc_test for running the tsc binary as a test instead. You can also run typescript_bin.tsc_binary which is a binary target for the tsc binary if you need to run sideeffects.

See more about these features at the rules_js docs

To make your IDE happy when using local workspace packages, you have to extra paths to the Bazel output in your tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "openapi_typescript/*": [
        "../../bazel-bin/workshop/case3/pkg/*"
      ]
    }
  }
}

See more about this in the rules_js FAQ in this case.

Things to try out

Build the application

bazel build //workshop/case5:build

Run application in dev mode

bazel run //workshop/case5:dev - note that this does not notice changed files in the workspace, so you have to restart the command to see changes.
To get hot reloading through Bazel you need to use ibazel, see bazel-watcher.
Then you can run ibazel run //workshop/case5:dev or npx @bazel/ibazel run //workshop/case5:dev instead.

Dev mode also works through cd workshop/case5 && pnpm i && pnpm run dev, which goes outside of Bazel

Create a Docker image

bazel run //workshop/case5:tarball builds an OCI compatible image and loads it into your Docker context.
Afterwards, you can run the application with docker run --rm -it -p80:80 case5:latest http://localhost

Inspect the build outputs

You can run bazel cquery //workshop/case5:<target> --output=files to get the files output for a given target.

If you run bazel cquery //workshop/case5:tar --output=files you will get the tar layer for application code. You can then inspect the tar by running tar -tvf bazel-bin/workshop/case5/tar.tar:

drwxr-xr-x  0 0      0           0  1 jan  2000 usr/
drwxr-xr-x  0 0      0           0  1 jan  2000 usr/share/
drwxr-xr-x  0 0      0           0  1 jan  2000 usr/share/nginx/
drwxr-xr-x  0 0      0           0  1 jan  2000 usr/share/nginx/html/
drwxr-xr-x  0 0      0           0  1 jan  2000 usr/share/nginx/html/assets/
-rw-r--r--  0 0      0      142531  1 jan  2000 usr/share/nginx/html/assets/index-DDIbAWc_.js
-rw-r--r--  0 0      0         334  1 jan  2000 usr/share/nginx/html/index.html

Additional things to try

Can you include the greeting-component in the app?

Can you transpile the TypeScript to JavaScript before building the app with Vite?

Check out rules_swc for an example on how to transpile TypeScript to JavaScript with Bazel. This could be useful if you want to reuse the JavaScript in tests to avoid multiple transpilations.