-
Notifications
You must be signed in to change notification settings - Fork 240
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
[RRFC] Pluggable script runners #691
Comments
cc @aomarks who created Wireit |
I'm incredibly hesitant around this given various feedback we are seeing around our I think working on that locking is at least our main struggle in this area as we are exploring things in a way that doesn't break existing workflows. Running with pluggable script runners means both opening up complexity for reproducibility and for still needing to understand failure cases of these tools. Certainly would like some kind of pluggable system, but we have likely greater needs for our work than just scripts. |
I don't think this introduces any new capabilities. You can already write standard npm scripts that delegate to a script runner, which is how Wireit works today. This proposal would make that more ergonomic to configure by package maintainers. I do agree that script runners need to carefully consider locking, etc., but this is already true today. |
Script coordination and locking does not need to be a feature of NPM in order to ship a feature like wireit that makes script ordering super simple to manage. Lerna and Wireit have both extensively proven this, and are extremely useful. Now that I've used Lerna (and intend to switch to Wireit) I can't imagine, for example, wanting to switch from either of those (with topological script ordering) to manually telling NPM the order of scripts and have to keep updating that when I refactor scripts. That would be a really huge pain in comparison to using Lerna or Wireit. Most of the time, people using this hypothetical feature will be managing a multi-project repo (monorepo, or repo git submodules) and if they have conflicts between their scripts they can solve that problem on their end, without resource locking being a requirement that blocks shipping something incredibly useful for NPM users. |
I tried out wireit @justinfagnani and I found that it didn't handle topological sort automatically. It wanted me to list out dependences between different pages in the monorepository manually when it was technically already in the package.json file. Instead of wireit, I adopted lerna/nx and it works great. My template project that makes use of lerna/nx is here: https://github.com/bhouston/template-typescript-monorepo |
Motivation ("The Why")
There are a number of tools, and a few RRFCs issues here (#190, #610 and #548) that relate to running scripts in series, parallel, etc.
The existing RRFCs are in some ways relatively simple, but the area of how and when to run scripts is quite deep and complex, and beyond what order to run scripts in, quickly gets into things like:
It seems like npm has a few options on how to proceed with more sophisticated script running, ranging from:
While I would love to see a great script runner built-in, I think all three of these options have serious downsides.
I'd like to propose an alternative that should be simple and allow for external project to extend npm script running capabilities, possibly creating well-worn paths for npm to adopt later, which is pluggbale script runners.
A script runner would be registered in a package.json file and get to intercede on running all scripts.
Ex:
Upon npm commands that invoke scripts, like
npm start
,npm test
,npm run
, etc., npm would call the runner with the script to run and command line flags.Alone, this doesn't enable much (though a runner could have flags run scripts of monorepo dependencies, etc), so we need a way to add more metadata about scripts for runners to consume. Letting scripts be objects instead of just strings would solve this.
With this additional information the script runner can now check inputs for changes, cache build outputs, and run dependencies or check that they're fresh.
Certain script metadata fields can be standardized, most importantly
"command"
which would be supported by the built-in runner. Other fields would be metadata for specific runners.Over time the
"runner"
field could be a place to opt-in to new built-in running behavior.Note that this is essentially building in more ergonomic support for what's possible today if you delegate all script to a runner manually. Wireit works on package.json configs like this:
I think explicitly carving out space for runners would discourage some of the fragmentation in the ecosystem where many runners have their own CLI that side-steps npm and creates a new thing to learn and barrier to entry for new contributors. The script runner approach keeps things fairly well-hidden behind plain npm commands.
Example
See above.
How
Current Behaviour
Currently scripts only execute the command given, and don't run in series, parallel, or with dependencies. Custom script runners have to be manually setup with their own script definition sections in package.json.
Desired Behaviour
Allow runners to bring the features of tools like Turborepo, Nx, Wireit, etc, but keep the external interface of the npm CLI.
References
Alternatives
An alternative would be to build the features of, say Wireit, directly into npm. I actually think this would be a great outcome, especially for workspaces, but I've been assuming that it's a bit to big of an ask.
The text was updated successfully, but these errors were encountered: