rules_js icon indicating copy to clipboard operation
rules_js copied to clipboard

[FR]: ability to register custom package script during package extraction

Open Aghassi opened this issue 9 months ago • 4 comments

What is the current behavior?

Today we would have to list out, for each dependency, a postinstall hook or similar and hope they have a lifecycle hook defined. Otherwise, we are on our own here.

Describe the feature

Provide the ability to modify the content of a third-party npm package during the initial fetch/extraction process. Similar to the exclude_package_contents feature filtering package files, but would allow custom processing and not only file exclusion.

This would be similar to lifecycle hooks, but defined by the workspace author and not by packages themselves.

Reasons

As codebases grow, we find the need to run tools on third party packages to cutdown on the number of files we have to pass around. Having a central way to run an js_binary on an NPM package before it is linked allows developers to efficiently prune, modify, and enhance third party code before it gets linked and used downstream. In our case, we are looking at creating single files (concatenation/bundling/etc) for each package so as to cut down on dependent files in the graph.

Aghassi avatar May 27 '25 21:05 Aghassi

This is doable today with 'replace_packages' but the part that was annoying was not having a good label to refer to the "raw" downloaded/extracted package. I had to resort to hardcoding the (implementation details) fully qualified external repo names. Perhaps providing a way to expose those is easier and unblocks this use case?

dzbarsky avatar Jun 28 '25 15:06 dzbarsky

I think @Aghassi is doing the same today (using replace_packages to accomplish this), is that right?

Maybe that is all we need. Or if it is done within rules_js can we do it any more efficiently and avoid an extra copy of the directory or anything like that?

jbedard avatar Jun 28 '25 18:06 jbedard

If I recall correctly my action took the archive as input and internally it ran the extract + bundle and emitted the package in 1 step, so don't think it can be more efficient. I think @Aghassi is using some variant of the code I shared, perhaps that bundler can itself be built into the ruleset? :)

dzbarsky avatar Jun 28 '25 18:06 dzbarsky

I ended up writing my own but it's the same idea with the same problems. Needed to extract the names package target and then return a new target wrapped in an js library. This allowed me to modify the contents of the tgz and then pass it forward in the graph. Then use replace_package. The only gotcha is if you don't version scope the key in replace package it applies to every package with the name. Which can be dangerous.

Aghassi avatar Jun 28 '25 18:06 Aghassi