Yarn's Future – v2 and beyond
github.com
github.com
Very excited to see shell compatibility guarantee in scripts as well. Using environment variables in scripts is a pain right now.
Finally one of the biggest news is the switch from Flow to Typescript. I think it's now clear that Facebook is admitting defeat with Flow; it brought a lot of good in the scene but Typescript is a lot more popular and gets overall much better support. Uniting the JS ecosystem around Typescript will be such a big deal.
It sounds to me more like they're testing the waters. They're definitely opening up, with the whole Jest and create-react-app supporting it, but as far as using it themselves would this be the first project to be migrated?
And then there's... whatever this is:
https://twitter.com/jamiebuilds/status/1064649666275340288?l...
I respect Jamie for the things done and built, but his views tend to be a bit extreme.
I agree that flow is not in a good place right now, but to say that they don't give a shit about the community just isn't true.
Flow has been making significant strides in community outreach, inclusion, and detailing their roadmap lately. And Facebook dropping flow would bring us toward a monoculture which I personally think is a bad thing (it's always good to have some competition to keep new ideas flowing and stuff improving), and Jamie advocating for it seems misguided and shortsighted.
Flow happily accepts contributions from outside people, but because of the somewhat esoteric language choice (ocaml) and the fact that it's significantly smaller in terms of community usage means that there isn't that many people to contribute anyway.
They might be in general, but these sound like some easily objectively checkable claims:
"If you want visible proof of this [Flow not caring for the community], just look through the repo. PRs are never merged. Issues are never addressed. Pretty much all of the activity there is done by a couple people in the community. Critical issues stay open for years. They do all of their development internally"
At a glance, it looks like all PRs are just closed, but looking at them individually shows a different story.
It's the same with React-Native, and several other OSS projects by facebook, and Jamie knows that, having worked at FB when that workflow was used.
It has its faults (I personally really hate the workflow they use, but I get why they use it. Github is where the people are, and Phabricator and other internal tools are difficult to integrate into it in a lot of cases, but I still hate it), but to say it's because they don't care about OSS or they do all their work internally isn't true. Plenty of FB employees and outside contributors both make PRs on github, discuss them on github, and just merge them internally closing the PR on github.
Flow has plenty of issues without needing to make them up or exaggerate them. Their errors still take weeks for many to understand and get used to, flowtyped is a mess compared to typescript's type distribution system, their fucking habit of single character type variables makes looking at built in type definitions extremely difficult, the flow binary still is extremely unstable on windows even after years, and the recent move of aliasing Object and Function to `any` seems like a misguided attempt to simplify some code and speed up some checking.
But at no point do I think they should can the whole thing, and I absolutely think they care about open source. Like I said in the comment above, Flow is in a bad place right now, but they are putting their money where their mouth is, the Flow team is reportedly growing at FB, and over the past few months I've seen a massive uptick in the number of releases, blog posts, external contributions, performance, and a significant decrease in the number of bugs I was hitting on a daily basis.
At this point, the attempts to pacify Flow users like myself feels an awful lot like when Silverlight developers were begging folks not to abandon ship. People have to defend their livelihood, I guess.
With YAML and whatever format yarn.lock was in, the only changed lines are changes to the version resolutions, hash and dependencies.
I don't know how restricted their YAML subset is, but in my experience it's so loose a format the only way to be sure YAML says what you think it says is to run it through a parser.
Yarn will actually do the merging automatically — if you have conflict markers in your lockfile, just running yarn will parse them along with the rest of the file and produce a new lockfile with the changes from both diffs (unless there's a genuine conflict).
I assume that this feature won't go away with the new lockfile format
Hopefully they'll be able to re-use much of that work for the Yaml file.
Fortunately as someone else replied, both yarn and npm have safe and easy ways to resolve merge conflicts in their lock files.
What is the largest concern about YAML is that truncated documents are almost always still valid documents. The likelihood of that happening compared to, say, a git merge gone wrong is much lower, but the consequences are likely much worse.
I don't have a strong opinion on structured data file format, but that's an issue with YAML that often goes unmentioned.
JSON uses commas `,` which will show multiple changes when the last item of a list changes.
[1, 2, 3,]
foo(1, 2, 3,)
And thus, when writing multiline literals and calls, it's pretty common to use the comma as a line terminator, precisely so that new lines can be added at the end without touching the previous line.JSON, however, does not.
Another major project moving from flow to typescript
However I certainly take the point that flow has been developer hostile. When we have had issues it has been impossible to get a response (here is a demo, is this a bug or in the pipeline?).
Though flow is v0.91 and Typescript is 3.2, i don't know if i can really fault them that much?
I don't trust TS, they are too much 'move fast and break things'.
(I had projects that started with TS < 1.0 and they all still parse and compile today, albeit with tons of lint warnings, particularly to use a better module system than AMD with pre-ES2015 TS imports, and all sorts of new type strictness options to turn on to make them all the more type safe.)
Even if you don't believe in the old Unix adage that "worse is better", Typescript today isn't that demonstrably worse than Flow. Depending on your metrics, such as general availability of community-supported type information, Typescript in increasing ways better.
I've yet to find anything he's done/worked on that I don't like, one of my programming heroes actually.
I agree that Flow had better capabilities around soundness. But the tooling around Typescript really made me jealous, specifically in VSCode.
Near the end of working with Flow, Typescript was getting some cool capabilities like refactoring JSX for React apps.
Nowadays I can easily say that Typescript is a far better experience than Flow. There are updates every two months, adding some neat features that you might find in other languages.
Then you add in the power of surrounding tools and their ecosystems like TSLint and it really feels like a next-level coding experience where the tools start writing the mundane code for you, driven the core TS static analysis.
Most of not all of the issues had with types have been solved.
Flow had some major tooling/developer comfort issues from day one and none of those are solved. Not to mention a really closed development roadmap (understandable perhaps, but nonetheless bad).
As a developer, I'm glad TypeScript won. I want more tool/compiler/language/etc makers to understand that the developer experience matters. If someone makes a tool that only works well under one very specific setup and ignores everyone else, that's just very limiting.
/* @flow */
interface HasIdentityFunction {
id<A>(a: A): A
}
class Example implements HasIdentityFunction {
id<A>(a: A): number {
return 42;
}
}
var x: string = (new Example(): HasIdentityFunction).id("hello")
[1] https://twitter.com/puffnfresh/status/1077072700609159168Seems like Flow works just fine for them, they just want to make it easier for others to contribute.
Why do programmers love error codes? As an end user, they are useless indirection to me and the only way this would even be tolerable is if the explanation was printed directly next to the error code, so why bother? Is it code quality, since you don't have to write a long error message when you emit a similar error? But doesn't that have the drawback of encouraging error code reuse when it might not be appropriate?
[append]
Thanks for the replies! I guess I could understand error codes for search ability that also provide information about the problem specifics.
Counterexample:
$ yarn add foo
Error YARN1001: Incompatible peerDependencies.
$ yarn explain YARN1001
# Some longer text about how two of my modules have
# incompatible peerDependencies
Better example: $ yarn add foo
Error Yarn1001: Incompatible peerDependencies.
* my-package@1.0.0
|-* foo@1.0.0
|-* bar@1.0.0
|-* left-pad@1.0.1 (peerDependency of bar@1.0.0)
|-* left-pad@0.9.0 (peerDependency of foo@1.0.0)
$ yarn explain YARN1001
# Some longer text about how two of my modules have
# incompatible peerDependenciesIt also makes it easier for developers look up a specific error in the documentation, assuming it's been documented.
If we where talking 20 years ago I might agree, but I really can’t see the argument with todays tooling.
Also many times the error message is interpolated with your specific details like
"Syntax error at line 123 in file /home/user/myfile , symbol X is not allowed here" this is a silly example but often enough when i google this errors I have to first strip out my data from them.
Things like "TS1234", "flake8 E802", "Yarn E4882" etc are pretty much guaranteed to give you the results you want. Whereas "yarn some-error-text" can be much noisier, especially if the error text changes over time, is short, is obscure or even translated. Worst case they're also more greppable inside the codebase.
Error codes are a really, really good idea if your application is popular and used by devs, IMO.
I'd argue even if it's not popular and it's used by non-devs.
Error codes saved our support people a ton of time when trying to understand user problems. It's good for the user to be able to understand the problem, but it's great when they can call you up or send a ticket in about error "E4882", and you instantly have a good amount of information about the problem.
This is extremely useful, because the error output can focus on just saying what the error is (which is great when you already know what the error means), and there is an obvious next step to get more information if you need more help.
And if you don't find the answer, searching online for "rust E0275" gives much more relevant answers than trying to search the right parts of the error message.
For instance, this is the basic "use after drop" error message:
error[E0382]: borrow of moved value: `s`
--> src/main.rs:5:20
|
4 | drop(s);
| - value moved here
5 | println!("{}", s);
| ^ value borrowed here after move
|
= note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
this is the expanded explanation: https://doc.rust-lang.org/stable/error-index.html#E0382 On my machine, I have to "page down" twice to get through the entire thing. "rustc --explain E0382 | wc" tells me the markdown source is close to 110 lines and 550 words.And as other people noted, hopefully other folks discussing the issue used the error code, which makes their discussion not just more easy to find but survive localisation: if you get a localised error message it's almost impossible to find information on it unless it's absolutely ubiquitous, because the vast majority of the discussions (and especially the most useful discussions) are going to refer to the non-localised version, which your software will not provide.
edit: I can understand taking issue with it though, some systems do use error codes to skimp on the actual error messages. I recall Oracle being a particularly bad offender.
[0] I'd expect Typescript is the same, but don't know for sure
The HTTP protocol is another famous example of user-facing error/status codes that don't necessarily mean anything on their own.
Say that you have a database. When you ask it for a specific piece of data, and it can't find it, it shows 'data not found'.
Then I build a program that reads information from that database; I program it so that if it receives the text 'data not found' it knows to handle the error somehow.
Ten days later, the guy who programs the database decides that 'oops! we couldn't find the element :(' is a more friendly message to the user. Now my program will stop working until I switch it to the correct error text.
With an error code those kind of things don't happen. If you need extra legibility you can totally send both a code and a message, but the code is expected to remain unchanged and I can trust that it will stay the same in the future.
Grouping behaviours is another use. For example, if I have a system that sends you information and you have sent me wrong input, there's a dozen ways you could have done that (maybe you didn't send me enough data, or you sent it in chinese characters I don't recognise, or I just got gibberish I can't even start to understand). All of those cases might require different messages to the final user, but internally for me they're the same thing ('invalid data') and the things I'll have to do will be the same, so propagating a code serves me well.
There's also the issue of internationalization. If 200 android users across the world are having problems with their phones, and they all get an error 3242, they'll be able to find proper help. If one is showing "the application couldn't start due to memory issues", the other "la aplicacion no pudo iniciarse por problemas con la memoria" and yet another shows "لا يمكن بدء التطبيق بشكل صحيح" we're gonna have trouble identifying all those things as the same problem.
So unique IDs are useful in many places other than just error codes. Hope that helps.
Everytime I install a new package my previous `npm link` references break in the node_modules folder. `yarn link` keeps these reference. Just as I expect.
Running ‘npm install’ updates the lockfile :/
Then there was the issue where it didn’t respect git commit hashes that were added to the lockfile, just taking whatever the latest commit was.
Much of it has been fixed over time, but the frequency and duration of these issues is concerning—and, I think, points to architectural deficiencies being the root of the problem. (And the project is so massive that it's understandably a really challenging thing to manage and triage)
For example:
* npm 5.0.0—5.7.0 didn't play nice with git-based dependencies (https://github.com/npm/npm/issues/17379)
* npm 5.0.0—5.4.1 edits package-lock.json unexpectedly (https://github.com/npm/npm/issues/17979)
* npm 5.0.0—5.4.? doesn't honor incompatible version differences in package.json compared to package-lock.json (https://github.com/npm/npm/issues/16866)
* Take a look at the issues labeled as [big-bug], and how long they've languished (mostly from the v3 era): https://github.com/npm/npm/issues?q=is%3Aissue+is%3Aopen+sor....
* and a bunch of others I can't remember off the top of my head; especially nondeterministic behavior in the v2 and v3 era.
* Whenever I, a coworker, or our CI system pulls changes, we need to make sure that we have the correct dependencies installed because package.json or the lockfile may have been updated. We don't necessarily know if anyone else has changed package.json; we just want to run a command that makes sure node_modules matched the package.json and lockfile. Running `yarn` when there are no changes to package.json takes under a second, so it's easy to just always get in the habit of running, and doesn't slow down CI. We can make our build and deploy scripts just run `yarn` to be on the safe side because it's so cheap to run. But with npm, running `npm install` when there are no changes to package.json in a big project still often takes 10-30 seconds.
* I've run into many bugs like this one with npm: https://github.com/npm/npm/issues/19839. For a while, I actually made our deploy script run `npm install` in a loop until it stopped changing things just to be sure it successfully installed everything (but then it turns out running `npm install` multiple times can actually cause issues! https://github.com/npm/npm/issues/18084. To work around that, if you pull changes that include a change to package.json, you have to remove node_modules and then run `npm install`. This made our CI system so slow...). I've reported various bugs like this. The bugs would get no attention, but sometimes they'd mysteriously go away after a few versions. But bugs that go away on their own tend to come back on their own in my experience.
Yarn has only given me one issue in my use of it and it was promptly fixed. I swear by it now.
The move towards TypeScript 'winning' has been fast, and to everyone's benefit.
Edit: changed strong to static.
Abstractly speaking, there's no big conceptual chasm that separates a test in a test suite from a test the compiler makes.
A lot of unit tests will revolve around checking types. If you don't have to runtime-check this, you can focus unit tests on semantics and integrations assuming the underlying data structures are correct.
In retrospect, my original response was too terse. Static typing and testing serve the same purpose, which is to make sure your application runs according to some measure of correctness. We shouldn't be setting up one-or-the-other dichotomies — we can have both!
Static types won't help with your application logic, but they will (for example) ensure your function inputs and outputs are the correct types, help document your code and ensure consumers call your code correctly. Unit tests can only do the first one, and it's more verbose and brittle.
All those kinds of tests can be eliminated with static typing. It's true that a lot of those types of errors would get picked up in functional tests, but at least from my perspective it's not great practice to rely on a functional test to catch that kind of change. If your functional test changes it's easy to lose coverage of your basic unit tests that were only happening implicitly.
2. If the tests must be updated whenever the underlying implementation changes it might be testing too much- it's better to test behaviour, not implementation.
const x = "one two" + 3;I'm a big fan of ES6 and I haven't been a fan of typed languages for a long time but I'm liking using TypeScript. So are my coworkers.
I tend to view TypeScript similar to CoffeeScript — it brings to JavaScript some features from other languages that are convenient and preferred by a subset of frontend developers. It allows for experimentation in the language, and helps inform TC39 proposals.
In time, I suspect support will coalesce around a specific TC39 process proposal to add type support, it will graduate to stage 3 or 4, get integrated into browsers and Babel, and enthusiasm around TypeScript will wane.
For data, 46% of npm's survey respondents used TypeScript: https://blog.npmjs.org/post/180868064080/this-year-in-javasc...
Do people prefer typed JavaScript over JavaScript tho? I know that I prefer typed JavaScript, especially to write long-term web applications or Node.js server applications, but I don't think there is yet an unanimous shift towards typed JavaScript.
I'd like dynamic typing but without the implicit and dubious type coercion. Like Python.
I keep hearing this complaint, and at the same time I'm wondering why it's a big problem. So you can't find 3rd party libraries that are good enough to fill in the void from the lack of a good standard library?
Given all the constraints, it’s highly unlikely that you find something consistent.
That's a strange choice of example to highlight the sparseness of the standard library.
There's not much I can do with a class that can't be accomplished with a simple function.
I think I've evolved in my thinking over this in the last several years of experience.
That said, Babel now supports TypeScript so you should get nearly the same performance with TypeScript as you did with Flow or even just plain ES transpilation. That way you can do typechecking as a separate step like you would have done with Flow.
GCC startup time is going to be faster than Node.JS startup time, but that's irrelevant. We don't need to restart the compiler on each iteration. You can just use an auto reloader for that.
And since we're real developers writing real apps, hello world is not important to us. We want to organize our code into modules and bundle those to a single JS file that is minified in production. So we're going to process the source code one way or another.
C++ is a funny example to mention because it scales pretty poorly in the compilation time aspect, because it lacks modules. Compiler startup times are good... But it's not really that fun burning all 16 cores trying to compile Qt and still having it take forever. Compare to Go where compilation is so fast most people don't even talk about compilation speed.
All languages compile eventually anyways, even JS. It just compiles in the browser. If you really want a "zero compilation step" experience, you can just load the TypeScript compiler directly in the browser. It's been done in the past for demos.
Interesting, I hadn't considered that. I've always just had a build script (usually in package.json), and run that when I change something (either with an inotifywait loop or manually). It does make sense that if you're instead keeping one long-running node.js process instead of spawning a new node.js instance every time, tsc's slow start-up won't matter as much. I'll have to keep that in mind next time I end up doing typescript work.
I have used Angular, using a long-running webpack process which does angular template and typescript compilation, and I found that to be excruciatingly slow even for small changes, but I'm willing to bet that has more to do with Angular than with Typescript.
> C++ is a funny example to mention because it scales pretty poorly in the compilation time aspect
C++'s compile times are horrible, I won't try to defend it - waiting another eight hours for Chromium to compile because you need a build with debug symbols is just horrible. However, most of my time actually working on relatively small C++ code bases is pretty good; compiling each individual file doesn't take very long, and you only recompile the files which have actually changed, and recompiling one C++ file and re-linking the project takes around 0.4 seconds (unless you're doing something stupid like linking in all of webrtc, which we admittedly do for a couple of projects at work). Compiling a typescript file which just contains `console.log("Hello World");` on the other hand takes a bit over a second. (I know compiling hello world isn't very relevant when your compiler is a long-running process instead of a one-shot thing, I'm just including it because that's what my experience with tsc has been until now.)
Do you happen to know of any good resources for how you would run the compiler multiple times from one node.js process? I imagine webpack maybe does it already, but I would be interested to import the compiler as a library or something, and do some testing to see how big of a difference it actually makes to not start a new javascript VM every time.
https://github.com/Microsoft/TypeScript/wiki/Using-the-Compi...
And of course you can read the source code for Webpack's typescript support.
Sidenote: although it's less popular, I highly recommend looking into Parcel Bundler, it's much nicer to use and has no configuration required. You can, for example, point it at an HTML file with a script tag pointing to a TypeScript entrypoint that includes NPM modules and it will handle compiling, bundling, minifying transparently. And it's relatively quick.
I probably shouldn't have lead with the "not only is it an extra step" thing.
Why? I've worked on large codebases in Coffeescript, ES6 and Typescript. Whatever this whole community sings and believes, but Coffeescript still wins for me. ES6 is still trying to catch up but will probably never reach the beauty and ease of Coffeescript. Both are transpilers, only ES6 with Babel is a total horror to manage (just upgraded a large codebase to Babel 7..).
Typescript takes about 2x the time to write if you want to create all your typings properly. I hear you say; only in the beginning, later it will speed up the development process. I've never seen that in reality! I've actually never seen a proper codebase in Typescript. Show me a Typescript codebase not using the type 'any'! In a decent system language you can't get away with that, it's just a fake sense of security.
A good codebase should not be dependant at all by Typescript or whatever hype comes next. Writing a good codebase is IMHO a craft and should not depend on the language or a bunch of tooling. If Typescript is way to go, what about Python, Ruby, abandon it, deprecated? Are those inferior languages compared to Typescript? Typescript is just another hype, very smart play by Microsoft btw.
I can the same way cast value to an Object in Java of NSObject in Swift.
1. One standard typed version of JS (As appose to flow and TypeScript) is a better use of open-source developer time. It also reduces decision fatigue when architecturing new JS projects. 2. TypeScript tooling is fantastic. Using VSCode or Webstorm spoils you. 3. TypeScript is a testing ground for experimental language features. It can shape the direction of future versions of JS. 4. Finally, the language is clearly well liked, in addition to being popular. We can debate the pros and cons of its quirks, but overall, the stats say developer satisfaction is high. https://hub.packtpub.com/4-key-findings-from-the-state-of-ja...
Not true at all. You balance all of this stuff inside your head anyways: this object has this shape, this function takes these arguments, etc. The only overhead is actually writing them down -- which in itself arguably speeds up development because then your IDE knows about them too.
I pushed back migrating from Coffeescript to TypeScript and I consider it one of the only times I was really wrong about a front-end technology.
That's the problem then. I have, and have clearly seen in the real world why it's superior. ES6/Coffeescript can obviously be done correctly, but chaos tends to ensue as the flexibility is abused. Over time it makes debugging/understanding difficult. TypeScript makes changing/navigating large codebases a breeze. In other words, it's much easier to do correctly than ES6/Coffeescript.
Show me a Java project without an unchecked cast... I’m not a CS person but my impression is that sometimes you need these types and they exist in the type system for a reason. No type system is conceptually “perfect” as in there are soundness/expressively tradeoffs. I don’t think using ‘any’ is always bad. Sometimes it’s even right?
But in TS, the main reason for "any" is interop with JS.
A lack of soundness is closely related to the Turing completeness, especially in languages based on HM. In an ideal world you would want a sound type system and not want Turing completeness, but the tooling doesn't exist to make those choices the most pragmatic right now.
I don't know the comparison to system languages is fair though, because the use-case for JS is quite different from system languages.
Javascript (and by extension, Typescript) is commonly used to interface between the user and the network, both of which often are outside the bounds of the type system. Add to that any code that interfaces with plain JS, such as external libraries or legacy code. When dealing with those, it's natural to use statically untyped values and type ascriptions based on reasonable assumptions.
Taking that into account, I actually think Typescript's type system is fairly well-designed for the use-case. The problem isn't really with Typescript, it's just intrinsic to the use-case of JS.
C is clearly statically typed, but among statically typed language it is quite weakly typed.
Of course, relative to other code in that language you can write good code in any language and that is a useful and important skill. If you invest enough energy and craft, you can even write code that compares favorably to good code in any language - the Linux code base is a testament to that. Still, it is a fallacy to assume that all languages are created equal. Nowadays, next to nobody would argue that writing code in Assembler is a good idea. And even though it is now possible to write web apps with C (via webassembly) there is no movement by seasoned C programmers to conquer the web.
> If Typescript is way to go, what about Python, Ruby, abandon it, deprecated? Are those inferior languages compared to Typescript? Typescript is just another hype, very smart play by Microsoft btw.
While the truism "use the right tool for the job" is overrated, it applies here. Untyped, quick to write languages are excellent for small projects. When I'm writing Python as glue code, designing nicely typed interfaces is a distraction. Also, Python, Ruby and Javascript have base types with excellent usability. E.g. when you parse time sheet data, it is pleasant to return [(time.parse('9:00'), 'document project X'), (time.parse('10:15'), 'implement feature Y')]. But when projects grow every structure enforced by the language is a guarantee I cherish. You know, there is this special case in your time sheet parser where you return a (time.parse('23:59'), Null) element, instead of using the empty string, which made the code much more elegant. But months later, when you are refactoring the code calling the parser, you have totally forgotten this behavior and introduce a subtle bug. That's the time where I wish I had a robust type system.
TypeScript is great in this regard, as you can ignore all types if you wish and gradually add them later, when the complexity of the code base calls for it. Or you start with complete type coverage from the start if that floats your boat. Or you never introduce types and just consume JavaScript. Because of that, TypeScript is especially valuable for libraries: It gives the consumers of the libraries all choices. And it's also the reason the success of TypeScript is celebrated that much: Each new TypeScript enhanced library increases the effectiveness of the tool (and reduces the amount of `any` crutches).
Also, I'm sorry but you make some weird comparisons. ES6, Coffeescript, TypeScript and Python/Ruby are 4 completely different things. Not sure why you are trying to compare them and choose a winner.
...
> Both are transpilers
You don't have to transpile es6 if you don't want older browser support.
https://github.com/krakenjs/zoid
Admittedly Flow, not TypeScript -- but 99% the same thing syntax-wise. And yes -- it was difficult to set up and get working comprehensively, but now it's there, it's fairly easy to maintain, and it's invaluable when refactoring, accepting PRs, or adding new features.
Most people using `any` should really be using `mixed` (flow) or `unknown` (ts) which at least force you to check before you use some property of those types.
If we want a clear winner to everyone's benefit, wouldn't we want Yarn to go away and for npm to gain whatever it's missing that makes Yarn relevant?
To be fair, I haven't touched Yarn in years. I switched to it, loved it, and then npm got the package-lock and some performance fixes and I suddenly didn't understand why I'd want to use Yarn.
I'm conflicted because on one hand I strongly believe that we're all better off using the same tools so we can help each other more easily. But that suggests that alternatives shouldn't exist, which stymies innovation.
NPM and Yarn don't have this problem, since they are pretty much drop-in replacements for each other. As long as `yarn install` and `npm install` both get the job done equally well, picking one becomes a personal choice. Every project that adopts a standard package.json is a win for both NPM and Yarn. There doesn't need to be a loser in this case, and diversity is good.
> Writing posix command lines inside your scripts field will work regardless of the underlying operating system. This is because Berry will ship with a portable posix-like light shell that'll be used by default.
> Scripts will be able to put their arguments anywhere in the command-line (and repeat them if needed) using $@. Similarly, scripts will have access to $1, $2, etc.
If you use either of these features your package.json will no longer work with NPM. Maybe they should call it yarn-package.json?
> Starting from Berry, we made it an explicit goal that each component of our pipeline can be switched to adapt to different install targets. In a way, Yarn will now be a package manager platform as much as a package manager. If you're interested into implementing PHP, Python, Ruby package installers without ever leaving Yarn, please open an issue and we'll help you get started!
Noooo, god no. Package management is a gargantuan, complicated task, and these languages all have their own solutions already.
That being said, it's cool that they're rewriting it in TypeScript.
But something for Python that actually works? Yes, please!
Yes and no. In the case of the `postinstall` script (which might indeed have to run on npm setups) you might want to refrain using those features. In any other case you simply won't use npm if you use them, because those are local scripts that only you and your team will use - and regardless of those features you should all use the same package manager anyway.
> Noooo, god no. Package management is a gargantuan, complicated task, and these languages all have their own solutions already.
We won't spend much time on it ourselves - as you mentioned other solutions exist and we have to pick our fights. Still, I believe this is a necessary move if we want to make our codebase clear and easy to contribute to. It's not so much about Yarn supporting everything than it is about making sure that we don't end up with a monolithic system hard to maintain.
Disclaimer: I work with TypeScript professionally.
The React team is _very_ busy already with work around Hooks, Concurrent Mode, and Suspense. There's no way they're going to pause development on implementing all these major chunks of functionality just to rewrite from one type system to another.
I've seen Dan express some frustration with Flow's pace of development on Twitter a couple times, but beyond that, no indications whatsoever that React would be converted to TS. In the entirely hypothetical scenario that React _did_ get rewritten to another language, I have to assume it would be something like ReasonML (which was created by Jordan Walke, the original creator of React).
A declaration file(s) could be included. There they could just declare types for all classes, methods, constants, etc. Similar to C header files.
(This is how the DefinitelyTyped repository handles typings for untyped source repositories: https://github.com/DefinitelyTyped/DefinitelyTyped)
Ex:
JavaScript: app.js
function app(arg1, arg2, arg3) {
// does something
return {
key1: someStringValue,
key2: someNumberValue,
};
}
TypeScript: app.d.ts declare type AppReturnValue = { key1: string, key2: number };
declare function app(arg1: string, arg2: string[], arg3: boolean): AppReturnValue;And like I said, Flow is providing sufficient benefit for the React team right now, and their focus is on expanding React's capabilities. Changing type systems is not on their radar as far as I know.
And I certainly get your point. However I wonder if they'd consider community-contributed TypeScript declaration files to the official repo as they wouldn't cause conflicts with the Flow system—
To pick a specific example, here's the file that implements the core logic for the new Hooks feature:
https://github.com/facebook/react/blob/6cb26774e27e03c7d5d6e...
As for the TS typings, there's been lots of agitation from people asking them to be officially included and shipped with React. But, again, the React devs themselves aren't TS users (that I know of), and so they don't have the expertise to write and maintain those typings. Better that they be left over in DefinitelyTyped for the community to maintain.
(I'm a Redux maintainer, and I feel exactly the same way about the typings for React-Redux. I don't have any actual TS experience myself yet, and I couldn't do anything useful in regards to the React-Redux typings. Plus, I've got far too much else on my plate to worry about those.)
Edit: but, their main codebase is in Flow, and that sounds like a mess to migrate, so I wouldn't be _too_ worried. It might slow down, but I doubt it will become unmaintained anytime before Facebook gets sued out of business :-P
There was initially talk of Flow using comments to actually work without touching the source code at all, but I don't think anything came of that... is there anything else on the horizon?
[Edit: Nevermind: I went looking for the github issue about adding types as comments, and it turns out it's already supported by flow: https://flow.org/en/docs/types/comments/ - is there anything like this for TypeScript?]
I have to ask what you're trying to achieve here. Moving types into comments just gives people who build without your typechecker the chance to break your code.
If I can have a folder of plain JS that I know will work in a browser 20 years from now without having to resurrect an ancient/abandoned toolchain, then I'll do that!
That's what Typescript is. Type annotations don't change your code, they're stripped away by babel at compile time. In fact, by default, tsc does compile TS code which fails typechecking, into valid JS code (which will likely error when you use it at least in some circumstances, but can run just fine).
Typescript is a clear superset of JS, so there's no actual logical changes or even syntactical changes done by the compiler. However, you may be confused by the often-used "compilation target" features of babel (and tsc), which is that you may write ES2018 code, target ES5, and have your ES2018 syntactical sugar be turned into ES5-compatible code. This is entirely opt-in, and not related to typescript (other than the fact that Typescript is always compatible with the latest ES spec, so you can use any legal ES2018 syntax in it).
Hope that clears it up…
With Flow, the type annotations are just stripped away, none of your Flow code affects runtime code.
This is not so with TS since you have things like Enums, which will be compiled into objects and are part of your runtime code.
If you write type annotations in Flow, they're stripped away.
There's no difference. TS has some additional features which are purely optional that don't get purely stripped out, but you're not mandated to use them.
In my eyes, it's a philosophical difference between the two, Flow can be more easily integrated into an existing codebase by just adding //@flow at the top the file and has no features which can affect runtime code. Whereas TypeScript tries to be a different language altogether that uses a new file extension, adds new features, and has its own compiler.
When you can implement a tool like this using TS, let me know https://github.com/flowtype/flow-remove-types
Enums are a fair point, those aren't in the ES specs (though I suspect at some point they will be). However, they're an incredible addition and they really are just syntactic sugar for a more complex type of object.
BTW, typescript supports jsdoc-style annotations, and --allowjs even lets it typecheck javascript code. It also supports more, because nobody actually only wants those things; they're not that great on their own.
You might not think the differences is a big deal, but affecting runtime code is a pretty major line to cross. Not that there is anything inherently wrong with that, but at that point it becomes a different tool, in my opinion.
enums are a tiny, extremely useful and extremely optional part of the language and they don't warrant this label of "philosophical difference", IMO.
Still, I once did Flex development (would compile to a SWF file, or with Adobe Air to a native executable). It was a pleasure -- so long as you used the Flex/Flash Builder IDE (which was itself built on top of Eclipse). Trying to develop in vim was harder, though mainly because of the MXML part, but I still liked MXML better than HTML. Later at the same job I did Node and found that pretty enjoyable too, plus I could use vim all the time.
Tooling is always a concern with a language. I think dynamically typed languages are partially successful because they let you get away with so much less tooling. Though not all dynamic languages are equal in the tooling they can trivially support, e.g. Common Lisp with Slime enables all the usual stuff (who calls x, who sets y, who specializes method z...) and you can use Slime from a variety of other tools.
I'd consider flow dead.
Sure they would. Flow has nothing to do with Facebook's business strategy, or its marketing campaigns, or even its corporate strategy. I'd be surprised if anyone on VP or higher even knows what it is.
Insofar as "NIH" wins at big companies, it's when there's a business motive to promote a certain technology or FUD about what other technologies might exist.
But engineering team A deciding not to use engineering team B's tools despite working at the same company? Happens all the time.
You can turn typescripts type inference on on a regular js file.
https://www.typescriptlang.org/docs/handbook/type-checking-j...
Isn't Flow more concerned with soundness than intellisense? Has TypeScript caught up with Flow in this regard?
Perhaps it's because I prefer to do my work in strongly typed, pure FP languages where I can but I work professionally with JS and have been investing in Flow there for over a year now. While Flow is still not exactly great it can at least mimic exhaustive pattern matching and catches most unsafe type errors without getting in the way of common JS patterns too much.
The reason the yarn maintainers are giving is because they want more contributors? What advantage will that have if TypeScript isn't catching the errors you used to be able to catch or don't know about yet?
Curious to know if it's worth migrating over to TS without sacrificing anything other than the minor inconvenience.
I think the answer is: it's very close. It's still a little behind flow on soundness, but it's now close enough (if you enable strict mode, which you should!) that you're unlikely to notice the difference.
The TS type system is very impressive. It can't do everything that the functional languages can do, but it can do some things that they can't, and importantly it's still improving rapidly.
You may be interested in the roadmap/changelog page: https://github.com/Microsoft/TypeScript/wiki/Roadmap
1: https://npm-stat.com/charts.html?package=babel-core&package=...
2: https://trends.google.com/trends/explore?date=today%205-y&q=...
3: https://developers.slashdot.org/story/18/11/25/017227/micros...
[0]: https://medium.com/@bluepnume/introducing-paypals-open-sourc...
[1]: https://medium.com/@bluepnume/jsx-is-a-stellar-invention-eve...
I hope that's not that silent, because at that point, everybody who works on that project will have to upgrade as well.
That said, shipping the light-weight POSIX-like shell will make it a lot easier for scripts to be multiplatform. That's the improvement I'm looking forward to most.
Also note that we recommend using `yarn policies set-version` to enforce the version of Yarn used by everyone in your team with very little friction:
https://yarnpkg.com/en/docs/cli/policies#toc-policies-set-ve...
I wrote a recent comment comparing the history and goals of Yarn and NPM:
documentation; https://yarnpkg.com/lang/en/docs/cli/audit/
original feature issue: https://github.com/yarnpkg/yarn/issues/5808
release comment in that issue: https://github.com/yarnpkg/yarn/issues/5808#issuecomment-441...
That is very nice. No need to install other dependencies just to do 'rm -rf'
That being said, maybe we'll offer some builtin as well (possibly in a similar way to what CMake offers?[1]). That would be worth an RFC later on :)
[1] https://cmake.org/cmake/help/v3.2/manual/cmake.1.html#comman...
Which lightweight shell will be used on Windows? Does it also bundle standard unix tools (if a script pipes to grep or less for example)?
How will paths be translated on Windows? I’ve attempted something similar recently and had to do a fair amount of regex magic + using cygwins built in path translation utility to preprocess commands. Curious to see if there’s a better way to solve that.
It will be in-house, and very basic. We don't intend to rewrite bash, just to provide the basic experience that is usually needed when adding script into the `scripts` field. For more complex needs we'll simply offer a way to opt-out and use the native shell, or to call Node scripts.
> How will paths be translated on Windows?
The current Yarn tries to do this by using the `path` native module. It's quite error-prone since backslashes tend to appear in the worst possible places. For the v2 I plan to work with all paths in a posix style, and convert them into Windows paths right before they reach the filesystem (which is similar to what Cygwin does, as you mentioned). It would be a bit slower on Windows, but massively simpler in the codebase.
p.s. I love Yarn :)
I still come across bugs (that are definitely in npm itself) that have been around absolutely forever, like:
> npm ERR! cb() never called!
It sometimes gets its primary purpose, dependency resolution, wrong. I'll give it a perfectly reasonable package.json to install, which it will do, and then `npm ls` will still error with "missing dependency!" in some package. This should not be possible.
Related, it will put packages from the flattened tree in the wrong place. I can have a dependency (that other dependencies need, specified in their peerDependencies) specified in my top-level package.json and bafflingly, npm will still move it from top-level node_modules into the node_modules of something else that happens to use it, breaking the peerDependencies I was trying to satisfy.
On the install process: even if the total time to install is roughly on par with Yarn, I find that Yarn is much smoother. Whatever they're doing, they're yielding the CPU a lot more, and the result is I can actually work while it installs. npm meanwhile doesn't yield much during install and slows the whole system to a crawl.
Some npm commands are extremely neglected. The "success" message printed by one of the user/permissions related commands is simply: {}
Lastly, I will leave this terrifying comment here: https://github.com/npm/npm/issues/16528#issuecomment-3075400... – note this comment was left 2–3 years after receiving $10M in funding.
I don't blame them for being one-upped by Yarn at every turn, but they still fail to get the basics right, let alone innovate on things.
Edit: also, in my experience using npm for some little stuff recently, yarn is still faster installing packages.
Edit2: I also like the ability to run scripts/commands from the base level of command, e.g. `yarn start`, `yarn webpack --mode production`, `yarn build:web`
Our lockfile format worked fine for the past three years (bar the unfortunate YAML incompatibilities that we're about to fix). Don't fix what isn't broken :)
After getting `package-lock.json` and `npm ci`, I would rather wonder why choose yarn instead of npm.
It coming standard means one fewer dependency for everyone on the team to install, which is important on my current team where roughly half are backend- or mobile-only.
I like both yarn and npm, and yarn would have some benefits for us, but probably not enough to counter the extra effort onboarding other devs. npm still has some pain points, but I’ve ran into a few pain points on yarn too. And I think there being multiple projects here has helped the ecosystem.
npm is also doing some neat feature development (npm audit).
Also, the npm team is fantastic, whereas when I adopted yarn early on they dismissed the issue I opened about yarn not working for my setup. They’re a good team, but that lowered my confidence that I’d be able to get through any obstacles while using it. It’s still a fantastic tool though.)
1) Start or inherit a project using Yarn because that's what all the cool kids are using.
2) Develop for a while, everything's fine.
3) Lose a whole day when you eventually stumble on a Yarn bug or missing feature in Yarn.
4) Angrily switch the project to NPM, solving the problem immediately.
5) Continue developing as usual.
I think this happened on like half a dozen projects after the yarn/npm split occurred, and I saw it happen as recently as Fall 2018. Developers leaned trend-chasing there, but after being burned several times even the trend-chasier ones were tepid on yarn and tended to accept that if they started with it they'd probably end up switching before long.
FWIW I don't like npm much, but I still default to it so I don't, inevitably, hit the above situation at some point. Yarn doesn't provide enough benefits to make it worth having an even less-trustworthy tool in my build process than npm already is.
[EDIT] TL;DR: We all got sick of ending up on open GH issues for Yarn when trying to track down build and, worse still, run-time problems. So we started favoring NPM again as the lower (though far from zero) headache option.
This effort we start is in no small part to decrease the number of issues that will be created by empowering the users to unblock themselves* and solidifying Yarn's codebase.
* You wouldn't believe the number of issues that are simply about things working as they should - we can't really blame their authors because it can be quite hard to find the right paragraph in the documentation, but it's extremely taxing on a small team. Similarly, we often have issues created against older releases, or without reproducible test case.
So I'm not sure you can glean too much from just looking at an issue count in isolation.