Hacker News new | past | comments | ask | show | jobs | submit login
A Newly-Generated Create-React-App 2.1.5 App Has 1,568 Dependencies (twitter.com/garybernhardt)
276 points by _0nac on Feb 18, 2019 | hide | past | favorite | 126 comments

Note that the listed discussion is specifically about projects generated by the Create-React-App tool, not React itself. React has always been usable by just adding a pair of `<script>` tags to any HTML page.

Dan Abramov pointed out [0] that:

> in terms of feature set (test runner, devserver, compiler with support for bundle splitting and optimizations, error overlay with editor integration, static code checker) it’s comparable to a small Xcode.

> It’s valid criticism that tools like Xcode are installed once whereas react-scripts is per project. But the upside is you never have the “different projects demand different Xcode versions” problem. And everything runs on CI thanks to full encapsulation.

> I’m hoping approaches like Yarn Plug’n’Play will give us best of both worlds. Shared install for the same versions between projects but with isolated and versioned tooling.

[0] https://twitter.com/dan_abramov/status/1097309141075456000

The bigger issue is less about weight (most of that doesn't end up in the final bundle anyway) and more about the fact that each of those dependencies is a point of possible a) breakage and b) security compromise. The latter in particular has been a rising issue with NPM's micro-packages trend.

I don't know how that problems is going away. Javascript doesn't have a great standard library and it's hard to impose restrictions on which packages/features/functionalities should be the "defacto" ones.

The strength of JavaScript is also the problem: it's really easy to create and distribute really flexible and dynamic code. This encourages a massive, vibrant ecosystem of packages which are extremely modular and flexible, and often tiny. So you end up building sandcastles out of thousands of grains of sand instead of LEGO houses.

What we probably need to do is walk that back a bit at a cultural level, and make our libraries just a bit more cohesive and self-contained. There are a few libraries like Lodash and Ramada that aim to be general-purpose toolkits, and Vue and Angular are good examples of reactive libraries that come with their own state management, plus some other stuff. Of course, the latter probably (I'm not actually positive) carry their own big lists of npm dependencies.

And for a tooling example, VSCode is basically a much more cohesive and holistically-designed version of Atom.

> I’m hoping approaches like Yarn Plug’n’Play will give us best of both worlds. Shared install for the same versions between projects but with isolated and versioned tooling.

TBH, I personally am not too concerned with the duplication/disk usage, but the number of dependencies it pulls is a pretty big one.

> React has always been usable by just adding a pair of `<script>` tags to any HTML page.

Yes but good luck with React.createElement(). React without JSX is really a pain to use (or Preact, Inferno, etc).

Vue is much more straightforward for those simpler cases where you don't need/want to setup Babel, Webpack, etc.

> Yes but good luck with React.createElement(). React without JSX is really a pain to use (or Preact, Inferno, etc).

What's painful about it? I prefer it without JSX, personally; JSX is a pretty simple syntax transform that doesn't really gain you anything that I can see, makes manipulating props a lot clumsier, and needs extra tooling. Most of the time it's almost identical with or without JSX, but when there is a difference, I've always found without to be smoother and clearer. You definitely want to assign React.createElement a shorter name, though.

There's a number of options available if you don't want to use JSX.

For example, if you prefer to use small wrapper functions like `h(MyComponent)` and `div()`, there's `react-hyperscript-helpers` [0].

More recently, Jason Miller published `htm` [1], which provides near-JSX syntax using ES6 template literals, and no build step required. It appears to be a very viable alternative to JSX in many ways.

[0] https://github.com/jador/react-hyperscript-helpers

[1] https://github.com/developit/htm


My claim of "you only need two script tags to write a working React app" is entirely accurate.

That _does_ limit you to just `React.createElement()`, which is the core React API.

If you don't want to call `React.createElement()` every time (whether or not you alias to to something like `h()`), then you either use JSX (and a build step), or one of the other options like the ones I listed.

Pointing at that, and then claiming it's insufficient for "building an entire house", makes it look like there's some goalposts being shoved down the field.

The goalpost is -- and always should be -- to build a working app without pretending you don't need a ton of dependencies. You do, unless you have a much bigger time budget than most of us.

We can do only so much with a limited toolset.

By your analogy, we should only be able to make a working app with `document.write()`.

Let's be realistic. A pair of script tags is only theoretically possible and nobody is stopping at that.

I never made any claims about what other tools you _might_ need to build "real world"-ish apps. I'm only saying that you don't actually need anything else, including build setups, to be able to write working React code, because that's a common misunderstanding about React. Folks assume you _have_ to have Webpack and Babel to use it.

Technically true, but that point isn't really meaningful if the amount of tooling you realistically need to build an app keeps on growing.

In theory I only need gcc, vim and a bunch of header files to write the next Chrome as well.

Additionally if you find local development unpleasant you can always try remote development via something like https://codesandbox.io/ which will setup a project with everything you need.

You know that jsx just compiles down to those calls right? Heck if all you need is just the transpile of jsx, typescript's compiler will do it just fine from the command line, no config to setup.

Obviously, but you are missing the point.

Just FYI, you can easily include a @babel/standalone script to get JSX in your script tags.


Oh this is good!

How is the browser support for this?

Note that running the transform in-browser on anything more than a "hello world" is going to be relatively slow. It's only useful for cases like a "single HTML file React example, with JSX syntax capability", and is _not_ recommended for any kind of production use.

Thanks, I saw that after writing my comment.

It seems Vue is definitely the simpler choice to write reactive components in projects without a build chain.

As I wrote up-thread, Jason Miller's `htm` library seems to be a very nice alternative to JSX that does not require a build step:


That might work in some use cases, but unfortunately tagged template literals require greenfield browsers. Vue 2 works in anything that runs ES5.

It works well, but so slowly. I tried it for a real project, decided against it. Precompiling JSX into ES6 works fine, and the result is incredibly fast.

totally agree.

Not just because it's harder to use without JSX (and JSX is a great idea), but also because every Stack Overflow answer assumes you're using Webpack and JSX. For a beginner, choosing not use JSX or Webpack, etc just makes the learning cliff steeper.

In addition to Yarn PnP, the folks at npm are still working on tink[0] which is early but useable right now.

[0]: https://blog.npmjs.org/post/178027064160/next-generation-pac...

Yep. I've glanced briefly at both PnP and Tink. Both sound neat conceptually, I just haven't dug far enough to know what the differences are in terms of actual approaches and implementation. Also haven't had a chance to play with either yet.

Long-term, stuff like the size of `node_modules` seems very solvable.

Simultaneously with that, I do think that there'd be benefit if some of the larger JS build tools started evaluating their own transitive dependencies and submitting PRs to inline some of the smaller pieces somehow [0].

[0] https://twitter.com/acemarke/status/1073593305378754560

Unfortunately, the ts compiler neither supports yarn pnp or rink right (and angular doesn't either). It's the biggest blocker for me personally - but I've played with yarn pnp and it's great.

Sounds like a job for Blazor! https://blazor.net/

A former boss of mine had a sign above his desk: “Transitive dependencies are the lifeblood of stuff. We don’t build stuff, we build software.”. While I am not a JS developer, I am distrustful of every dependency brought in and aggressively work to eliminate the only kind of useful ones. They’re debt brought into the code base and must be constantly evaluated for security concerns, interactions with other dependencies, and upcoming changes being incompatible with your code, which may in turn cause you to be unable to upgrade other dependencies.

Not having to write code is great, but when you bring something in it becomes code you must maintain for however long it is in your project. The utility calculus is variant for all projects and even different phases of the same project. But the calculation should be done often and ones that fall below the utility threshold should be removed.

One thing to note about create-react-app is that nearly all, in fact almost literally all, of those dependencies are development tools. They are also a pretty “normal” configuration of tools, based on standards rather than some custom framework.

This means that if you have a problem with create-react-app or it were to be abandoned, you could just get a different development tool and likely make zero changes to your actual code.

For sure, I'm not necessarily commenting on this particular example, as I'm unfamiliar with the tooling brought in by that command, and don't use JS myself. It's more of a comment about software dependencies in general. I'm usually much more tolerant of development dependencies than production dependencies.

And at what utility threshold should one ought to take a lib vs self-write?

Unless you're deeply experienced, it's a very hard judgement to make.

Plus the time spent investigating is not small either.

My rule of thumb is to take a lib if it's not you're core concern, and write your own if it is. You only have one core concern in a project, and that's what the customer pay for.

It's different based on each dependency and where you're at in the project lifecycle. If you're running as fast as you can to get off the runway before you crash, you have more of an incentive to bring it in and punt the problem down the road. But after that point passes it should be reevaluated. You should know every dependency in your code and why it's there.

For me, I find that it's a function of overall value to your code, number of issues you've had with it, overall size, ability to understand the code relative to what it's doing, and project health. Again, the calculus is different for everybody, but the important aspect is that you're consciously thinking about the utility of the dependency.

An ORM is hard to write, is often hard to read, but provides extreme value, and hopefully has a large community to quash issues and contribute to the project's health. To borrow an extreme example, left pad is not. Even if left pad is not in your core competency, that's not something that should be brought in because you can write your own. Even left pad may be subject to the event-stream style attack, and it being out of your control is risk you're bringing into your project.

Risk management is tricky, and you'll never get to 0 risk, but you should try to minimize it where you can reasonably do so. It's all about balance.

Sign above Newton's desk: "If I have seen further it is by standing on the shoulders of Giants."

We can strive for sustainability and autonomy, but we're forever dependent on each other's work. As they say, it's turtles all the way down.

Yes, but there is a lot of nuance here.

Introducing dependencies is a quick way to get to market since you don't have to build a universe from scratch.

Once you've gotten to market, you have to support your thing. This is when dependencies start to have a non-zero cost. When you'd rather spend engineering efforts on building new features, you instead have to do regular house cleaning to make sure your thing continues to work and have a happy upgrade path.

The larger the engineering organization you work in, the more apparent this becomes. Smaller orgs can sometimes brush the ugly under the rug. Larger ones bump into issues constantly. I'd wager that 5% to 10% of engineering might be dealing with maintenance of dependencies.

(fwiw, I'm mostly speaking in terms of my experience as a backend engineer.)

You are seeing to the heart of my argument. Thank you for that. I agree on the 5-10% mark, and find it's true even in smaller orgs that have a mature enough product. Once the product solidifies, having a bunch of different dependencies dictate which direction you can go is not in the best interest of the company, and should be reevaluated accordingly.

To thoroughly abuse the metaphor, you don't always want to go where the giant goes. Sometimes you would like to climb down and walk your own direction. Dependencies can take you near where you want to go, and if they can take you all the way there, terrific! Use them for as long as you can! But if you're not directing the giant, you're subject to its whims. And the more people standing on the giant's shoulders, yelling in its ears where they want it to go, the harder it is to make sure it's going where you want. At a certain point, this risk outweighs the rewards, and you adjust accordingly.

> I am distrustful of every dependency brought in

Ever look in your node_modules folder? I dislike the JS ecosystem for this very reason. It's so common to find dependency soup in any non-vanilla JS app.

Not in JS, but yes I do. Often. A useful exercise is trying to just bump everything one at a time and seeing where you can't.

Tooling helps with this, but I usually do this reevaluation task when I go to do dependency bumps. "Why can't I bump this dependency to its current version?" usually causes me to reevaluate the dependency thoroughly. Many times it results in just making an upstream PR, but sometimes the decision is made to inline the parts that are used. As an example, we had a dev dependency that all it did was print tables with borders for pretty printing test failures in some capacity. When I went to do a language bump, it was incompatible, so I rewrote it in 10-15 lines using the standard language library. At the time, it was helpful, but it overstayed its welcome by preventing a language upgrade. As a counterexample, our ORM has caused me extreme strife this month because it changed a feature we were relying on heavily. That resulted in a bunch of work, but the dependency is so useful to our project that I would not have considered rewriting it.

It's a little ridiculous to view this as a problem. I am currently working on a small personal project in my spare time with 775 dependencies. Quickly perusing the dependencies the reason there are so many is because I am using:

* Webpack

* Unit testing (Mocha)

* Code coverage (Istanbul)

* Browser transpilation (Babel)

* Type safety (typescript)

Now for an apples to apples comparison I used to work on c#/.net. Complaining about these dependencies would be akin to me complaining that I couldn't manually audit the unit testing dlls that VS is using to do code coverage for me. Of course, no one ever audits these DLLs. A more interesting analysis is to look at how many non-dev dependencies you have (I have none, I doubt this basic react package has more than just react for the production code).

Of course one could argue "someone might stop maintaining this project", but this is equivalent to saying "I won't use open source". In fact, in my experience the opposite is true, with closed source paid software becoming obsolete more regularly than open source alternatives. If a company decides something isn't making money they will usually can it while with open source at least someone has the opportunity of picking it up when an author loses interest.

Dev dependencies are as dangerous as production dependencies and always have been. Read this from 1984: https://www.archive.ece.cmu.edu/~ganger/712.fall02/papers/p7...

Those 1,568 create-react-app dependencies are maintained by people you have no formal relationship to, and are all versioned independently. Visual Studio is one monolithic package released by one of the largest companies on earth. Microsoft is not going to back door you and it has a huge incentive to stop anyone else from directly back dooring you via Visual Studio. On the other hand, the maintainer of the event-stream NPM package, with ~1.5 million weekly downloads, recently gave control to a stranger. They successfully back doored it and evaded detection for over a month. https://blog.npmjs.org/post/180565383195/details-about-the-e...

Is that any less true for completely unrelated pieces of software on the same machine? If you have a nice secure monolithic .NET project on your machine, and you also ran a create-react-app project on the same machine, shouldn’t you be just as worried?

Not really, at least IMHO. Not every vulnerability in [insert unvetted react dependency here] contains a host-targeting malware payload. In fact, I'd imagine those are the minority. Some concern is certainly warranted though.

now with the nuget ecosystem VS projects also depend on external dependencies you have no formal relationship to

yep. In theory a dotnet project pulling in nuget packages is in the same class as a node project pulling in NPM packages.

In practice, it's tremendously different.

As mentioned, a do-nothing react app has 1500 dependencies, all managed by who-knows-how-many different companies and individuals

A do-nothing aspnetcore app has maybe a few dozen dependencies, and with the exception of Newtonsoft.JSON, all of these are managed and supported by Microsoft.

When you scale that up to a real app, I don't even know what you get with Node/npm? 2500 dependencies? With aspnetcore you probably end up adding 10-20 more dependencies, and some of them are probably written by Microsoft.

So, your "potentially untrustworthy package count" in node is about 2000 packages, whereas for aspnet it's about 10 packages. You can review and pay attention to 10 packages. 2000? Not so much

Aside: A java/maven project probably falls somewhere in between, but closer to the aspnet scenario. Instead of a few dozen dependencies you might have 50, but it's still realistically possible to review them all, and they're far more likely to come from trusted publishers such as the Apache foundation.

That's a different issue. I was replying to the claim that Visual Studio itself vs. create-react-app itself is an "apples to apples comparison" (their words).

I think the "package count" is perhaps a bit of a red herring. IMHO the "publisher count" is more important.

I don't care if there are 700 packages if they all come from the Apache Foundation. I trust the Apache foundation and as such they can be considered one "block" when it comes to reviewing their chance of releasing a malicious/hacked package.

Visual studio is basically ONE package from ONE publisher Internally it's made up of thousands of tiny components, and includes third-party open source software such as Newtonsoft.JSON, but Microsoft is responsible for vetting all that stuff, and they do.

The problem with the JS ecosystem is that many of the packages come from all over the place. For example, create-react-app depends on envinfo which is published by "Trevor Brindle". It also wants cross-spawn, from "André Cruz", chalk from "Josh Junon", Commander.js from "abe tomo", fs-extra from "JP Richardson", this list goes on and on.

Who are all these people and are they all trustworthy? I don't know, I can't tell, and neither does anyone else, which is the core problem.

Well with .net it's usually less than 10 of dlls (not counting .net framework itself, though it may have increased in several years). As opposed to npm, where webpack itself may need 3-5 packages (css loader, url loader, etc), not counting their dependencies.

But I'm not saying it's better or worse, just different. But for sure it's harder to audit.

I am (usually) not a JS dev, but we have quality standards which are, to some extend, regulated in my business (banking/payments), so to use this, I would not only want to, but to some extend need to understand all (ok, maybe not all, but at least the ones that seem to not be maintained very well or the ones that come from lone devs who might find another hobby and just quit maintaining) these 1568 dependencies and audit them for security every update. I would need to make sure they are maintained and if not decide if we will maintain them (if we are on a certain version of a NuGet package (we use .NET Core mostly) and the maintainer quits but somewhere in our stacks something depends on it, we have to make this decision, but we or the packages we use simply do not have that many dependencies). I do not want to dismiss other companies by saying 'apparently they don't care' but in the React/Node (JS) space in general, that feeling does creep up quite often when I read HN.

Though this submission is talking about development dependencies rather than runtime dependencies. For example, the scaffolding it generates builds a Javascript app that runs in the user's browser.

Still a potential problem, since each transitive dependency even gets to run arbitrary code during install on the developer's machine, but a different one.

Point taken, but then we get into the 'omg how is this development package installed on the prod machines?' ' Because it is convenient for finding issues'. I am sorry to say I know disturbingly many devs that run dev on prod because they can just continue devving on prod. That's not restricted to Node but I see it with RoR and .NET Core as well.

That would not pass muster at all for me but I see it quite often and interestingly not in startups but bigger companies on departmental level (no code reviews there anyway...).

The problem here is that any code run during development could generate code that ends up in production. Even if the dependency isn't used in production, there is a "compile step" (though it's technically transpiled) during which all sorts of mayhem could ensue.

Absolutely. It's like a static site generator having a bunch of dependencies. I just wanted to refine the distinction, though it doesn't really change much. But you can at least be more prudent here than you could with 1,600 production runtime dependencies, like doing your development in an isolated environment on your own machine.

I too work in this regulated business, and don't think your argument holds unless you don't inventory your dependencies and regularly scan code (source code and dependencies) for vulnerabilities

Presumably you are not the target audience for something like this, which is a batteries-included getting started package.

You could for example use React with TypeScript and have far, far fewer dependencies...

"JS developers keep reaching for huge JS packages. Just import small ones"

"JS developers install too many small packages."

Whooooooo cares. When you come up with the maximum arbitrary acceptable packages (including nested dependencies) for a project, and then also the arbitrary minimum LOC needed to publish a package (for all you leftpad haters), then throw your numbers in the toilet and stop talking.

I love that Babel, Prettier, Jest, etc use plugins as individual npm packages. I love the ecosystem it has created. I love that we have a big ecosystem that improves developer experience.

Genuinely curious: how long have you been developing web apps, and what stacks/platforms did you work with previously?

I ask because your reaction goes against everything I've ever felt, and I sincerely want to understand.


I've been working in web dev since 2008 and have never been happier with the ecosystem or more productive.

Cool. Still excited to hear from @stevebmark!

When you started in 2008, were you self-taught, college/university or bootcamp? No wrong answers.

Have you been working primarily in JS the whole time?

Did you do front-end, back-end or some blend of the two?

It looks like the left-pad incident has collectively taught us nothing and has had no lasting effects. One of the things that bothers me the most is over and over casually downloading 1568 independently controlled packages from a free-for-all repository (also privately owned and controlled, but that's a different discussion).

create-react-app is a complex tool put together by I team I largely trust. What I want on my machine is a static build of their work, not the whole sausage making factory in 1568 pieces. Once I would have the binaries, the whole of npm and the JavaScript ecosystem could go away altogether and I would still be able to build and deploy my apps.

The package, in its published form, would be vetted by the create-react-app, who have a much better idea of what's going on in their dependency tree than I do. If they decided they need that many dependencies, it is up to them to manage the complexity. That said, it would probably make their lives easier to depend on 10-20 packages, statically built by people they trust, and so on.

Even if the result of this would initially be very similar to today (still running the same code of those 1568 packages), it would make me trust this stack a lot more.

Yes but it does alot of stuff.

It's not surprising or concerning.

That's what it takes to get modern things built - lots of other things.

Exactly. Even if it had 10m loc and 10k dependencies, that’s not a problem at first sight.

In fact, the 1.5k dependencies in this example is a drop in the bucket when you consider all the dependencies that your react app needs to do anything useful (http, dns, tcp, ip, browsers, OS’s, et cetera).

I’m not defending React here, I don’t know enough about it, I’m just saying 1.5k dependencies for a hello world app might be bad, but it depends on the details.

And repeating as usual, it is caused by lack of standard library for js environment. All of things mentioned could've been packaged into 1-2 dependencies. But instead we need to independently add each one.

Similar case with babel and webpack, that each plugins (and loader) is a separate dependency. I don't know if it's more efficient or modular for development, but it is surely bloat the packages.

Agreed. Why reinvent a wheel that's there for the using, when you could be working on the aspects of your project that make it your project?

Because the scope of a project should include usability, speed, resource thrift, maintainability, and security.

The whole brogrammer culture of "throw another library onto the fire" is the reason that simple programs require crazy amounts of computing power.

Unless you are doing assembly language programming at a clean screen then you are building software that sits on the shoulders of other software.

It's not just JavaScript that has dependencies - everything does.

You make a very valid point, but compared to other programming languages and cultures, the JavaScript ecosystem encourages mammoth projects with many more dependencies than they need.

It’s not the concept of dependencies that’s at fault, it’s the number of them proportional to the task.

> Unless you are doing assembly language programming at a clean screen then you are building software that sits on the shoulders of other software.

Yet, we don't just eat dirt off the street because even when we eat the usual food, there's always some dirt in it.

Really bad analogy. Most runtime libraries (or OS libraries for that matter) of other programming languages are of high quality and don't introduce 20 seconds of non-interactivity on a gigabit connection and 4-core CPU with 32GB RAM.

A ton of websites out there do the latter.

I don't need to do assembly language programming because the tools I have (that are built on top of it) are actually good. Unlike those in JS land.

I don't exactly understand the point of create react app. Are there people who churn out apps so regularly that this tool has value?

I tried it and in order to satisfy everyone's needs it seems like overkill tooling for most needs.

For context, I'm a lead frontend dev in a company of a few hundred people.

Most people don't remotely know how Webpack works. And they shouldn't have to! Same for most other developer tools. You need a few people who can dig out issues if they arise, but most of your people will be concerned with actually building things on top of those tools.

When every team starts a new project from every few months to every few years, having a boilerplate setup quickly becomes very valuable. The added benefit that third-party boilerplate has is that you don't have to maintain the whole lot yourself.

Needless to say these upsides don't come without issues, security and accountability being the big elephants in the room, but popularity helps here, too. The boilerplate is used by a lot of people, in organizations both big and small. If an issue arises, you can usually collectively work out the problem very quickly. It doesn't make the issues go away, but it gives you a good balancing point.

As a tradeoff versus either setting up every project manually or maintaining your own boilerplate project, it's definitely worth consideration — it might not match your needs, but it's a strong option.

Thanks for sharing. I'm not going to be one of those, "well you should learn how it works" kind of people. If people make useful, maintainable products with these tools, great.

I think maybe I just struggle with the concept of being that hands-off with the tooling. I don't think I could cede control to some one-size-fits-all solution. For example, what happens when you run into some important library that doesn't tree shake or minify properly? What do people do? Do they just pick different libraries for the wrong reason? Do they just deploy an un-optimized application?

Not knowing how the stuff you depend on works feels really scary to me. Reminds me of the Star Trek TNG episode about "The Custodian" where the colony came to depend on a tool that nobody knew how to fix, so their lives were shaped by the tool's abilities, not the people's desires.

The flip side of this, is I know how it all works, and I don't want to deal with it anymore. I spent 2 quarters at my last job digging through all the webpack/babel stuff just to come up with something that didn't work as well as CRA does out of the box.

And on top of that, it's all different now. I'm not as interested in trying to maintain all of that, on top of maintaining my app. CRA is a fantastic tool for this.

That is why Create-React-App has an exit option. This results in a configured WebPack app that can be customized by hand but no longer can be re-configured with c-r-a. I learned a lot about WebPack and other dev tool configs by exiting from c-r-a to see what it produced since I hadn't used WebPack prior to react.

> Most people don't remotely know how Webpack works. And they shouldn't have to!

Until it breaks down leaving the project in an unmaintainable state, you're right. Then it's a scramble to understand and update that in my experience usually results in locking that dependency down to a strict version number and hoping that won't break anything else. It's great for security as pointed out in this thread /s. Not the optimal solution, but then again, they don't pay me enough/have enough staff for the optimal solution. And this is code that isn't even part of the app! Just shitty tools preventing me from even building the app. I can relate to the people complaining on here. This is with one or two dependencies too. Try solving those issues a few thousand times. You'll wish this horrific trend of front end code compilation would just stop. The problems truly never end as soon as one has to deal with npm and js dependencies. Which is not to say other languages don't have the same problems. They do, just not on this epic scale of shit.

From my experience, I’ve never had CRA suddenly break down all of a sudden and leave it in an unmaintainable state. The whole point of CRA is that doesn’t happen.

I agree that most of the reason to use CRA is to avoid needing to set up a complicated toolchain. However I've mostly stopped using it now in favour of Parcel. That gives you the zero-config of CRA without the weight. As a test, I just tried setting up an absolutely minimal React + TypeScript app. This is what I did:

  mkdir parceldemo
  cd parceldemo
  yarn init
  vi index.html 
  vi index.tsx
  npx parcel index.html
The two index files are here: https://gist.github.com/ascorbic/3b075105b49917975326f1d31b3...

...and I have a working React app, with hot module reloading and TypeScript. Parcel installs TypeScript as a devdependency and react and react-dom as dependencies, and starts the HMR server. It took less than one minute.

Because almost no-one in the office knows how to do anything without that tooling? I wish I was kidding. Not in my own company but I am integrating with a partner at the moment and any deviation from the create react app and subsequent tutorials that build on top of that is stopping them dead in their tracks. Things like 'JSX is some magic programming language with magic and more magic' is akin to, in my world, 'XAML is some magic language stuff that has nothing to do with C#!'. Obviously both are (trivial) transformations, but most 'break shit fast, break everything' crowd seems to not have grasps the absolute fundamentals of anything. But, to be honest, when it works, they do work at breakneck speed; the downside is that the result is on a 6-12 month throwaway (complete refactoring) cycle. Which is ok for many projects.

>Are there people who churn out apps so regularly that this tool has value?

Its the opposite. You create a new app so infrequently that its not worth learning how to do it yourself. Just run the tool once and its all set up and you can forget about it.

I used the vuejs equivalent and it set up everything in a usable way and I have been happily developing without having to change any of those configs set up for me.

CRA serves three primary purposes.

First, it allows React learners to set up an environment without having to learn Webpack and Babel first. Prior to that, most tutorials would waste multiple pages on "Before you can do anything else, here's how to set up a Webpack+Babel config..."

Second, it allows experienced React devs to spin up a project without having to do all the configuration work (or copy and paste it from somewhere). It also provides good defaults for build output, lints for common mistakes, and makes it really easy to get future build improvements just by updating a single `react-scripts` dependency.

Third, it also acts as a common starting point for instructions and tutorials. For example, I wrote a blog post a while back on using the Cesium.js 3D globe library with Webpack and React ( http://blog.isquaredsoftware.com/2017/03/declarative-earth-p... ), and I was able to start by just saying "Create a CRA project, eject, and modify these two config values".

I agree that create-react-app is bloated and overkill, but that's also a lot of the value in it, or at least it has been for me.

When I used CRA for a project about a year ago, it spit out a gigantic README with everything anyone ever might want to know about JS development, it had a long webpack configuration that hot-loaded CSS and auto-reloaded the page on JS edits, it set up the app to use a service worker, and it used a ton of other technologies and libraries and tools that I didn't know existed. They've scaled it back quite a bit since then, but I think getting a feel for what's out there is really valuable, and even though it has way more than you need, it's nice to be able to easily try those things to learn what they are and confirm that you don't need them. Otherwise, you might end up with a community of people who don't know about ESLint because none of the tutorials thought it was critical to set up before getting started.

One mindset (not necessarily for beginners) is that when working on a serious project that will need non-trivial config, it's best to run create-react-app, eject, carve away all of the unnecessary stuff that you don't want, then take ownership over every aspect of the build system and tooling. That leaves you with a much more solid starting point than if you start totally from scratch and only add things as you need them.

CRA is a set of best practices for setting up a React app.

Even if you do stuff by hand you can run CRA and see how the experts do it.

I think a great option is a collection of example configurations for a stack. When learning Webpack, 90% of my learning was by looking at other examples. The hardest part was making sure I wasn't looking at out of date examples.

The unfortunate thing about CRA is that it's another tool on top of a tool to learn. It's not just instant and obvious, it has its own layer of configuration and understanding of how not to break it, how to upgrade it, etc. So people spend time learning the tool's tool instead of the tool.

I'm also not convinced this is "how the experts do it."

Hi there,

Create React App is by default zero configuration and we do our best not to make it possible to break it. For example you cannot access the configurations of Webpack for this reason. We do allow some configuration through environment variables[0] but try to minimize amount of those too (and some of them will probably get removed in future version too). The public API is around 4 commands (start, build, test, eject).

This makes it possible to make big changes underneath the package in even minor versions (eg. updating major version of Webpack) without breaking existing CRA-powered apps. You can see migration guides for every single version in the Changelog, usually consisting running a single command[1]. This was also true for the major update from 1.x to 2.x [2]




That said, it does take some effort to understand the benefits and limitations of CRA. How could we improve on that one?

Disclosure: Doing maintenance work on CRA

I think it's handy for people who have never used a framework before to have all the tooling set up and available immediately. If I've never really worked on a JS project before, it's perverse to wade through docs of a bunch of orthogonal tools just so I can play about with the tool I set out to learn.

Even if you have worked with that framework before, odds are six months have passed since then and the framework has changed 50% of its best practices. Using a tool like this also avoids stale documentation/tutorials.

I frequently spin up empty repositories for bug reports/playgrounds/one-off ideas. It's an extremely valuable tool when you just want to get down to working on the code.

I just don’t see how this matters. Looking at it this way is just not interesting. This is the whole point of dependency management: making dependencies so easy that this sort of thing happens. One must ask: what’s the dependency graph for the complete build, after tree shaking etc. it’s definitely not thousands of modules. And if so—so what?? That’s the whole point!!

The real issue is security, but that’s another issue. It’s remarkable you can just push code to npm without signing it. Every time I push a commit to GitHub and then release it on npm it really gives me the creeps. Fortunately we have CSPs.

You acknowledge security as "the real issue" in your comment. I don't know how to square that with the first sentence in your comment, "I just don't see how this matters." It matters because of security, like you said.

Install a CSP and you’re done? (assuming we’re talking about front end code)

That's not the kind of security problem we're talking about here. https://blog.npmjs.org/post/180565383195/details-about-the-e...

Huh? This is an issue affecting backend JS. We are discussing front end applications.

Even if this code is only run on the developer's machine, you're trusting 1,600 entities to not pwn it one day.

It's worth some concern.

As the copay attack shows, that everyone uses these libraries doesn't let us rest assured. There are virtually zero eyeballs on the code of transitive dependencies because you would have to extract tarballs to read code. And attacks can be extremely targeted. The copay attack was only discovered because of a deprecation warning in the attacker's code that someone reported.

That is true. Thank you. But is that the totality of the danger, then?

There's nothing special about "backend". It's normal for the client side bundle to contain many dependencies that came from NPM.

Right but if they can’t phone anywhere when the client executes them, they’re not dangerous to the client. As another commenter points out though, there is the danger of executing on the dev’s computer: I guess that is true.

Very interesting. Thanks for posting!

His section about circumventing CSPs was particularly interesting and relevant. CSPs were an impediment to him, and he avoided operating his scam on sites where a CSP was installed.

He was also able to go around CSP. I am not a frontend developer, but I really don't like how frontend developers seem to treat security and dependencies.

It really isn't normal to have 1000+ dependencies and it really isn't safe. Just saying "CSP will protect us" isn't good enough.

Yeah I agree except I don’t understand what the point of the tweet was. Whether you have 1000 deps or 10 deps, the problem is about security, not dep count. Who’s going to carefully audit 10 deps when they’re transitive? More than would audit 1000, but not many more. Having few deps does not appear to be the solution to dependency security.

> Who’s going to carefully audit 10 deps when they’re transitive?

I do. That is why I don't have many deps in general. Transitive or not. With only a handful of dependencies that are from trusted sources and that are audited by me I can be sure that they are safe.

With 1000+ dependencies that are from as many random sources you can not do the same.

Having 10 dependencies is drastically different from a security aspect then 1000+.

... I continue to use smartclient.com for my front end work.

It continues to kick everything from a productivity perspective and the framework is fantastic (for business-y apps).

People used to tell me it was too heavy weight. People used to tell me jQuery or Angular were better.

No external dependencies. NPM not needed. Might be a bit old in some places but so what.

It may be great for you. But it will not go well when someone else needs to support it.

It might be old? GWT? Just go back to developing Web 1.0 applications and see how that goes. GWT is antiquated. I realize the churn associated with front end can be maddening, and you don't always need a Single Page App, but from a usability perspective you are really behind the times.

My first actual web app I ever built was with GWT + SmartGWT, back in 2011-12. The decision made sense at the time, because I didn't have any JS experience, and the JS ecosystem wasn't nearly as mature at the time.

Over time, though, the actual time to make any kind of change to the app became incredibly painful. The loss of the GWT DevMode plugin back around Firefox 27 hurt too.

We just finished rewriting that app with a modern React+Redux implementation, and I took great glee in deleting the entire GWT portion of that codebase. The changes have already paid off by letting us add some additional functionality that would have been a distinct pain to implement in the old codebase.

Sure, the fact that it was the second time through was a factor, but the iteration speed and codebase structure are truly both vastly improved over the original.

Another team has a SmartGWT app that they're planning to migrate in some fashion as well. Unfortunately, they locked themselves in badly by using SmartGWT's server-side black box that hooks into a DB to send data to the client. It's going to take them a while to start teasing that apart.

It amazes me how many people suggest that $2015_technology is behind the times, on a site that - aside from a javascript voting button - would happily exist in 1995.

The one consistent metric I find across everything is "how easily will it be to throw this away?"

It's always the not easy to throw away things that hurt the most.

The ‘black box’ isn’t really that. There’s an open source Node version of it published on the companies github and on their forums

I never said I used GWT.

I don't really understand how headlines like this are helpful. Is there an ideal number of dependencies? How do we decide that 1568 is too high? Is it better or worse than 156 dependencies that each have 10x the LOC? How should the CRA devs address the bad big number? Rewrite all their dependencies from scratch and bundle them with CRA?

Instead of guilting developers for their dependency count, maybe we should be auditing open source project dependencies or suggesting better tips for vetting dependencies.

> Is there an ideal number of dependencies

Maybe we could at least argue about the number of digits?

The solution would be a node standard library project that contains the slowly moving parts of the 1500 dependencies, which means that it doesn't need too much maintainence.

I don't understand why the companies that depend on webpack haven't built a project like this yet (and made sure that the important projects use that library), but I believe it's just a matter of time.

That’s a great way to have even more competing libraries.


Where are those 15 efforts? I don't see any effort to take a hard look at combining the most used few hundred libraries into a collection of a few libraries.

It's hard and boring work also.

Underscore and Lodash are obvious examples. I don't know if the project maintainers' stated purpose is specifically that, but they are clearly creating big libraries of common utilities. And, surprise surprise, two extremely common problems with frontend NPM projects are: 1) unintentionally importing the entire library instead of the few functions you use, and 2) having many different versions of the libraries in your output bundle because of other dependencies.

Hence things like this exist:



You can’t say “it is good design to have small composable building blocks” and then complain about the number of those blocks.

I don't think this will be a sustainable ecosystem. The software is even built on fast consumption now.

Javascript dependencies grow on you, quickly...

Cool beans!



ESLint isn't a transpiler, it's a linter

It checks code formatting, it doesn't enforce a transpiler

So, only needs a 0.06% chance of a package having compromised code (e.g. bitcoin stealer, ssh/pgp keys stealer, keylogger, mitm, etc etc.)

Apparently, the trade thinks its 1970s-style orgy-bathhouse is fine just like it is--thank you very much.

When you look at what a mess the web is as a platform, 1,568 dependencies is a modest amount of asphalt to fill as many potholes as it does.

In JavaScript land, you need an external dependency for freaking left-pad[0]. In freer countries, that cutting-edge 1970s technology[1] is built-in.

[0] https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/

[1] https://stackoverflow.com/questions/293438/left-pad-printf-w...

I agree.

There's an effort to get at least a standard library namespace, but it's at month 8 of just deciding on the semantics of how to import: https://github.com/tc39/proposal-javascript-standard-library

Oh, God. Finally, they have at least started talking about stdlib. It's bizarre how a modern language could exist without a standard lib.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact