Yarn – A new package manager for JavaScript
code.facebook.com
code.facebook.com
I loved Bundler's deterministic builds but chafed against the Ruby limitation of only having a single version of a dependency at once. npm solved this problem elegantly, but still struggles with non-determinism. I had resigned myself to thinking that maybe these were just fundamental tradeoffs in package management that could never be resolved.
Then I had the opportunity to use Cargo, the package manager for Rust. It synthesized what, in my mind, are the best features of npm and Bundler into a single package manager, with terrific speed to boot.
Yarn looks like it will be Cargo for JavaScript. After Cargo improved on many of the great ideas of npm, those ideas are returning to help improve the JavaScript ecosystem. Cross-pollination at its best.
This also highlights a shrewd move on the part of npm: a clear decoupling between the npm registry and client, with a well-defined protocol between the two. The strength of Node is in the staggering size of its ecosystem; how those bits end up on disk is an implementation detail. This smart separation allows for this kind of experimentation on the client side, without causing the ecosystem fragmentation that happens when a new package manager requires a new registry.
I'm also happy to see that a significant amount of work has already gone into the governance model. Despite the largest contributors being Facebook employees, it looks like they've really outdone themselves making sure this is a community-run project. A BSD license, no PATENTS file, and an Ember/Rust RFC process[1]; this has all the hallmarks of a community open source project. That's critical for open infrastructure projects like this, and they've nailed it.
[1]: https://github.com/yarnpkg/rfcs
I'm very much looking forward to using Yarn in my own projects because it looks like it solves a lot of real problems I encounter every day. Thanks for all the hard work!
But at least it's a move away from NPM. I think the most problems I had with JavaScript develompent in the last 2 years came from NPM.
According to http://blog.npmjs.org/post/151660845210/hello-yarn, it seems it doesn't work with private packages yet, which may or may not be an issue for your project. But it seems this is a complete CLI replacement for NPM.
I personally don't know much about either tool (don't do a ton of JS), but it's possible that fixing the existing client without either breaking backward compatibility or making it too complicated (multiple modes of operation) was too difficult or not worth it.
Also, I'm having a really hard time understanding the complaint about a new client. The value is in repository of reusable code, not the client. That you can use different clients with the same repository is a feature, not a bug.
These issues have been raised a few times, along with the shrinkwrap/reproducability stuff, and it didnt seem like it was a big priority for the core team. Understandably I guess they seem more focussed on the enterprise/private repo side of things and just keeping things running on the client side.
npmjs.com = package repo which Yarn can use.
at least as far as I can tell
Also, npm isn't deterministic and it got even worse with v3. Sometimes you get a flat list of libs, if a lib is used with multiple versions, the first usage will get installed flat, the rest in the directory of the parent lib, etc.
The npm-cli is basically a mess :\
What we do currently is we lock everything to an explicit version - even libraries.
At least it's possible to get deterministic builds if you are willing to do a bit of work carefully / manually updating all of your dependencies at once.
This means your library tests will not be deterministic.
Using the Cargo.lock file for libraries does solve this, but then every binary package you build that references your library will have to be specifically tied to the versions in the library.
We do this internally because it's the only way to provide deterministic builds over time.
Over time I suspect it will get harder and harder to keep this rigid web of dependencies working.
One thing we might try is to enforce the rule 'no library will contain any tests'. At first glance this kinda makes my skin crawl, but maybe if we could find a way where every project that used a library could somehow share the tests for that library it could actually work.
git submodules might actually be able to provide these tests for each binary package. If only git submodules would stop corrupting our git repos... :-(
Anyways you can put a lockfile with your library, and it shouldn't affect downstream.
this obviously doesn't fix anything and I think the points in this discussion stand, but I've never understood why the defaults are not more conservative in this regard.
JS dev has been a minefield like that, the entire ecosystem reminds me of C++ except lower barrier to entry means a lot of noise from newbies on all channels (eg. even popular packages can be utter crap so you can't use popularity as a meaningful metric)
You can do the same kind of version range tricks in typical Java builds, for example (Maven), but most people hardcode the values to keep builds as deterministic as possible.
For some reason, the JS community seems to prefer just trusting that new versions won't break anything. Its either very brave of them really (or maybe just foolish).
I don't think Yarn solves any of these problems, tbh. It seems like what we really need is a package manager that tests the api of each package update to make sure nothing in it has broken expectation in accordance with Semver.
Let's not pretend that we aren't all blindly tossing in random libs of dubious quality and origin we find on github into our package.json and hoping for the best anyway. My company talks a mean talk about "best practices", but, my god, the dependencies we use are a true horror show.
Say that I use yarn to depend upon some module X, specifying a fixed version number like the good boy scout that I am. Module X resides on npmjs and in turn depends upon the bleeding edge version of module Y. And then one day module Y goes all Galaxy Note and bursts into flames.
Can yarn shield my app from that?
You can do (and are supposed to do) the same with npm's own shrinkwrap, but people claim that it doesn't work as intended.
It's not that npm devs were naive enough to believe that unpinned deps would be safe for reproducible builds.
However I've heard several people allude over the years that 'npm shrinkwrap' is buggy, and isn't fully reproducible (though never experienced any problems personally). This is the aspect yarn claims to address, along with a supposedly more succinct lockfile format.
From a build tool perspective (we use npm scripts for basically everything [and some webpack]) I am also not missing something particular.
Looking at other comparable solutions (from other languages) I'd say npm does a pretty good job.
but it still far from perfect.
And if you want to lock versions for your entire dependency tree, npm shrinkwrap is what you're looking for (It's essentially the same as lockfiles in other development package managers). Though for security reasons I prefer to keep things locked to a major version only (e.g. "^2.0.0"). Shrinkwrapping is useful in this instance too if you need to have predictable builds (and installs as it'll use the shrinkwrap when installing dependencies too if it's a library rather than the main app) but want to ensure your dependencies stay up to date.
It's not perfect by any measure, but there are ways to make it work the way you want.
The problem isn't really fundamental. Bundler makes almost all the right choices already. Its major disadvantage is that it only works for Ruby.
What it _won't_ let you do is pass a v1.0 type to something that requires a v2.0 type. This will result in a compilation error.
There's been some discussion around increasing Cargo's capacity in this regard (being able to say that a dependency is purely internal vs not), we'll see.
That alone has me super excited about Yarn, before even getting into the performance, security, and 'no invisible dependency' wins.
Yarn does offer a `--flat` option that enforces the highlander rule, and I'm hopeful that the existence of this option will nudge the ecosystem towards an appreciation for fewer semver-major bumps and more ecosystem-wide effort to enable whole apps to work with `--flat` mode.
Plz send halp!
So go crazy and install every version of lodash! Nothing will break.
Edit: I haven't dug into this, but it might be possible to use Typescript namespaces to distinguish a and b's versions of x. https://www.typescriptlang.org/docs/handbook/declaration-fil...
If a depends on x v1 and exports this dependency then your application also imports x v1. If b depends on x v2 and exports this dependency too that means your application is transitively importing both x v1 and x v2 which is not possible.
If a or b only use instances of x internally and do not accept instances of x as parameter or return an instance of x they don't have to export their dependency on x.
If either a or b do not export their dependency on x then there is no problem. Your application will only depend only on x v1 or x v2 directly.
There was actually a high profile bug when someone ended up with two versions of react included in the same page: https://github.com/facebook/react/issues/1939.
I'm not a React expert, but I don't see why that situation would only affect multiple React copies with different versions?
It's placing your own release cycle at the whims of your dependencies' release cycles. In the corporate world that would not be a viable solution.
For instance, when using gemified javascript libraries with bundler it is painful to upgrade to a different version of a javascript library for the user facing site while letting the backend admin interface continue using an older one for compatibility with other dependencies.
If so, different major versions of the same dep should be considered different libraries, for the sake of flattening. Consider lodash for example.
Personally I'm not really sure I like it. If I specify an exact revision of something, chances are I really do mean to install that exact revision. I don't see why I need an extra flag for that.
* LA: handles linear algebra and defines a matrix object.
* A: reads in a csv file and generates a matrix object using LA
* B: takes in a matrix object from LA, and does some operations on it
In this case, if B depends on version 5 of LA and the new version of A depends on version 6 of LA, then there's going to be a problem passing an object that A generated from version 6 and passing it to B which depends on version 5.
* Figure out early on (before 1.0) what your base interface will be.
For example, for a promise library, that would be `then` as specified by Promises/A+
* Check if the argument is an instance of the exact same version.
This works well enough if you use `instanceof`, since classes defined in a different copy of the module will have their own class value - a different unique object.
* If instanceof returns true, use the fast path code (no conversion)
* Otherwise, perform a conversion (e.g. "thenable" assimilation) that
only relies on the base interface
Its not easy, but its not always necessary either. Most JS libraries don't need to interoperate with objects from previous versions of themselves.However, since A exposes outside methods that take a matrix as an argument, it should not assume anything beyond the core interface and should use LA-6's cast() to convert the matrix.
The problem is partially alleviated when using TypeScript. In that case the inferred type for A demands a structure containing the `normalize` method, which TypeScript will report as incompatible with the passed LA-5 matrix (at compile time). That makes it clearer that `cast` would need to be used.
Another solution is to provide version overrides and make B depend on version 6.
However if there are differences in the matrix class between different versions of the library then you're forced to write a compatibility layer in any case.
And a shrewd move by FB: to not announce their new registry on the same day.
Time will tell whether they only want to be proxying NPM or will allow direct pushing to their own registry. If they do, JS ecosystem might see another big shift.
So I don't think interests will ever align to create a new registry. Nobody wants to do that. That would have serious consquences for the JS community and would take years to recover, in my opinion.
For example, if I refer to 'left-pad', it would default to 'npmjs.org/left-pad'. If the author goes rougue, I think it would be great to enable people to publish and consume 'thirdparty.com/left-pad'
Disclosure: I'm a FB employee with no knowledge of our plans in this regard
2. you can already have your own version of thirdparty/left-pad by maintaining your own npm repository. i think what your parent post is referring to is facebook saying we're going to make our own public node/javascript package registry and you should publish to our registry.
doing this at the moment does nothing for the community other causing a lot of pain points. ex) now npm authors will have to publish to both registries so developers don't have to dig to find where it was published to, then they also have to hope that someone else didn't register the module name in one of the registries..
there is just too much splintering if facebook decided to become a competing registry rather than just using npm's registry and building on top of it.
Only to resurface again: http://status.npmjs.org/incidents/dw8cr1lwxkcr
And it will, no doubt, resurface again and again and again
Possibly not soon, at least from a technical perspective, but I could definitely see a PR fiasco (security, bias, etc.) causing a loss of confidence in its stewardship.
And I don't think it'd be that big of a disruption if it were to happen; for the hypothetical case of Facebook+Yarn, they're already proxying to NPM, so they could easily continue to do so while also accepting packages that are Yarn-only.
- strictly defined version update time intervals, e.g. you can't update your package more than once a week (or have to take some special actions for critical updates, e.g. contact support)
- "delayed" publishing, e.g. when you submit your package it will only be published in 24 hours, until then you can re-submit updates, etc.
- similar to above, but your package wont be published until it was tagged on github (or elsewhere) for a certain amount of time
- published packages can not be removed, but you can disassociate them with your account by marking them as "not maintained" and possibly assign new maintainers for it
- maybe introduce some way for developers to mark new versions as "backwards incompatible" if they do break backwards compatibility
I think there is definitely a "market" for some stricter node package repo.
This is due to the way that Ruby includes code, where it's available globally, vs Node where code is scoped to the including module. I'm not sure how Ruby could support multiple versions with changes to the language and/or RubyGems
* Partly, there are a larger number of Javascript developers that haven't been exposed to other ecosystems, and end up reinventing some wheels
* More importantly though, I think the pace of innovation in the javascript ecosystem is actually good in a way, because other more mature languages (I'm not talking about age of the language, just maturity of the tooling and ecosystem) have gone through the same growing pains, it just took a lot longer. It's easy to forget, coming from the Python world for instance, the pains of easy_install and distutils vs seuptools, etc etc. I still find Java dependency management a bit of a pain, because I don't know it very well.
We're just watching a sped up version of a language maturing, and it's painful as individual developers trying to keep up, but I don't think it's as negative as HN often makes it.
1. In the browser we have less control over the environment the code runs in, requiring tooling to achieve a stable, normalised environment which we can improve at our own pace, rather than the rate at which browsers are updated.
2. JS has become very widely used very quickly, which means that there have been lots of hastily built things, which have been replaced by better things (and for every 'better thing' there are many alternatives which fell by the wayside), and a larger pool of people to build them.
3. It's easier than ever to build new tools (or any kind of app, for that matter), because the npm ecosystem makes it trivial to combine existing smaller pieces of code into new combinations.
It does take some getting used to, but when you stop looking for one big tool that can solve 5 semi-related problems, and start looking for 5 little tools that each solve one of the problems, things get much more clear.
And yes, I know that this kind of reliance on dependencies can cause issues, but from my experience, those issues don't seem to bite that often, and many of them can be resolved with even more tooling.
don't forget about mobile devices, with ios having such a difficult-to-write-anything-new version of mobile safari.
i'm writing a new app for myself, so i don't have to worry about any backwards compatibility issues, except it needs to work on my iphone, which uses mobile safari webviews, which means i have to either use shims or restrict myself back to es5, non-html5 features (or work around their html5 limitations).
example: you cannot cache audio files to play using <audio> tags in mobile safari. safari just refetches it from your server (also has to recreate the audio object, which causes a lag in the audio being played). technically you _can_ cache if you convert all your audio files to base64 and use the webaudio api. i'm probably going to have to go this route because i'd like the app to be offline usable.
so rather than spend time on my app, i now have to write out a build step for converting audio to base64. then test that it works fine in ios and desktop browsers (at least chrome, firefox). it all just keeps adding up.
Node libraries are typically several orders of magnitude smaller and more single purpose than java libraries. Java libraries like Guava and Spring are typically quite large. A practical example is from unit testing: In Java, you might use JUnit+Mockito for your test dependencies. In Node, to get similar functionality, I have the following deps: Mocha, Sinon, Sinon-As-Promised, Chai, Chai-Moment, Chai, Chai-Things, Chai-Shallow-Deep-Equal, Chai-Datetime, Sinon-Express-Mock, Supertest.
Many Javascript applications both client and server functionality, and there is different tooling for both. Webpack is currently popular for building stuff that will run in the browser, whereas server side stuff is different.
It's a much newer technology than java and there is quite a lot of churn around tooling in general as the nature of the way applications are built change.
Similar with http://mithril.js.org/ over React, Angular and Ember. A single drop-in library with 13 functions in it's API. The library itself is a single, understandable source code file. Mithril is pretty much the exact opposite of Angular and Ember.
A lot of front end devs are eschewing frameworks completely. With modern DOM and web APIs, you can do a lot with "just" vanillajs.
I didn't add sinon-as-promised for fun, I added it for in-memory sequelize integration tests. same for all the other libraries I mentioned.
My point is that by keeping libraries small, you will end up with either more dependencies, or a lot more hand-rolled code. Neither of these things are inherently bad or good, and I'm not defending them. What I am trying to do is explain to the commenter why the node ecosystem seems to have such an emphasis on package management and the tooling around that.
As an example: you _could_ have one SpockJS framework that gives you React + Redux + ReactRedux, but instead each of these libraries are separate so you can use them without each other. This allows you to, say, move from React to Angular without changing the state of your application.
With everything moving so quickly in JS, this separation turns out to be valuable enough to tolerate a lot of packages and dependencies. It also makes it easier for communities to exist for solutions to specific problems, which at least in theory results in better solutions.
It's not necessarily better, just a different approach.
Like I said, it's not better just different.
Strangely enough both Java and JavaScript were first released in May 1995. Server side JavaScript was released the same year just after the browser version.
Though I get that you are referring to the js eco systems (commonjs, npm) compared to the much more mature Java ecosystem.
C/C++ tooling is a plastic butterknife you get with airplane food.
There are tons of libraries for C, many of which aim to do the same, only faster/smaller/scalable/whatever. There are many compilers, both open and closed source. And there are documentation tools, syntax checkers, unit testing frameworks and whatnot.
Of course there are also languages like C# where there’s a de-facto standard for almost everything: IDE, compiler, base library, GUI framework(s).
I think choice is great!
Because, from this outsider's perspective, it seems like most of the tooling is library management (rather than, say, profiling or linting -- does javascript even have a linter? -- or debugging).
Yes, as libraries. There are multiple linter options that can be installed with a project. Debugging is available, usually through an IDE or browser.
There are tons of tools, of course also including jslint, debuggers (e.g. IntelliJ, dunno about others). There are editors and even IDEs. Then there’s the problem of bringing (NPM) modules to the browser using tools like webpack or SystemJS or whatever. There are general purpose build/automation systems like gulp. There are transpilers that “compile” ES6 to ES5. For any given task, you can probably find at least five programs that do it.
And if you look at all the topics, you’ll find that library management makes up only a small fraction of everything.
Yes, thousands of them, npm alone has 1200 results for linter:
There are various packages that are extremely small (see leftpad and associated controversy). They often wind up in a slightly larger package, which itself winds up in a slightly larger package, which recurs until you finally wind up with one actual package of consequence that you're targeting. For example, Express (a very common Node.js abstraction) has 26 direct dependencies, yet 41 total dependencies.
A lot of this results from early Node.js' mantra of having small, focused packages. This could potentially be a good thing because instead of having three major dependencies that have their own way of leftpadding they can all rely on one library and thus code is efficiently reused. This can be bad, however, when they each need their own version of the dependency - or worse - the dependency is removed from the registry (see Leftpad and associated controversy).
One of the legitimate problems that I've seen is that there are various libraries that are just thin wrappers over functionality that is native to Node.js - but written to be "easier to grok". Thus, these thin abstractions become practical code duplication out of some mixture of Node's developers lack of effective verbosity/documentation and application developer laziness. But then they creep higher up the dependency chain because someone at a lower level used it.
On one hand it can be quite simple (and rewarding) to write code while minimizing dependencies. On the other hand, abstractions such as Express make it very easy to write code and it feels like you only have "one dependency" until you look under the hood.
Babel, the most popular transpiler, is 335 total dependencies, and it doesn't even do anything out-of-the-box. You need to add babel-preset-latest for 385 total dependencies if you want to actually transpile anything.
Want a linter? ESLint is 128 total dependencies.
Yes.
> Are there aspects of the language or runtime that reward multiple layers of configuration management?
A significant fraction of the node community likes to split their project into really, really small packages and treat them as if they're independent even if they come from the same source repo and tend to get used together. As an example, the popular collection processing library Lodash publishes a package for each method and people actually do depend on individual methods.
There are two major rationales for this. The first is that JS is a dynamic language and in dynamic languages, smaller chunks of code are easier to reason about than larger ones. The second is that the JS community as a whole cares more about artifact size than pretty much any other community. Having smaller packages allows you to produce a smaller payload without having to rely on techniques like tree shaking.
I find micro packages maddening but people give me their code for free and it mostly works so I don't complain about it that much.
It really isn't. The NPM client is just really, really poorly written, with no parallelization to speak of.
Not really. The npm client is just flaky, very slow, buggy, has some major design flaws in its v2 incarnation, and has a completely different set of major design flaws in its v3 incarnation.
The core architecture works fine for small packages.
> Seriously up to now it was impossible to have a build server isolated from the internet if you didn't want to check-in all the dependencies
Of course not, although I admit the linked article implied it was if you didn't read closely. There's a wide number of solutions, including running a private registry, or a copy of the public registry, or a local cacheing proxy of the public repository, or a custom npm client that hits a local cache, etc. Some of the solutions work quite well, and in fact yarn itself is just a re-implementation of some existing solutions.
> I really can't understand how people can even think to use a dependency manager system that doesn't satisfy the essential requirement of having your CI server sandboxed.
As the article noted, Facebook was sandboxing their CI server and using NPM; they just didn't like the existing solutions. (Nor should they; they were a bit naff.) But that doesn't mean (nor is anyone claiming) that there were no existing solutions. Yarn looks great, but it's an extremely incremental change.
All of this is why people are excited about Yarn, but to me it's a band-aid on several architectural mistakes.
Just say no to frameworks. Just say no to ES6 and transcompilation. Just say no to asset pipelines. Viva la JavaScript. Viva la Netscape. Viva la Node.
For browser work, you can do almost everything you need with some jQuery, handlebars and moment if there are dates. A few other small libs here and there and you've got almost everything covered. Some edge cases may drive you to use some library that is heavily dependent on 32 different sub-libs but it's really not that often.
Server-side Node.js is the issue, not browser compatibility.
Now imagine Office 365, the same software with the same functionalities, except running in the browsers. The task is to essentially write Microsoft Office (front-end logic) entirely in JavaScript (or TypeScript), with the additional problems of dealing with browser compatibilities issues, which are just as hard as OS compatibilities issues.
Then, imagine all the software going to the "cloud". JavaScript now has to have the capability of re-writing all these software originally written in C++, C#, Java... all sorts of languages. It is quickly becoming a superset of all ecosystems where everyone is trying to migrate their software to. So it is not surprising that people are inventing more and more tooling to make it more powerful to suit their needs.
Yes, because the standard library provides practically nothing useful in itself.
Add those together, and you get the need for real complex tooling.
With that said, tooling is nowhere as complex as it is for languages like C++ or Java. People are just used to it on those platforms, and the tooling is more mature/understood because it already went through the countless iterations, 15-20 years ago or more.
Java isn't too complicated either. I've used Gradle and Maven but doing things manually like in C++ can also work.
Crucially, they don't reinvent the wheel every couple of months so a C++ or Java dev can focus on building things instead of relearning how to build things.
TLDR:
- open, community governance that will support long-term evolution
- the technical details get a lot right out of the gate (decent performance, predictability, and security)
npm chooses the first version of a package it encounters to install at the top level. Every other version is installed nested. If you have N uses of version A and one use of version B, but version B is installed first, then you get N copies of the package at version A.
"$(npm bin)/bin-cmd" is getting really old
Absolute and utter hogwash.
I don't even need to get into versioning to make this argument but I'll exclude it for clarity's sake. Simple scenario:
root -> A
root -> B
root -> C
A -> B
B -> C
What folder structure is created? root/node_modules/A/node_modules/B/node_modules/C
root/node_modules/B/node_modules/C
root/node_modules/C
Symlink that all you want, how is it in any way whatsoever thoughtful and elegant? It's not a real solution by any stretch of the imagination. Myriads of pre-existing systems that correctly deal with this scenario existed at the time that NPM was concoted. Ignored. Considering that node is touted as a cross-platform solution, how well does version@3 deal with filesystems that don't support symlinks? I've run into this: not at all.NPM version@3 could not be further from the ethos of "engineering." It's an outright hack, and it quickly betrays its limitations. It could have been far simpler, far more considerate of pre-existing wisdom.
Just tried using npm3 explicitly and I stand corrected.
http://yehudakatz.com/2016/10/11/im-excited-to-work-on-yarn-...
> unless you've actually shipped a product using this tool
Given that wycats _worked on_ this tool, I would assume it's his experience helping build it that's the basis of the claim.(I don't work at Tilde so I can't tell you if it's been shipping with yarn, but it would shock me if it wasn't.)
Are there any branches of ember-cli implementing yarn?
I'm sure this will be added in the future, but it is currently a dealbreaker for me - I'm using a single package that's just straight hosted in a private git repo, as the package itself isn't ready to be published yet. I'm sure other people are using private packages for more normal reasons (closed source, pre-production, etc).
If yarn actually made it simpler to refer to a local package during development, I'd be on board with that. (I am developing the dependency, but want to also work on the thing that depends on it, so I'd rather just save locally and refresh npm on the outer project, but that's hard to get right - file urls don't always update, the easiest workflow seems to be delete the package from node_modules, and npm install, with the package having a git url rather than a version in package.json).
I agree local development with many packages can be hard. For Jest we adopted `lerna`
See https://github.com/facebook/jest and https://github.com/lerna/lerna which makes cross-package development in a mono-repo a lot of fun. Maybe that solution will work for you?
With npm I've been frustrated a few times whereby you can fork the repo and point package.json to the git repo but after running npm I usually get a bunch of compilation errors.
It would be wonderful to make this as simple as with bundler within the ruby ecosystem, point to forked url and running yarn handles the rest.
That's insane. It wouldn't surprise me if yarn becomes popular and its proxy to npm slowly turns off and boom, everyone would be migrated and npm would be left with little to no users. Yeah that's probably unlikely for the immediate future but Yarn is positioned perfectly to siphon off npm's users very painlessly.
http://blog.npmjs.org/post/78165272245/more-help-with-selfsi...
I think it's a great example of moving a little too quickly, honestly. Especially since it bricked plenty of npm installs instead of being "just another bug".
I love the service they offer. Not a fan of the tools or pace. Npm comes in the node installer so why do they even have to care about improving?
Just my thoughts.
So today by default yarn goes through its servers which then proxy to npm's. As time goes Facebook can add more features to its own repo (custom submissions instead of to npm or maybe it does a federated publish to both at first, nice looking pages with community engagement tools built in, better metrics (npm provides me with almost worthless metrics), etc). Then when enough people are using Yarn Facebook could simply...flip the switch. Then boom, zero npm usage.
I would be terrified if I were NPM right now. They've sat on their hands for years not improving npm. I mean npm3 had a silly CLI animation that made all downloads take orders of magnitude longer simply because of the animation!
P.S. if you're trying to use yarn with a custom npm repository just drop a .yarnrc file into your project's directory then add the following in that file:
registry "http://<my register>"
From their perspective it's very difficult to make breaking changes to the client because of the sheer number of people depending on them. (We've faced similar problems on Babel)
Yarn still makes use of the npm registry and all the high quality infrastructure they've built and support they provide for the ecosystem. They are a critical piece of this.
Granted it's far too early to write npm off. But with how slow they've moved over the years I'm unconvinced that yarn won't take over the space unless it runs into some bad problems. Npm 3 and its launch was an absolute mess and, ultimately, it's almost just a package managing tool. I am unconvinced that breaking changes is much of an issue if at all for them. They could abandon shrinkwrap into a better system and I think everyone would be happy for it; no need to keep propping up that awful system.
Would they, though? If Yarn turns out to be the better tool that doesn't change the way they work (beyond solving some pain points) then would they even care? Facebook could even offload the hosting to some open source group like Apache.
It's purely anecdotal but a lot of people I have worked with would love to see an alternative to npm. It's just slow and the features it gives to authors is pretty limited (I want better metrics, please!). I'm not even sure I would call it sketchy, it would just simply be phasing out something deprecated (I'm not talking about a swift take over more like a slowly-boiling-the-frog-in-the-water takeover).
It's only my opinion and if Facebook really doesn't want that to happen then I guess it won't but it's pretty easy to imagine it, IMO.
When did it start becoming reasonable for a front-end only part of the MVCC pattern to have 68 dependencies?
Or for a transpiler like Babel to add 100k+ files? I'm sorry I just find it ridiculous that instead of taking a look at the disease (unbounded complexity), we are looking to engineer our way out of the problem by creating a package/dependency manager that "scales". Are the frontend problems at Facebook of showing HTML forms and buttons on a page really that complicated to warrant such a behemoth of a system?
This harkons back to the days at LinkedIn where I spent my time in a misguided effort to create a distributed build system because our codebase had grown so massive that it literally took a distributed system to build it and still release within the day. I feel bad for people working on these systems because while it is fun and "technically interesting" to solve "problems at scale", you're really just digging the ditch deeper for your company. You are putting lipstick on the 500 lbs pig; making room in the dump to pour in more technical debt.
I don't think anyone ever imagined we'd be in a situation where a javascript framework is approaching the complexity of an operating system in terms of individual source files and SLOC.
Just boggles my mind.
Absolutely: this is overkill for your blog or portfolio website, but part of the rising complexity with the tooling and dependency system is due to the rising complexity of the applications themselves.
Do any other software platforms out there face the same magnitude of complications?
To speak to one of your primary examples: Babel is freaking huge and somewhat absurd, but is there any other way to advance the Javascript language? Fortunately, this is only a development dependency, and the client doesn't have to see it.
On a happier note, these are good problems to have. This is another indicator of how successful the web platform has become. You can build some absolutely incredible projects these days, and they are instantly available to billions of people who are operating thousands of different hardware devices (with different specs and dimensions) running dozens of operating systems. No gatekeeper, bureaucrat, or corporate curator must approve your work. Just simply deploy it, and anyone with the URL can access it. It is a mind-blowing human accomplishment. I look forward to seeing how the web continues to progress over the coming decades.
Initial thoughts:
- Why didn't Facebook contribute the updates to NPM directly?
- They are coupling a package manager and registry proxy; the latter has many existing implementations already
- The differenced between Yarn and NPM+Shrinkwrap do not seem substantive; NPM made the design decision to use a sometimes non-deterministic install algo in NPM3 to speed up install times - when network is involved, there is a serious trade off between idempotency and speed
In general, FB seems to love building their own versions of existing tools:
- Flow, introduced 3 months after TypeScript
- Nuclide instead of Atom/Sublime/VSCode
- Jest instead of Jasmine/Mocha
- DraftJS instead of (insert of of the existing 100 text editors here)
- ...
I get that these are useful internally at FB, but I don't think they help the community much. It would be better to work with existing tools and contribute back to them than to reinvent the wheel every time something doesn't work perfectly for their use case.
I get that FB uses these as recruiting tools, it's useful for them to have rights for these projects, and it gives their engineers something to do and be excited about, but I do not want a whole dev tool ecosystem controlled by big FB.
Also, I find IED's approach to speeding up builds far more novel and interesting - https://github.com/alexanderGugel/ied
Let me explain that a little bit... The javascript "ecosystem" takes the unix philosophy to the extreme in many ways. And one of the points of the unix philosophy is to try to avoid "bloating" tools with tons of options, and instead trying to create new tools where appropriate.
Many of those are perfect examples of where "improving" a current tool with the changes they wanted would end up with a more complicated and difficult to use tool.
- NPM makes tradeoffs that the majority of developers in the JS world want right now. Like it or not, deterministic installs isn't something that most people want or need (at least, they don't know that they might want or need it). Making a new tool that anyone can use when that is needed is a great solution, and it avoids bloating NPM with a hundred little flags and tons of code to cover edge cases. It's the perfect example because anyone can switch to using yarn when it's needed without any extra work.
- Nuclide is actually just a layer on top of Atom. They wanted a bunch of things to all work one way, so rather than try to get Atom to change to include what they wanted, or require developers install a ton of extensions, they packaged them up on top of Atom as one system.
- Jest had different goals at the start. Testing react components was ugly and difficult, and Jest wanted to solve that first (IIRC, i'm not very familiar with jest unfortunately). Again, it's something that can be used if needed, and can even be combined with other testing tools if you want (we almost did that at my work, used Jest to test the front-end components, and our current mocha+friends setup to test the "business logic").
Bullshit, nix systems rely on stable global dependencies, not 50 versions of the same library installed locally. I don't buy the "unix philosophy" excuse. The nodejs community just doesn't care about API stability which is why there is that inflated number of modules with 90% never maintained more than a year.
- Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new "features".
Which is what this thread is about.
- Expect the output of every program to become the input to another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input.
JS has wonderful stream support, and it's used everywhere in many tools. This is probably where JS is the weakest out of these.
- Design and build software, even operating systems, to be tried early, ideally within weeks. Don't hesitate to throw away the clumsy parts and rebuild them.
I mean, if JS isn't this taken to the extreme, i don't know what is...
- Use tools in preference to unskilled help to lighten a programming task, even if you have to detour to build the tools and expect to throw some of them out after you've finished using them.
This also describes JS to a T. Tons and tons of tools, each often only usable by a small number of people in niche situations.
Now i'm not saying that JS is as well designed as unix, i'm not saying that it's exactly the same as unix, i'm not saying that Unix doesn't do things better, or that JS doesn't have it's warts. I'm just saying that it's the "unix philosophy" taken to the extreme. It might not be good, it might not last, but it's working out pretty well for many people right now.
Are you seriously telling me you've never had a linker (static or dynamic) choose the wrong library?
Do you think Flow was built in 3 months as a reaction to Typescript? Not that it was a big enough problem that two different groups of people independently decided to try to solve it? EDIT: disregard this, Flow was introduced much longer than 3 months after TypeScript. The blog post introducing Flow mentions TypeScript, and is probably worth reading for background [1]
> Nuclide instead of Atom/Sublime/VSCode
Nuclide is an Atom plugin.
> Jest instead of Jasmine/Mocha
Jest provides a superset of Jasmine functionality, and uses Jasmine as its test runner.
[1] https://code.facebook.com/posts/1505962329687926/flow-a-new-...
They probably knew that TS was in progress when they started, but I don't have a window into that. I did ask some Flow devs a few weeks ago if they are interested in merging with TS, and they answered with a categorical no.
As a caveat, I am a daily TS user, and have only played around with Flow.
What this means in practice I don't fully understand but it seems to result in enough architectural differences that it apparently makes sense to have both despite the superficial similarities in syntax and behaviour.
Flow on the other hand solves one problem and solves it well. It behaves as any other tool would.
As i said, try to transpile this in TS: http://redux.js.org/docs/basics/ExampleTodoList.html
This is why they made Flow.
Object spread is not part of the ES7 spec. It is a proposal which has not made it to stage 3 yet, and might still be dropped. That said, there is a TS issue tracking adding support for it: https://github.com/Microsoft/TypeScript/issues/2103.
Did Flow take 2 years to get implemented? I didn't think the initial release looked like a project that had 2 years of dev time on it.
Given npms years of crap I'm ready to give it a shot anyway. This might be one of FB's projects that actually gets some traction, especially given its developed in collaboration with other big names.
If you are curious to find out more about why we built it, please read our blog posts, beginning with one about testing performance and our unique constraints at FB: http://facebook.github.io/jest/blog/2016/03/11/javascript-un...
Finally, test runners tend to get stale. Any large organization will run into trouble with any kind of tooling as companies scale up engineers or codebases. Testing is no different and we aimed to solve those problems for Facebook; getting to open source our solutions is an added bonus and we are excited to work with the JS community to build the best tooling we can possibly build.
So yeah, I'm definitely on the "keep reinventing" side of this debate.
They should mention this at the very beginning. Multiple big players investing in this package manager means that we should maybe inspect a little bit more before chanting xkcd.com/927.
Basically, yarn is npm client done right reusing the same npm package repo.
Exponent uses a monolithic code repository (rather than many small code repos) to manage our many interdependent projects. Our repo is actually setup very similarly to Facebook's mono-repo, though obviously considerably smaller in size. We were encountering _many_ of the same problems as Facebook with our NPM setup -- long CI/CD build times, indeterminate node_modules directories that caused our projects and tools to work for some people on our team but not for others, and the inability to do "offline-only" npm installs in CI.
We actually talked with our friends at Facebook about these problems, and tried many of the same approaches they did -- shrinkwrap everything, checking in node_modules, uploading the node_modules folder to separate place (we used another completely separate Git repo), etc. All these approaches either didn't work well or were difficult to maintain, especially on a small team.
Yarn has fixed all these issues for us.
One not-yet-super-publicized feature of Yarn (though I'm told there is a blog post coming) that has been super useful at Exponent is the ability to build a distributable offline cache of dependencies. We have a "node_modules-tarballs" folder in our mono-repo that contains tarballs of all the dependencies for every single project that we maintain at Exponent. Yarn will pull from this cache first before fetching from the NPM registry. This offers HYPER-predictability...it's a level of confidence over and above the "yarn.lock" file, and let's me sleep well at night knowing that my team can get up and running quickly no matter where they're working, how reliable their internet connection is, etc. No more worrying about "did I forget to update the shrinkwrap" -- things just work.
As JS developers, we all, beginners and experts alike, can experience this "JavaScript fatigue" that we always hear about. Fighting with tools is never fun. We just want to write code!
As we've started to use Yarn at Exponent, both on our engineer's machines as well as in our continuous integration and deployment environments, we've at least had one less tool to fight with. Yarn works, works fast, uses the great parts of the NPM ecosystem that we know and love, and most importantly, is _predictable_.
Definitely looking forward to that blog post from the Yarn team, but I'd definitely be interested in your own comments on how to use that "checked-in tarballs" approach.
That's exactly what we need! How do you tell Yarn to build and use this offline cache?
Search "go" on google, and the first link is the programming language. Search on any other search engine, and as one might expect, the definition or the game of go is ahead of the language.
yarn is framework for doing X in web programming, and this a framework for doing Y in web programming. not sure if dependency management and cluster system management are far apart enough.
warning electron-prebuilt-compile > electron-compilers > jade@1.11.0: Jade has been renamed to pug, please install the latest version of pug instead of jade
in npm, that would have just said the part after "jade@1.11.0" which was really vague and didn't really make you want to "fix" it because which npm module do you have to go into? who knows because npm (the package manager) didn't tell you.
One interesting little tidbit I found from diving into the source:
https://github.com/yarnpkg/yarn/blob/master/src/constants.js#L15
https://github.com/yarnpkg/yarn/blob/master/src/registries/yarn-registry.js
It's not mentioned in the post, but looks like they're running their own registry as well...Oh! And open governance: https://github.com/yarnpkg/rfcs !
npm, Inc strongly encourages people to build and use mirrors. for example, cloudflare (where the mirror lives, and where seb used to work) has been running https://npmjs.cf/ for a long time.
Nix and ied (which borrowed from Nix) got these problems pretty much solved.
I don't understand what spoke against these approaches?
I mean okay, nix has its own language, which is probably a turnoff for JS devs, but ied?
(Disclaimer: I'm the author of ied.)
It has been working well with our npm proxy and is basically a faster, better-deduped drop-in replacement that removes our need for npm-cache, npm-check-updates, and all of our shrinkwrap hacks.
This is finally the npm rewrite we've been waiting for.
In looking at the yarn repository, it's nice to see a clean, modern build, ES6 + async/await, Flow typing, and so on. This is what a well-maintained JS project looks like in 2016 that's built for production use.
npm, for all its flaws, was a revolution when it was first written. But since then, it has been large, unruly, difficult to maintain, and has largely unaddressed many important production use cases. It is nice to see a group of companies using Node in production take the lead on addressing problems that really matter to production JS apps.
Practical, usable, deterministic lockfiles are wonderful and the lack of them has been the single biggest pain point in the npm ecosystem.
I'm curious about the "flattening" approach though -- and why something like ied ( https://github.com/alexanderGugel/ied ) wasn't done instead. ied only ever installs one copy of a module, but allows each module to think they have their own copy of it through clever symlinkery (essentially making it FEEL like npm 2 while getting the benefits of npm3/yarn). I'm not a fan of (explicit) flattening for a number of reasons:
1. Mimicking recursive dependencies while still only having on physical copy on disk has the benefit (or downside I suppose) of isolating and protecting different module's dependencies from each other. AKA, if you require("x").mutate = true, this won't be seen by other modules. Again, depends whether you like this feature or not, but with node's treat-symlinks-as-different-files configurable switch, you can actually control it yourself in ied I believe.
2. You don't run into tricky situations where require("x") can accidentally pick something up you didn't mean to (since it is now in the parent path of ALL your dependencies). So, if A depends on x, and you install B, it will be able to require("x") (maliciously?) and modify it, affecting A's behavior. Perhaps this is considered a strange possibility, but it gets particularly weird with peer dependencies, where you expect the user to choose their own top level dependency, but this can now be accidentally "chosen for you" by a subdependency of another package.
3. I just don't like clicking on my node modules folder and seeing 100 top level directories when conceptually I typed "pkg-manager install one-thing". This can lead to you yourself making the above mistake, by require("x") and having it "just" work, then having it "just break" when you remove the dependency that included x.
I'm willing to be convinced though (on RunKit we had module-fs simulate npm2 install behavior, super simple recursive installation, conceptually similar to what ied does).
We ran into a lot of issues with OS compatibility around symlinks and existing tools not supporting it. Windows lacks support for symlinks on non-Admin accounts, NTFS junctions work but they're slightly quirky in their behaviour and don't behave exactly the same way.
A lot of tooling relies on the existing node_modules structure. ESLint for example will load tools relative to itself which means that they need to be reachable in the tree, you can solve this with hardlinks but there's caveats with that too. Existing tools aren't very well suited for handling cycles either which in a system like npm are extremely common as a transitive module could depend on one that's higher in the graph.
We care a lot about existing ecosystem compatibility and because of these limitations we went with the current status quo. We'll continue to explore others options though and if there's a chance we can do it without any of these caveats then we're more than happy to explore it.
Let me know if you have any further questions!
Would be really nice if you would e.g. add ied to "Prior art" on your README then. ;)
/ @alexanderGugel (the guy behind ied)
That, to me, is what is wrong with npm. The problem stems from node.js not coming with "batteries included" so there is a proliferation of tiny libraries that do the most trivial things.
One problem is that packages often bundle everything, rather than including an npmignore. I'm guilty of this myself.
Do you think that the problem of over-dependence is reversible, and if so, how?
This is in no way a fault of node.js but of the whole JS standard. People these days use npm modules to run in a browser and ship stuff bundled together with webpack (or other bundlers), so even if nodejs had a proper stdlib, you'd still need to depend on a polyfill so that your stuff works in a browser environment, too.
And due to the fact that even if a sane stdlib would ever be standardized, it would take YEARS of time until it reaches significant market share (looking at you, Android, Safari and IE), so you'd always have to ship a polyfill.
Going further down shit creek, each project I work on has its own node_modules. Which duplicates all of this crap, ad nauseam.
Do I really need React and Babel and jQuery and Webpack installed for every goddamn repo? You're not a package manager if you're not managing packages!! You're a glorified wget.
Upgrade to npm v3, that should these problems.
ES6 module imports and HTML Imports both require that dependencies are imported by URL. This means that the only reliable way to import another module is by relative URL, like:
import * as $ from '../jquery/jquery.js';
This requires that packages are installed flat, as siblings. Yarn is going to enable native JS modules and projects like Polymer to use npm instead of Bower. :)This means that HTML imports and ES6 modules can force flat installs and start moving the front-end package ecosystem in that direction.
It's not very helpful if you are distributing an NPM package, but for people who aren't authoring libraries, its a godsend.
Even so, that requires a build tool. I want to be able to load working sources directly out of my packages directory.
Not if you use a build tool for your frontend.
> Even so, that requires a build tool.
That was basically what I was suggesting. I'm not sure what the other option really is. If you're working within the browser (implied by this being a frontend), then you have to use a build tool since javascript modules/imports haven't landed in any browser yet.
For now, but native JS module loading is right around the corner, and at that point I don't want to have a required tool to load my modules.
Currently I use HTML Imports, which don't require tools because they use relative URLs. It works really well, so I hope to use that pattern with JS modules.
I see no documentation nor code for the service powering this, nor is there a way to tell the command line tool to use a registry at a different address.
Aren't we just replacing the dependency on npm, Inc.'s registry with a new dependency on Facebook Inc's registry with this?
Yes. The client has a few advantages, but the registry is still closed and while with npm there's an option of running a private registry if you pay them, here, there's no option at all.
My inner-cynic makes me feel like everyone at Facebook is really young, as I've noticed a trait of inexperienced developers is to try to create new things over finding and improving existing tools.
In reality it could be something as simple as Facebook releasing more FOSS software than others, or maybe their releases having more visibility.
Either way, feels like Facebook like to pave their own way, for better or worse.
It's great to see attention is being spent on what is a really important area, one which has been largely under-appreciated in Node.js until now (aside from for a short period after the left-pad incident).
Kudos to Facebook, I look forward to giving it a try.
The justification for Yarn starts by ignoring the existence NPM Shrinkwrap. It then proceeds to mention Shrinkwrap and refer to its supposed short-comings. Whilst there absolutely were issues with Shrinkwrap in the past, they've already been addressed by NPM.
NPM is slow, perhaps Yarn is faster and has some extra features. But why these couldn't be contributions to NPM seems like a serious case of NIH...
No. NPM is awful in ways that could not be fixed without braking changes. They have a need, so they satisfied it. A need which, by the way, every one of the dozen-or-so Node-using projects I've worked on have shared.
> Whilst there absolutely were issues with Shrinkwrap in the past, they've already been addressed by NPM.
This isn't even remotely true. Shrinkwrap is still a usability nightmare and doesn't begin to address the non-deterministic install behavior that crops up when you add new dependencies.
> why these couldn't be contributions to NPM seems like a serious case of NIH
There's no way that they could have got these changes in to NPM in anywhere near the time it will take for Yarn to become popular; if at all! Politics (or the avoidance thereof) are practically _the_ perfectly valid reason to justify NIH.
I'll wait a while for Yarn to bake, but personally, I hope NPM dies a swift and total death.
Examples, please.
> This isn't even remotely true. Shrinkwrap is still a usability nightmare and doesn't begin to address the non-deterministic install behavior that crops up when you add new dependencies.
Again, examples, please.
> There's no way that they could have got these changes in to NPM in anywhere near the time it will take for Yarn to become popular; if at all! Politics (or the avoidance thereof) are practically _the_ perfectly valid reason to justify NIH.
Did the Yarn developers make any attempt to contribute to NPM at all? If they did and were turned back, then sure, I understand. However, everything I've read about Yarn thus-far is just vague finger-pointing at NPM.
I'm by no means suggesting NPM is perfect, for one I find it incredibly slow. However, surely that can be optimised.
However, regarding dependency version locking, which is the problem Yarn is trumpeting, what are the actual issues with Shrinkwrap? I'd like something specific. Since Shrinkwrap was updated to keep a flat sorted structure (a while ago) I've been using it no fuss at all. What are the specific issues people are running into now?
I've seen comparisons with Bundler, and how Yarn will be more like Bundler's Gemfile.lock files. However, the thing is the current version of Shrinkwrap works almost identically to Bundler's lockfile e.g. When I update a dependency the shrinkwrap file automatically updates (at least that's the default behaviour).
> Examples, please.
The first and foremost: Version pinning should be the only way it works. Obviously _requiring_ shrink-wrap would be a breaking change.
> > Shrinkwrap is still a usability nightmare
> Again, examples, please.
Having to explicitly call shrink-wrap is just silly. Devs on every time I've used shrink-wrap with frequently forget to do it and it causes all sorts of "works for me" problems later. My team has also experienced all kinds of brokenness related to private NPM repositories and shrink-wrap non-determinism.
> Did the Yarn developers make any attempt to contribute to NPM at all
I don't care about this at all. Just because you got there first doesn't mean you should have some kind of special claim to solving the problem.
> Having to explicitly call shrink-wrap is just silly. Devs on every time I've used shrink-wrap with frequently forget to do it and it causes all sorts of "works for me" problems later.
Really? An entirely new tool because you didn't like typing "npm shrinkwrap" once, just once per project? I... I don't even know how to respond to that...
> My team has also experienced all kinds of brokenness related to private NPM repositories and shrink-wrap non-determinism.
I'm unclear on what you mean? Do you mean in the past? Cause if so, sure... but hasn't this already been addressed?
> I don't care about this at all. Just because you got there first doesn't mean you should have some kind of special claim to solving the problem.
This is an all too common attitude in the JavaScript community. Hence the plethora of poorly maintained, duplicated NPM packages.
I'd rather humanity not waste the man-hours duplicating effort. Do something productive with the time you saved.
As mentioned, if for some reason the NPM guys weren't co-operative, then I understand, however that doesn't at all seem to be the case.
I don't know what kind of projects you work on, but new dependencies get added with some regularity on any large node project, requiring a shrink-wrap every time.
If you've never experienced the forgetting-to-shrinkwrap problem and its interplay with team dynamics, then I envy you. But I also must give up trying to explain to you, since this drives to the heart of the problem and I must conclude that we simply do not have enough common experiences for you to ever understand. The developers of Yarn et al clearly have lived this nightmare.
> Do you mean in the past
Where the past was < 4 months ago. If it has been fixed since that, I don't care: too little, too late.
> This is an all too common attitude in the JavaScript community.
An equally big problem in the JavaScript community is that core pieces of infrastructure have been "claimed" by people who have absolutely no idea what they are doing, but are happy to community-coordinate their way to some kind of idealistic open source victory.
> weren't co-operative
Again, I don't care if they were willing to co-operate. I have zero confidence in them.
> I'd rather humanity not waste the man-hours duplicating effort.
Give up on this dream. People are going to re-invent everything from now until the end-of-time, and rightly so.
I can only hope the Yarn developers knew about the changes, and had a real justification for their work.
Again, I'm not saying the Yarn developers didn't have justification, I just haven't seen any yet. Love to be shown otherwise.
I would go so far as to say that npm is the single biggest problem with the node community at the moment.
NPM seems to be continually addressing their short-comings, as you would expect from any software project. It's come a long way.
Specifically, what are the existing short-comings of NPM, and why couldn't they have been addressed via pull requests?
The article states that running `yarn` is the same as `npm install`, which doesn't look like the case. At that point, I'm curious what are the differences.
A better std lib for node and module LTO would be a good step forward to removing the proliferation of tiny packages
[0] https://github.com/yarnpkg/yarn/blob/99dd4504469273332f01ce5... [1] https://github.com/composer/composer/blob/20ee689bb464edfe7e...
It is the same pattern.
The official npm cli is quite old and evolved along with all the different coding styles and architecture choices of the node and JS ecosystems.
It's also full of dependencies on originally purpose-built modules that suffer from the same problems. This compounds various issues, resulting in long-standing bugs like `npm publish` sometimes not actually including all files in the tar bundle it generates[0].
NPM 3 was a partial rewrite but it's still built on the same mountain of code as NPM 2 and 1. npm Inc developers have in the past complained about not being able to address issues for a lack of resources despite having a ton of developers on the team[1].
The official npm client also doubles as an account management CLI to the npm registry. Which apparently npm Inc now considers a design flaw as they recently started creating a standalone tool for managing other aspects of their commercial services[2].
And finally it's important to understand that having a new package manager that is not tied into npm Inc means it's easier to replace the npm registry as the official node module registry in the future. Which would allow the community to get rid of the privileged position npm Inc currently holds in the node distribution (which is otherwise governed by the Node Foundation).
Rewriting the client from scratch actually turned out to be the sanest approach in this situation, I think.
[0]: https://github.com/npm/npm/issues/5082
fwiw, only 2 of those humans work on the CLI, (3 if you count their manager, who spends a lot of time managing). other people work in sales, marketing, engineering on the website, engineering the registry, community + docs, etc.
wombat is not a tool for managing our other commercial services! it's a way to manage our webhooks product, one of many products we have, though very certainly the smallest.
yarn depends on the npm registry, which depends on npm, Inc making money to keep it running.
Thanks for clarifying. But that does show that having a company fund two full-time developers to work on the CLI wouldn't have been sufficient. Yarn was mostly built by Seb (403 commits) starting in late January and Konstantin Raev (121 commits) with contributions from several others (<30 commits each). The commit graph[0] actually shows development mostly paused in April and May, putting the total development time closer to half a year.
This most likely includes collaboration with the other people supporting the project (both Seb and Konstantin work for FB) and a lot of architectural planning -- aspects, which likely would have required an even greater investment of time if building on the legacy codebase of the official npm client (not to mention having to negotiate all changes with npm Inc directly).
> wombat is not a tool for managing our other commercial services!
Sorry about the misunderstanding. When wombat came out a lot of people wondered why wombat was a standalone tool when practically every other aspect is part of the npm cli and from what I gathered from npm devs at the time the decision was more of a technical one (different people working on different tools for different things) than a managerial one (different products deserving different tools).
> yarn depends on the npm registry, which depends on npm, Inc making money to keep it running.
Yarn currently uses a downstream mirror of npm as the direct source of truth, with support for private registries being actively worked on to support the private parts of the npm registry and products like npm enterprise or free alternatives like sinopia.
However that is obviously an implementation detail. Decoupling yarn from the npm registry by going through an intermediary allows experimentation (as the npm blog post points out) and ultimately allows avoiding a hard dependency on npm Inc as a company.
If npm Inc were to shut down right now, yarn would still have a read-only mirror. I'm sure Facebook and Google have enough experience solving problems at scale that they could build a public registry alternative if necessary (such as if npm Inc went out of business tomorrow).
I'm not saying yarn will kill npm Inc. But yarn can kill the npm client and replace it with a community-supported alternative (under an open governance model similar to Ember), which in turn makes it a lot easier to fade out the reliance on the public npm registry maintained by npm Inc -- benefiting both the community (by eliminating a single point of commercial failure in the node ecosystem -- exactly like joyent was to the node project) as well as npm Inc (by eliminating a major drag on development resources and cost center).
The only drawback from such a move to npm Inc would be the loss of its privileged position in the ecosystem, the "first mover" advantage of being the place to go if you want private packages (because it's more frictionless than any of the alternatives -- exactly like GitHub in the git hosting space).
Nearly all modern JavaScript build tools are built on Node.js and NPM pre-dates most of them.
The only other thing I can think of that has seen as many shifts in JS development practices as NPM is Express (*2009) and that library has far smaller complexity and has arrived at a drastic reduction in features and a far tighter scope.
The NPM client on the other hand was originally cobbled together by Isaac and then grew organically as the NPM registry massively grew over the months and years of node's success.
The NPM client and registry are the epitome of technical debt. Calling it "old" is the most charitable way to phrase this.
Yarn, on the other hand, has focused on npm compatibility from the get-go. The entire point is to be a drop in replacement, with no changes (or maybe very very minimal changes) required to gain a lot of benefit.
In this slice of the industry where everyone is told they have to rewrite to the latest thing every year or two, I find it very refreshing to see Yarn's focus on backwards compatibility, improving existing infrastructure, and having a clear, painless adoption path.
jspm aims to be type-agnostic with respect to modules (supports all major types, hence why it is called a universal module loader). jspm certainly doesn't advocate rewriting your modules (you can use exports, AMD, ES6, whatever). In fact, when the browsers natively support module loading, systemJS will go away (which is really just a polyfill for this functionality).
jspm also has npm compatibility.
yarn global add typescript
yarn link typescript
error No registered module found called "typescript".
info Visit http://yarnpkg.com/en/docs/cli/link for documentation about this command.
what?edit: also,
$ yarn add typescript
yarn add v0.15.1
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
error ENOENT: no such file or directory, open 'C:\Users\******REDACTED******\@types\react\index.d.ts' at Error (native)
info Visit http://yarnpkg.com/en/docs/cli/add for documentation about this command.npm-cli's job was simple. Take in a `package.json` as input and output the same `node_modules` folder as fast as possible. But somehow it couldn't do that even after getting 6 years old. On top of that, every now and then with when you ran `npm update` or `npm dedupe`, it messed up the `node_modules` folder with extraneous and invalid packages.
For example:
"scripts": { "dev": "node api.js --config config-dev.json" }
$ npm run devlots of "npm run" -> "yarn run" there.
I wonder whether Facebook realizes just how much damage they are going to be doing to the JS ecosystem with this approach.
The big deal about semver and how it's implemented in NPM is that there is a choice of how to deal with it - either you automatically allow compatible updates and risk an occasional maintainer fuckup, or you explicitly pin everything and take on the burden of constantly updating your versions manually and tracking security releases.
The latter might work for Facebook and other large organizations, but for many smaller developers, the consequences of an accidental break are much, much less serious than those of constantly having to keep pinned dependencies up to date. End result: people don't bother at all, and insecure versions never get upgraded for the majority of the userbase.
This, in turn, removes the incentive for package authors to do anything with semver at all, once Yarn's approach becomes commonplace. Why bother with semantic versioning if everybody is expected to manually check and pin their dependencies anyway?
Facebook also needs to take into account their influence over the ecosystem. The reality is that whatever project Facebook puts out is immediately seen as gospel and "naturally, a well-engineered thing and a good choice to use!" - this is literally a daily argument in #Node.js when somebody is trying to argue why a poorly-fitting tool is somehow appropriate for their usecase. "Well, Facebook uses it!"
In reality, the Yarn workflow is designed to work for Facebook and organizations of similar size, and in all likelihood it will break down in other situations. People will not realize this until they've already bought into it, and by then it's too late.
> Why bother with semantic versioning if everybody is expected to manually
> check and pin their dependencies anyway?
I think this is the disconnect here: the lockfile does protect me from updates, but ranges are still useful: they allow a tool to help me upgrade my dependencies. With the lockfile-based approach, you usually _don't_ pin to specific versions: with Cargo, we even defaulted to the ^ operator, so 'foo = "1.2.3"' is the same as 'foo = "^1.2.3"'. So this is what happens: 1. foo v1.2.3 comes out and I put that in my Cargo.toml.
2. foo v1.3.0 comes out. My build doesn't change.
3. I decide "hey, there's some new versions of my dependencies, let's upgrade."
4. I type "cargo update". Now, my lockfile is updated to have 1.3.0 instead.
That is, ranges allow you to use semver as a tool. The big issue here is transitive dependencies; yes, for my own deps, I could have specified an exact version and done it every time. But what about the dependencies of my dependencies? Or the dependencies of the dependencies of my dependencies?I totally understand your concerns about cargo-culting tooling, and that Facebook-sized organizations have different needs than non-Facebook sized ones. But repeatable builds are a big deal, and managing dependency ranges so you can still use semver while getting repeatable builds is a big deal. Even for smaller organizations.
(And that's beyond the speed and security aspects of yarn.)
I understand that, but you're looking at it from a technical perspective, while it's partially a psychological issue - namely, the question of how you drive certain desirable behaviour.
When you make upgrades explicit, rather than automatically installing newer versions, you reduce the deployment of (security) bugfixes, because many people simply will not run `upgrade`.
The reason is that you've created an expectation of manually checking versions before updating them - after all, why would it be a manual action otherwise? - and people do not want to commit to doing that. That is why this will harm the ecosystem - it undermines the mutual trust that a maintainer will be using semver, and that you can rely on it to automatically get updates.
The solution is simple: make lockfiles opt-in. That doesn't mean that you can't aggressively require a developer to lock their versions once they have opted in - it just shouldn't be a feature that is enabled by default.
> But repeatable builds are a big deal, and managing dependency ranges so you can still use semver while getting repeatable builds is a big deal. Even for smaller organizations.
For many people, it really isn't. Comparing the tradeoffs of manual upgrade management vs. the chance of occasional breakage due to non-determinism, many people will pick the latter.
And I'm not just talking about "organizations" here either - there's plenty of development going on outside of any organization, on personal projects, and that is precisely the kind of development you'd want to encourage.
Absolutely agree with this statement, it drives me insane listening to the hype before anyone has really even had chance to form an opinion on it.
I'm also bummed cuz I've been working on a static site generator for over a year written in node called Yarn as well[1].
I guess it's time for a rename! Any suggestions? :D
This kind of liberty is the sort of stuff npm was designed for. It is also why npm has been causing trouble in many cases.
There are many use cases for this functionality, the design of a software package shouldn't instill dogma into its users. Users use software for their needs, not to sign up to a religion.
If you think consistency across computers is a religion then I don't think we're going to find a lot of common ground here though.
Finally, yarn is not intended to replace the npm client. It is intended to replace it for a certain use case, which happens to be one many companies have. Unlike Yarn, Npm is highly flexible and obviously you like it like that. I strongly doubt it's going to stop being developed all of a sudden because some other people made Yarn. So what, exactly, is the problem?
Follow users needs, not your idea of what they are or the problems with npm are.
$ rm -rf ./node_modules
$ npm install yarnpkg
$ ./node_modules/yarnpkg/bin/yarn
and it just freezes up and never finishes: [4/4] Building fresh packages...
[1/3] ⠈ node-sass
[2/3] ⠈ radium
[3/3] ⠈ phantomjs-prebuilt
[-/3] ⠈ waiting...
[-/3] ⠈ waiting...
This is not a particularly complex app, the dependencies: npm install --cache-min Infinity
I have this aliased to `npmi` on my system and use it all the time.It still doesn't solve the biggest problem the node.js and javascript ecosystem has IMHO: dependency hell, thousands of trivial packages, just utter chaos.
Can somebody please explain to me: 1) How does npm fit in in the process of developing a web app. How does it manage the js files / libraries and where does it place them? 2) How is yarn going to make your life easier
Please go easy on me.
2. npm doesn't have bundler's lockfile, but this does. It's also faster.
Is a replacement / mirror / rethink of the NPM infrastructure coming next?
If I was NPM Inc I would think about adopting yarn if possible.
It also seems to imply that this is edited by the `yarn` command so it would be invalidated if you manually edited your `package.json`? Dunno if it's destructively invalid though.
1: https://yarnpkg.com/en/docs/configuration#toc-use-yarn-lock-...
Is it really important that one knows that a tool dependency uses left-pad ? What could be the drawbacks of such bundling?
http://blog.npmjs.org/post/141905368000/changes-to-npms-unpu...
The actual disruption however was solved by npm Inc disabling unpublishing (except for some very specific circumstances) and by creating a dummy account unpublished modules are reassigned to to avoid abuse (whereas previously anyone could simply claim unpublished modules and publish new versions).
No, I mean someone retroactively removing a package others were using out of spite.
For e.g. Facebook, I bet they have some online filesystem like NFS or similar, that hosts the global yarn cache for their continuous integration system. This way, their CI system doesn't call out to the cloud for every build.
Looks like they use SHA-1 hashes, though. Please, let's get rid of SHA-1 already.
Stop copying stuff. Just make it global and link.
Next step is to make packages immutable and signed.
I'm happy with this step and the fact that facebook will be able to push this.
I'm a huge fan of bundler - it's dependency heaven. I'm also a big fan of the rubygems repo. It does not allow changes in released versions.
Even without symlinks it's a much needed improvement in the javascript ecosystem
The reason is that each package only finds its dependencies relative to its own location. So your second level dependencies cannot vary from project to project unless you do copying.
(Example: AppA and AppB depend on LibX. LibX depends on LibY. Through their deterministic lockfiles, AppA and AppB disagree on which version of LibY to use. There is no way to symlink things together to satisfy that case without copying LibX or altering node's package resolution algorithm.)
Looks like it's new in Node 6. Yarn supports Node LTS.
npm install – 2m5s
yarn (no cache) – 9s
yarn (cache) – 2s"
C:\Users\******>npm install -g yarnpkg
npm WARN deprecated yarnpkg@0.15.1: Please use the `yarn` package instead of `yarnpkg`Chocolatey is coming soon, once they approve the package.
[+] https://github.com/yarnpkg/yarn/issues/599#issuecomment-2529...
Most of my problems with developing modern JavaScript apps are around npm client, long installs and huge dependencies folder.
I hope it will improve everybody workflows.
yarn yarn install v0.15.1 info No lockfile found. [1/4] Resolving packages... error https://registry.yarnpkg.com/babel-code-frame: socket hang up at createHangUpError (_http_client.js:252:15) at TLSSocket.socketCloseListener (_http_client.js:284:23) at emitOne (events.js:101:20) at TLSSocket.emit (events.js:188:7) at TCP._handle.close [as _onclose] (net.js:493:12) info Visit http://yarnpkg.com/en/docs/cli/install for documentation about this command.
Thank you, Whoever touched this. Thank you.
But that would be too easy...
Not sure why Facebook spent so much time and money to create a more complicated "solution", or why so many people don't realize that.
EDIT: Even when it's hitting the cache, it's only ~5% faster than clean NPM with networking for me...
Why is the JavaScript community continuously creating new tools instead of contributing to existing ones ?
https://medium.com/@mfornasa/using-yarn-with-docker-c116ad28...
So yeah, in theory, you could create a whole 'nother binding to a runtime just for front-end tooling. Nobody's found node lacking enough to do that.
(Also don't forget that frontend JS has to target dozens of subtly different browsers, so we unfortunately need to "build" JS files to account for backwards compatibility, etc)
(Edit: Note: I mean you don't _have_ to. You might like the performance increase, but if you only use it casually, even that might not be worth the trouble.)
why not mirror npm modules there then?!
Thank you, thank you, thank you, thank you, thank you.
I'll continue using npm thank you very much.
console.log("u got powned")You shouldn't check in node_modules. You should use a shrinkwrap file to indicating the specific sub-dependency versions you're using.
Not really. They just mention it in passing:
From the article
>> Shrinkwrap files aren't generated by default and will fall out of sync if engineers forget to generate them, so we wrote a tool to verify that the contents of the shrinkwrap file matches what's in node_modules. These files are huge JSON blobs with unsorted keys, though, so changes to them would generate massive, difficult-to-review commits. To mitigate this, we needed to add an additional script to sort all the entries.
Comparing node_modules to shrinkwrap isn't necessary. Building the app will re-generate node_modules and tests should catch whether or not the app works as intended.
The sorting issue for shrinkwrap is legit, but the answer to that is sort it! Sure you'll get some deep diffs if the dependencies change, but that reflects the real changes to the app.
The simpler answer seems to be to add a build test to mandate the existence of a shrinkwrap file, verify it's sorted, and (optionally) verify it's up to date. The latter doesn't even have to be done every build.