Dum: An NPM scripts runner written in Rust
github.com
github.com
If "written in Rust" is a clickbait, then most first page HN titles are clickbaity too otherwise why will you click on them? To me and most people, "Written in Rust" or even "Written in Go" reads like "it's fast" and that's definitely a feature!
The babel transpiling takes about 5 seconds compared to the 200ms of npm scripts startup time. Since I haven't felt this pain of npm startup times myself as a pain I must be able to state that without being interpreted as negative, don't you agree?
Of course, speed increases are positive over all but this requires me to install something just to gain 200ms from whenever I run an npm command which isn't that often. I am sure there's a lot of people out there who this benefits a lot but I haven't personally experienced this is my years of doing node development.
Sure, npm run isn’t my biggest bottleneck. But it’s noticeable, and becomes annoying a couple of layers of indirection deep… which isn’t that uncommon, especially in monorepos. Shaving 200ms off might not sound like much, but it really depends how often you’re taking that 200ms hit.
They've contributed so much work, and I think it's really cool that they're always diving in to solve problems and take a crack at alternative solutions. Mad props.
NPM is painfully slow, everyone's harping on the 200ms, for larger projects that number is much higher.
I'll be using this and happy it exists.
Agree on the negativity (surprising and completely unwarranted), but a nitpick: npm install is slow (this doesn't replace that). NPM scripts are generally very fast, unless the implementation of your actual script is slow (in which case it will be similarly slow with Dum).
(the Dum GH has benchmarks showing perf. gains for scripts, but the % improvement is only significant because the script doesn't do anything - the gains would be static for real-world use-cases, making the % gain negligible)
All that said, there are other very valid reasons to use Dum - limited, and containing a lot of caveats, but very valid all the same.
That seems like a pretty big performance problem on Node's part.
Wouldn't it be better if Node solved this, than people having to use external package managers that may not be so well-integrated into the ecosystem? Thirdly would people even bother using an external package manager because of a 200ms delay? Is that considered acceptable at this point?
In the meantime this is a practical, acceptable solution.
> Thirdly would people even bother using an external package manager
What do you mean? This tool is not a package manager, it is just a script runner.
Out of curiosity, what makes you say that?
> What do you mean? This tool is not a package manager, it is just a script runner.
Bah, sorry. I had PNPM in mind when I wrote that (which I highly recommend). PNPM doesn't explicitly focus on startup time, but it does majorly improve performance as it caches packages.
On top of that, `npm` similarly has a high startup cost adding to the original node cost.
Node apps are very slow to start to run due to synchronous `require` eager-loading all the module files, so there is some re-architecting necessary to get a performant startup time
yarn v1 is probably the best of the bunch with startup lag close to pure node (100-150ms)
yarn v2 and up can be extremely bad, 1s-3s with medium to large repos, especially with PnP enabled which AFAIK forces eager resolution.
pnpm similarly has had troubles starting up quickly. It used to be even slower as it passed the command to `npm` in a suboptimal way. Nowadays its about the same speed as `npm` as it uses `npm` for `run`.
Node's working on it.
Just spent a few minutes checking NPM's startup code. For a total run of ~234ms, it spends:
~50ms loading a version-parsing lib, loading JSON metadata containing Node binary version and checking node binaries against some hard-coded compatibility data. Dum doesn't seem to do any such sanity checks, which may be fine if you manually ensure your environment is correctly setup.
~25ms initiating logging (& exception handling). This seems like it could be improved.
~40ms loading config & 2 external dependencies (`which` and `graceful-fs`) - not sure if the config is the reason for slowness. The dependencies bring functionality Dum doesn't seem to need as much as NPM does. I guess the load-perf of the dependencies could be improved, unless it's the config loading causing this.
~80ms checking for updates!!! Absolutely no need to do this on every run - this could be throttled somehow at the very least.
The remaining ~40ms is actually running the script
---
Update: After looking more closely, it appears the update checking code doesn't actually run every time - it's taking 80ms just to load that code (without doing the actual check - the check is cached)
Nowadays, we have esbuild and a whole suite of other tools that run in <10ms, so a slow startup time is dreadful.
Git hooks as someone mentioned below are a good one.
It absolutely was an honest question, and nitpicking on my intent to imply I think this project is silly seems a little unnecessary: I don’t, and really do want to know what it could help with, as none of my use cases need it right now. I’d like to keep any eye out for when they would though.
Run tests and linter on-save. Have vim with LSP and other tooling, startup fast enough to close and re-open the entire editor, rather than background (<CTRL>-z) or alt-tab. Just do a <CTRL>-c<CTRL-p><enter> to reload any changes in a running dev server, rather than tooling that attempts to listen to io-events and reload the code magically.
There are loads of small things that become a lot simpler when kill&start is just as fast as "internal reload".
Which initially is not too bad, but the bigger the codebase gets and the more often you run it, it adds up. 300ms per invocation is something that a lot of CI providers would love to save.
Relevant XKCD: https://xkcd.com/1205/
> "test": "NODE_ENV=test mocha --reporter spec"
(and doesn't work across platforms like windows)
Or added functionality like being able to pipe the output to multiple places (eg. terminal and log file).
That would offer perhaps a slightly more compelling use-case than saving 200ms; I don't care about that much, I honestly doubt anyone else does either.
The spawn time for an npm compared to the runtime for an npm task are orders of magnitude different, surely, for any non trivial task.
"start": "NODE_ENV=production node ./index.js"
To... "start": "cross-env NODE_ENV=PRODUCTION node ./index.js"
I'm glad Yarn supports this natively, though. It seems silly to rely on an external package for something so basic (especially with the security vulnerabilities of the ecosystem as a whole).Which is why I recently kicked all the cross-env out of my nodejs projects and replaced it with Ruby's dotenv[0] (in projects that already used ruby alongside) and zenv[1], in Rust for projects that don't.
Basically
"start": "zenv --file .env.production -- node ./index.js"
[0] https://github.com/bkeepers/dotenv
[1] https://lib.rs/crates/zenv (readenv is an alternative, but that doesn't allow overriding the .env file)https://old.reddit.com/r/AmongUs/comments/iyg093/is_it_on_pu...
For me it is a serious nag. And I come from Ruby, where, with Rails, startup time is abysmal. So I am used to something.
Don't people use the watch options so they don't need to interact with the app to have it rerun things? I don't think speeding up how long scripts take to start will change that.
Same for (re-)starting webservices and such. And when not available or applicable in my editor, GNUtools, bash and unix offer plenty of tools to easily do this for me. E.g. https://linux.die.net/man/1/inotifywait to fire a command (e.g. restart a service) on changing files.
I presumed these `--watch` where there to solve the slow-booting issues only (like in Rails) but maybe they are there because someone didn't know their OS and DE could do it for them already and decided to build it into the suite or tool instead of using existing tooling?
You should look up what "git" means in English :)
This is one of those people who just constantly pump out so much open source code. I remember looking through their profile when I was using EME years ago (2017?), wishing I had the time to do half of what they were tackling.
From a quick glance, it looks like this could have been implemented in any native language. I like Rust as much as the next guy, but using it to get clicks when Rust specifically over another native language doesn’t make a difference feels a bit clickbaity.
Libraries or tools written in C++ interest me less personally, because they're more work for me to integrate into whatever I'm typically doing, but I can see that someone working in C++ might like such things to be labelled the same way for the same end.
*Angry Oberon noises*
it looks like this could have been implemented in any native language
I use this 30 line bash script, with a dependency on jq. It works for me, and is pretty much instant.no
> using it to get clicks when Rust specifically over another native language doesn’t make a difference feels a bit clickbaity.
- every single article mentioning rust in any way has this complaint in the comments
- I think that much of the reason people mention it is not a cynical ploy for clicks (though that exists for sure), but denotes that the program is a modern program that is likely to work in a certain way? It's hard to specify what that way is, I should try and write something about it, but I think people who complain about this are missing that it's kind of a cultural signifier more than a literal statement about the language it's written in.
* It is probably fast.
* It is almost certainly very easy to install.
* If anything is missing or broken I can probably fix it myself.
There are a few projects that tout being written in C++, but it has never been a regular "selling point" in HN, because HN was a thing almost 2 decades after C++ was the "new hotness".
So, we've seen it for Node, Rust, and Go more.
>I like Rust as much as the next guy, but using it to get clicks when Rust specifically over another native language doesn’t make a difference feels a bit clickbaity.
You think this person spend weeks writing this for "clicks"? Unless the author posted it, they might not even know it was posted on HN (it's often the case with posted projects: someone else finds them and posts them).
They had a pet project in mind, they liked Rust and wanted to use it, they did.
from the readme: "How: This is written in Rust! (Or any compile-to-native language)."
https://hn.algolia.com/?query=written+in+c%2B%2B
https://hn.algolia.com/?query=written+in+python
https://hn.algolia.com/?query=written+in+go
https://hn.algolia.com/?query=written+in+rust
EDIT: There's one exception. "Written in bash" is and will always be clickbait, fight me
Rust answers some of those implicit questions in a way that is acceptable to a lot of us.
Notepad++ maybe?
"Written in Rust" is the new "Sent from my iPhone".
it doesn't matter that you have the thing re-written in Rust, because there is no reason for such thing to exist in the first place.
It's much more convenient to type `npx something` than `./node_modules/something/bin/something`, for example. Especially so when folder names are not obvious.
package.json is such a sloppy and arbitrary place for your scripts. I don't know how the creator of node looks at the mountain of things that are all in package.json and thinks that's a fine design. You are a package manager, stick to it.