Bazel: build js_library with another linked JS dependency (yarn workspaces)

635 Views Asked by At

I have a project that includes several JS packages and organized with Yarn workspaces:

<root>
├── WORKSPACE
├── package.json
├── workspaces
│   ├── foo
│   │   ├── package.json
│   │   ├── BUILD.bazel
│   │   ├── src
    │
    ├── bar
    │   ├── package.json
    │   ├── BUILD.bazel
    │   ├── src

FOO package depends on BAR package and it's defined in FOO/package.json:

workspaces/foo/package.json

{
  "name": "FOO",
  "dependencies": {
     "BAR": "link:../bar",
  }

workspaces/bar/BUILD.bazel looks like this

load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
js_library(
    name = "bar",
    package_name = "BAR",
    srcs = [
        "package.json",
        "index.js",
    ],
    visibility = ["//visibility:public"],
)

and here workspaces/foo/BUILD.bazel

load("@build_bazel_rules_nodejs//:index.bzl", "js_library")

js_library(
    name = "foo",
    package_name = "FOO",
    srcs = [
        "package.json",
        "index.js",
    ],
    deps = [
         "//workspaces/bar:bar", 
         "@npm//:node_modules"    # <-- this line causes an error because linked package couldn't be found in node_modules
    ], 
    visibility = ["//visibility:public"],
)

and WORKSPACE file includes:

yarn_install(
    name = "npm_foo",
    package_json = "//workspaces/foo:package.json",
    yarn_lock = "//workspaces/foo:yarn.lock",
    package_path = "workspaces/foo",
    strict_visibility = False,
    # links = {
    #     "bar": "//workspaces/bar",
    # },
    # generate_local_modules_build_files = True,
)

yarn_install(
    name = "npm",
    package_json = "//:package.json",
    yarn_lock = "//:yarn.lock",
)

yarn_install(
    name = "npm_bar",
    package_json = "//workspaces/bar:package.json",
    yarn_lock = "//workspaces/bar:yarn.lock",
    package_path = "workspaces/bar",
)

with all of this setup, I run bazel build //workspaces/foo:foo and it fails. Do I need to configure links or generate_local_modules_build_files attributes in yarn_install? Or what changes required to get this linked packages work together?

1

There are 1 best solutions below

2
On

As far as yarn workspaces aren't supported by rules_nodejs, following workaround worked for me:

here modified workspaces/foo/BUILD.bazel

load("@build_bazel_rules_nodejs//:index.bzl", "js_library")

# this list contains all dependencies from the top level `package.json` file
# do not include linked `bar` package!
DEPENDENCIES = [
  "@npm//react",
  "@npm//react-dom",
  ...
]

# node_modules filegroup includes all dependencies from workspaces/foo/node_modules
filegroup(
    name = "node_modules",
    srcs = glob(
        include = [
            "node_modules/**",
        ],
    ),
)

js_library(
    name = "foo",
    package_name = "FOO",
    srcs = [
        "package.json",
        "index.js",
    ],
    deps = [
         "//workspaces/bar:bar", 
         ":node_modules"
    ] + DEPENDENCIES, 
    visibility = ["//visibility:public"],
)

and WORKSPACE file has only one yarn_install rule for top level package.json since nested workspaces are treated as self-managed:

yarn_install(
    name = "npm",
    package_json = "//:package.json",
    yarn_lock = "//:yarn.lock",
)