aspect-build / aspect-build/rules_js

[FR]: link outside WORKSPACE for dependencies during local development (~= `pnpm link`)

Open
#1,165 10 comments 2 reactions 0 assignees View on GitHub
enhancement help wanted
Dominant language
Starlark
Stars
378
Forks
183
Avg merge
1d 9h
Merged PRs (30d)
32

Description

### What is the current behavior?

Currently, `rules_js` fetches packages from either:

1. A remote location (https://registry.nodejs.org/..., git://github.com/...) with the Bazel downloader
2. The user workspace (//pkg/left-pad), which requires the package to be pulled into the workspace and its dependencies readable by `npm_translate_lock`.

Attempts to link outside the Bazel workspace to an NPM package located elsewhere on-disk get rejected with
[invalid link_package outside of the WORKSPACE](https://github.com/aspect-build/rules_js/blob/fd156d1bb159d2982f0fa4bc798a2bc618db2a11/npm/private/npm_translate_lock_generate.bzl#L97-L104).

### Describe the feature

The [npm link](https://docs.npmjs.com/cli/v9/commands/npm-link) workflow is pretty common in the node community, as it allows a dev to modify a third-party package and use it without having to vendor that package.

As a contrived example motivation (replace `left-pad` with any other package):

1. I've found a pathological case in `left-pad` performance that my application highlights
2. I'd like to contribute a fix back to upstream `left-pad`. While working on that fix, I want to use the locally-changed copy in my application as a sort of "real world" gut-check in addition to the `left-pad` test suite. Just to make sure my pathological case is indeed getting fixed.
3. I don't want to vendor `left-pad` for any number of reasons:
1. `left-pad` has a complicated/obscure build system that makes it non-trivial to vendor and build with `rules_js`.
2. `left-pad` takes bugfixes incredibly fast, so my vendored copy would only exist for a few hours after my PR goes out.

In the current state, there appears to be no way to build `left-pad` in a separate directory and use it in my `rules_js`-built package(s).

With vanilla `pnpm link` (or `npm link` or …), the workflow is roughly:

1. `pnpm --dir ~/bitbucket.org/my-org/my-app link ~/github.com/left-pad/left-pad` to use a custom `left-pad`
6. Change and rebuild `left-pad`.
7. Change and rebuild `my-app`. It includes my `left-pad` changes.

Ideally, the workflow would be pretty similar under Bazel + rules_js. For local development it feels reasonable to break hermeticity, akin to `npm_translate_lock`'s current `use_home_npmrc`), but I'd be happy to add an extra flag or two to achieve this.

-----

Relevant slack conversation: https://bazelbuild.slack.com/archives/CEZUUKQ6P/p1689358470077099

Contributor guide

Open the contributing guide

Research direction

Start with npm/private/npm_translate_lock_generate.bzl, especially the validation linked from the issue, and trace how npm_translate_lock handles workspace and remote package sources. Compare that flow with the described pnpm link workflow. Done means a package built outside the Bazel WORKSPACE can be used during local development and rebuilt changes are visible to the consuming application.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
build-system
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.