-
-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FR]: npm_package(bundle_dependencies = ["my_dep"])
#891
Comments
My stance in such scenarios would be that you end up manually bundling these shared private libraries- if you don't want to publish them to npm. That is something you could do manually via e.g. If other parts of the monorepo then would rely on the NPM artifact, that would incur the cost of running the bundler. Previously, with |
Structurally the rules_js/npm/private/npm_package.bzl Line 95 in 181d84c
It doesn't currently generate or modify the package.json file and generally leaves it up to the user to configure the contents of the package. It sounds like you've got something working in user space. Could this be generalized into a rule that proceeds npm_package that could then be passed to the npm_package sources to get the updated package.json and any files needed to go along with it for the bundled dependencies? |
This is probably do-able in user-space if we'd rather say it's out of scope for However, I do think the general use case of "Sharing code within a monorepo without having to relative import really far away or publish every utility package" is something that @devversion and I have been chatting about this a bit. I do like his point that we could run a bundler to preprocess the package, I could see that as a viable solution (and probably makes sense for Angular), but it does have some undesirable side effects. Bundlers typically don't have a mode for "vendor this one dependency in my package", so they are likely doing other work which needs to be turned off or worked around. For example, I don't think this use case benefits from bundling all the JavaScript into a single file, it's also not a strict file-by-file transform. You'll likely have to live with some undesired changes to the package output you didn't want in the first place. Basically, I'm not sure how you would get ESBuild to do the right thing here without biting off a bunch of complexity or annoying trade-offs you shouldn't need to make. I was hoping The point about dev / prod builds is relevant here though. One fundamental problem with bundling dependencies (whether via This is a little rambling and not really a cohesive comment, but hopefully that makes some sense. My goal here was to propose
I remember some Slack thread where Greg or Alex basically said that the intended solution to this to create internal NPM packages. That can work locally, but the only way I see that working when published is by publishing those internal packages as well which I'm hesitant to do for internal utilities. Maybe the solution is |
I've used ncc for this, and even published the code https://github.com/aspect-build/bazel-examples/blob/pkg/vercel_pkg/defs/vercel_pkg.bzl and a blog post so I think this can be considered resolved. |
What is the current behavior?
npm_package()
builds only the current package and drops all of its dependencies, assuming they will be linked separately. This is usually the desired behavior, but can be limiting when trying to share utilities within a monorepository. Consider:If a file in
lib
depends onutilities
, then it either needs to either:../../../../utilites/...
.link_workspace_root
(which I believe is generally discouraged).//:node_modules/utilities
fromnpm_link_package()
.The last approach works great locally, but requires the
utilities
package to be published if thelib
package is published. Users then need to install both packages and link them together at runtime, even thoughutilities
may not be public API or be trivial enough to not justify its own published package.Describe the feature
I think the solution here is to leverage NPM's
bundleDependencies
feature. We can define annpm_package()
containing a list ofbundle_dependencies
which are included in the output.This would generate a directory structure like:
It would also update the
package.json
to includebundleDependencies: ['utilities']
, which would tell NPM to keep the bundledutilities
package.I tried doing this in user-space and kinda got it to work. I was able to generate the
node_modules/
tree, though it gets dropped bynpm_package()
which setsexclude_srcs_patterns = ["**/node_modules/**"]
by default. After clearing that attribute, the package contained the bundled dependency and I was able to use it vianpm_link_package()
from a separate workspace.I didn't try publishing the bundled package, but
cd
-ing into the built artifact and runningnpm pack
for some reason drops thenode_modules/
directory, yet if I copy the directory out of Bazel's output tree, and then runnpm pack
, it does containnode_modules/
. I'm not sure if there's a file system issue here or something else going wrong.I'm also not entirely sure how transitive dependencies should work. Testing this out independent of Bazel,
npm install
of a bundled transitive dependency seems to lay out the directories like:Though it also seems to support:
I suspect the first option would be desirable, since two packages could bundle different "versions" of the same dependency, and they should each get their bundled implementation.
I don't think my implementation is doing this feature correctly, since it lays out a flat
node_modules/
structure. I'm also not entirely sure how the dependency structure of linked packages works in@aspect_rules_js
. I also feel like thedeps
attribute ofnpm_link_package()
might be relevant here, but I couldn't find any documentation about it and don't understand how it is supposed to work.While I think bundled dependencies would be really cool, my ultimate goal is around sharing code in my monorepository. Currently I'm doing everything through relative imports, which doesn't scale great. I was under the impression the recommendation in an
@aspect_rules_js
world was to make private packages and manually link them. That works fine locally, but I don't want to publish all these internal, utility packages and would rather inline them in the public packages where needed. That's what led me to find a way to bundle dependencies in an NPM package, I'm not sure if there's a better approach for sharing code.Fund our work
The text was updated successfully, but these errors were encountered: