Just an initial starting point for a bazel monorepo with a SvelteKit application. The goal is to show how to setup bazel to run a sveltekit app during development and to build it for a production release.
Keep in mind, I'm not an expert in bazel or sveltekit, so there is most likely better ways to get this to work. This is just the result of researching to build a monorepo for myself. If you see something wrong or that can be improved, please create an issue or a PR.
The repo was set up using:
The repo has a single sveltekit application under packages/my_first_app
and a
single library under packages/my_common_package
. The app depends on the library.
This is purely for demonstration on how you would create common libraries inside
your repo, since it is the main purpose of a monorepo.
At the root of the repo you will find a package.json
file where all
dependencies for all JS projects in the repo would be listed. This is
meant to encourage a common version of packages accross apps. However,
you don't need to run pnpm install
in order to build apps. The package.json
file is meant only to inform pnpm which versions we care about. When we run
this command (per the Aspect docs on how to set up rules_js)
pnpm install --lockfile-only
pnpm will only create a lockfile with specific versions based on what package.json
has listed. Finally, when we run a build, bazel will look at the version in
pnpm's lockfile, fetch those, and will make them available for packages to list
as dependencies. In other words, bazel will be doing the job pnpm install
would
normally do.
Applications should have a package.json
file inside them too. There are two
main reasons for this:
"type": "module"
in order to resolve things properly, and the only way to do that is through package.json
.package.json
, as is the
case for the Attractions UI Kit.Build dependencies (which in the case of sveltekit is most of them) should not be listed
in package.json
, they should be included in the build defined in packages/<app name>/BUILD.bazel
.
If you open packages/my_first_app/package.json
you'll
notice there's only one dependency listed, that's because the dependencies svelte needs are
listed under the BUILD.bazel
file.
In order to add a new package you should do the following:
packages/...
.pnpm-workspace.yaml
.packages/<package name>/node_modules
BUILD.bazel
file inside the package.pnpm install --lockfile-only
again. This is so pnpm and bazel can see your new package.Once you have that you should be able to build or run any targets you defined in BUILD.bazel
.
The example app has 2 commands available, build
and serve
. These are meant to mirror the vite dev
and vite build
commands that sveltekit normally uses. You can
run them by doing:
# build
bazel build //packages/my_first_app
# serve
bazel run //packages/my_first_app:serve
# or serve with HMR
ibazel run //packages/my_first_app:serve
Using the first serve command will not enable HMR. The problem is
vite is built to look for changes on your source repo and rebuild, but Bazel builds
everything inside of a sandbox, meaning your changes to source files are not reflected
there until bazel runs again. To get HMR to work we need to use ibazel. As a convenience, a script is defined inside the root
package.json
to run ibazel through pnpm if you prefer using it like that. Regardless,
using the second command should work (requires iBazel to be installed in your machine).
pnpm install
globablly. As explained
above you don't need to run that, since bazel will fetch its own dependencies
during a build however, it will help to get rid of some editor errors saying it can't find a given package.