Hacker News new | past | comments | ask | show | jobs | submit login
[dupe] React/JavaScript fatigue (medium.com/ericclemmons)
174 points by pbhowmic on Dec 28, 2015 | hide | past | favorite | 183 comments

What we need is Shadow DOM support: http://caniuse.com/#feat=shadowdom

I recently adopted the "you shouldn't have to think about your toolset" and "use boring technology" mindsets. I learned React but I stopped following all other wonderful work being done by the community. It was just too much. And as a result I became happier and more productive.

My passion is my pet project which uses JS, not the JS ecosystem itself. I'll wait a year for build tools to become easier and React architectures to stabilize. Until then, my code won't be the holy grail of immutable flux, but my users will never know that. My re-builds take a couple seconds and I don't have hot code reloading. And I'm ok with that.

I work with (what I consider to be) the bare minimum: React, Babel, Browserify, and fswatch. It's all wired together in my Makefile. It works pretty well. When something clearly needs improvement then I'll address it. Maybe I'll switch to Webpack and integrate hot code reloading to improve build times when I have some free time. But only as a luxury. I can get by without it.

The above sounds easier for build tools than for JS architecture. After all, switching from Browserify to Webpack is a lot easier than refactoring your code from your existing setup to something like Relay, Om, etc... What I say to that is this: Gradually integrating flux (vanilla or Redux) into an existing React app is actually very simple. Extract local state, throw it into a store, and add a subscription. I wouldn't expect any refactoring headaches at all if your component hierarchy makes sense. Everything else (for example anything related to GraphQL, ClojureScript, you see where I'm going) counts as "not boring technology" and significantly increases the risk of being pulled back into the unproductive search of JavaScript enlightenment.

I certainly don't want to discourage library authors in any way. If that's what you're passionate about then don't let my jaded thoughts stop you from building something great. We are in a period of great discovery, innovation, and change. I just wanted to share my thoughts about making a conscious effort to minimize my toolset and accepting the tradeoffs of not having the latest tech.

When I started using React on a commercial project a year ago, I was totally uninterested in upfront adoption of technology other than the minimum required. So I eschewed all the Flux stuff and just used a single nested record of app state updated with the simple built-in immutability helper. We put everything in just two or three files so we didn't need any complex build tooling. We did routing by just listening to hash change events. We got up and running very quickly and fleshed out the app in a couple of months with no major problems. Later we've started using some stuff, but we did it gradually according to real needs.

So when I see people starting their projects by configuring dozens of tools and technologies that they don't really need up front, I wonder why they don't just start simple.

React is still pretty new and doesn't really proscribe anything beyond the view layer. So when people jump into it they go online to try to get an idea of how they should structure their apps they find a lot of buzz around things like Redux and React-Router. Those are both good tools but the combined learning curve for those + ES6 + Webpack + Babel can be pretty steep.

But, like you say, for a lot of apps you can start with a much simpler stack. I did the same thing when I was getting started. My "stores" were just simple JS objects with some subscribe methods. This worked well enough that I was able to focus on building my app and to see first hand how great the React model is for building UIs.

Exactly. My experience with JS (which is entering non-trivial amounts) has been this:

Either get a boilerplate, generator or spend frustrating afternoons configuring to the start line. Then once you start work spend hours reading docs to figure out what all that stuff you installed actually does.


Build from scratch, build the simple stuff, then when your brain says 'hey someone must of done this', look for a library and plug it in. Then at least you understand a general idea of what you're installing.

An over simplification, of course, but building rudimentary routers, event managers, mvc structures etc helped me immensely.

Yeah. I guess I'd recommend a patient approach of first making sure to learn what the library itself does, and then being cautious about importing too much stuff up front. Because that does lead to fatigue and confusion.


The problem is when people ask themselves "What do I need?" and then go "I don't know ... hmmm ... I better get everything then ..."


A lot of dev, like me in the college, have the tendency to get everything right before starting writing first line of code when learning something new, in hope that orthodox practice will help avoiding pitfalls on the way.

But what I really learned along those years, is that pitfalls are inevitable, and expose yourself to them at the early phase of learning is helpful so that you could later appreciate other people's solution and the reasoning behind. Trying to get everything right from beginning hinder you from getting such first-hand and organic insight, and wondering with tools too much will stray yourself from focusing on the essentials.

"Two or three files" can also be a terrible idea if a project mushrooms. Nobody wants to wade around 2000 loc files just because its missing tooling, but I can def see your argument.

Maybe not. I don't mind, I have incremental search. For me, wading around 200 files in subdirectories is more tedious. But it seems to be a matter of preference.

We have 1 file per react component, and keep our files down to < 200 loc (and we're still using es5). As long as you define your components before mounting any of them, you don't have to worry too much about dependency order.

>I recently adopted the "you shouldn't have to think about your toolset" and "use boring technology" mindsets. I learned React but I stopped following all other wonderful work being done by the community. It was just too much. And as a result I became happier and more productive.

Thank you!

I had to pick up Node.JS and npm for a project recently. Apart from it not working properly in an enterprise environment (NTLM proxy and interception certificates) there are so many things to remember on top of my normal Visual Studio knowledge.

I know Microsoft is moving in this direction with DNX and I think it's a good thing, but also could lead to a lot of unnecessary complexities. No one's going to miss XML-based project files though (sln and vcproj are being replaced by json files)

Webpack doesn't have a monopoly on hot reloading, you can do this in browserify too: `npm install browserify-hmr`

With watchify:

  watchify -p browserify-hmr -o bundle.js
With budo:

  budo main.js -p browserify-hmr
If you're using react, you'll only need a tiny wrapper around the root element to opt in to hot reloading: https://github.com/substack/react-starter-hmr/blob/master/ma...

All of this should fit comfortably in a Makefile (or npm run script) and each piece you add is small and comprehensible.

Agree with that attitude, you'll never have enough neurons to follow all the things released. The key is to pick only the minimum you need and forget about the rest. Anyway, as Knuth says, premature optimization is the root of all evils.

Honestly, at this point, since the JS community seems to have fallen back on just lifting all of the good ideas from the Clojurescript community, why not just go straight to the source and start learning some Clojure?

- You don't need to bring your own persistent data structure lib (ImmutableJS/mori/etc,)

- Don't need to bring a functional utility lib (lodash/ramda/etc)

- The build ecosystem revolves around a really solid piece of software in Leiningen (that has a ridiculously high level of adoption)

- Hot reloading (mainly through Figwheel) is simply magical (it's stable and "just works".) The amount of work to get a hot reloading environment setup and maintained with Webpack and various loaders is way too much, and often involves actual changes to application code to support it, which is unacceptable.

- The language itself is designed from the ground up to be functional

This is just what I can think of off the top of my head after a few glasses of wine, but there's a ton of reasons why we as JS developers should start taking a hard look at Clojurescript again.

I was hired to write JS code on a team of people who know JS, by a company that is comfortable writing significant chunks of code in JS. If I try and check in some Clojure into our repo, I'll fail code review. If I suggest adopting Clojure on a new project, it'll be shot down. And for good reason; nobody here knows Clojure, we're not a Clojure shop, we don't even know the right questions to be asking about risks and issues of adopting Clojure, much less the answers.

If we were going to adopt a new language, I think I could make a solid case for Typescript that might get accepted. I could see making a case for Elm or Purescript, but I don't think either will fly. But Clojure is a lot further out there in terms of adding it to an existing team of PHP/JS/HTML/CSS devs.

In addition, while you note that the JS ecosystem is basically just playing catchup with Clojure, it is (slowly!) catching up. More to the point, ES6 is the future of browsers; we're using Babel and polyfills as a stopgap, but the code we're writing is code which is increasingly capable of running on the browsers on our dev machines. Clojurescript is, let's be honest, never going to be natively supported in Google Chrome. JS, as a language, is getting better, JS build tools are getting better, and the JS ecosystem is getting better. It may have a long way to go, and it may be slow, but it's getting there. From where I stand, the gap between JS and Clojure is just going to get narrower (it's always easier to copy than innovate after all). Why shouldn't I just wait and get the benefits for free?

(Disclaimer: I love the idea of Clojure, and I actively looked for Clojure/Clojurescript jobs the last time I was on the market. But what I found was a job writing ES6/React/Redux, which is almost as good as the hypothetical Clojure job, and has the advantage of existing.)

>Clojurescript is, let's be honest, never going to be natively supported in Google Chrome.

Not quite sure what you mean by this, but source maps, syntax highlighting and other native extensions were added by the Chromium team over the last year specifically for Clojurescript support.

But, as far as a language running natively in Chrome, none of the languages that transpile to JS do, not Elm, Purescript, etc, so I'm not sure what exactly you are referring to.

He is referring to the fact that his language of choice, es6, will be running natively in chrome, since it's just new javascript.

However, since ClojureScript transpiles to Js I don't really have to care about this do I. From my perspective Js is effectively bytecode.


I tried that for 6 months then went back to JS only to discover that within those 6 months Facebook and half of the React community had moved on to ES6, and even ES7, which meant that I just missed half a year of the most important phase in the evolution of JS. Great job, says me. I'm having to make up for it now.

What nudged me out of my love affair with CLJS is when I needed to implement a really simple async pattern in CLJS. Everyone pointed me to core.async (later on someone mentioned the cats library which uses monads etc) It didn't feel right to use core.async's syntactically and conceptually complicated CSP pattern to solve a truly simple problem that can be solved far more elegantly with a much simpler and more general pattern using ES7's async/await.

And now that we have decorators, typed data structures, iteration protocols and a myriad of other tools available to us in ES6/ES7 the only thing that is missing is NATIVE immutable types.


This is a really strange line of argument. While core.async is popular, nothing precludes you from using other libraries such as promesa https://funcool.github.io/promesa/latest/ that have semantics you seem to prefer.

Second, ClojureScript has great interop with Js, so there's absolutely nothing stopping you from using a Js library/feature if you so choose.

>And now that we have decorators, typed data structures, iteration protocols and a myriad of other tools available to us in ES6/ES7 the only thing that is missing is NATIVE immutable types.

It boggles my mind that somebody could see this as a positive. The biggest problem with ES6 is that JavaScript just keeps growing as a language. It has lots of features and quirks already, and more are getting added. This is what you end up dealing with when using ES6 + React (https://i.imgur.com/AjSTP20.png).

I think the problem with this is that it adds mental overhead when you're reading and writing code. Something that looks like it might be doing one thing does something subtly different. This leads to hard to debug errors and wastes you time. It also distracts you from the actual problem you're solving.

promise-a by itsef does not solve callback hell it simply turns it into a never-ending-chain-of-thens but async/await (built on top of promise) does make things easily comprehensible. How do i use async/await in CLJS? More importantly why shouldn't i use something like ESLisp if I am into lisp but want to work with JS features directly? Why would I want to mix JS with CLJS amd require everyone who maintains my code to know both? I'd recommend checking oit ESLisp on github, although they're still working on adding ES6/7 support.

To each their own Dimitri :) i gave up on CLJS after it was evident to me that JS is maturing and has copied a lot of the stuff I like from CLJS plus some stuff from C# like async/await. Haskell is cool and so is Elm but all of these will ultimately be copied in pieces by the most dominant language on the web (JS) so it's easier to be on the receiving end of all that goodness as opposed to being stuck in any of those niche languages. Appologies. It's just my opinion.

How is "never-ending-chain-of-thens" fundamentally different from async/await? It's still the very same code but with different (and somewhat disconcerting) sugar. I've been using promises long before ES7, and it's actually harder for me to read async/await functions and reason about them because they look so much like ordinary functions but aren't. There are useful features in ES6/ES7, to be sure: fat arrows, destructuring, imports/exports. Classes and spreads are useful too if you do a lot of React and JSX. But async/await, decorators and generators are just fancy and questionable ways to perform routine functional stuff one can easily do in shaggy pre-ES5 Javascript. I write a lot of ES6/ES7/JSX at work and CLJS at home and 100% prefer the latter. I want immutable values with destructuring, lazy sequences, suit of threading macros, decent cond|p/case, protocols and whole CLJS ecosystem. I've adapted to ES6/ES7/Redux/RxJS and often even could write code near-identical to CLJS/Reagent/Re-frame/Reagi stack. But it is definitely more painful and limiting experience.

Async/await doesnt lead to a long chain of thens with a trailing catch. It gives you proper synchronous semantics like any other synchronous code, while allowing you to specify concurrent logic. Its syntax is very understanable. You're missing out! I think you don't actually have a clear idea if you think async/await is a step backwards. You're arguing for the sake of arguin, right? Else, give me some examples in code. Thanks.

Oh, yeah, it replaces that cumbersome

.then(() => doSome(thing)) with bare doSome(thing)


.catch(err => doOtherThing(err)) with catch (err) {doOtherThing(err)}

A breakthrough indeed!

I just don't see how's that fundamentally different and why one should have synchronous-like semantics for async operations.

Moreover I do a lot of RxJS and like stuff and it's perfectly normal for me to have async computations steps wrapped in functions. Luckily no one tried to "improve" JS syntax specifically for RxJS.

So I totally get async/await syntax and semantics but it forces me to switch mental context for no good reason and thus is useless and disconcerting.

And it's ridiculous to see this minor "feature" as a reason to switch from CLJS to ES6/ES7

You seem oblivious to the advantage of organizing your async code in the same manner you organize your sync code. But the bigger reason I gave up on CLJS (besides core.async and its CSP model being a ridiculous over kill for simple async management yet being the primary choice the language gives you out of the box) was that ES6/7 are advancing at a much rapid pace than all of those Compile-to-JS languages and no one I know in the JS world would want to program a web app in a Lisp-like language (it's like using an RPN calculator rather than a normal one to do your taxes) for advantages that are disappearing fast relative to JS.

The Extensible Web Manifesto embraces the Babel inspired iterate-before-you-approve spec development model and that just makes JS evolution go so much faster.

So there is no hope for any niche language to unseat JS, and staying with a healthy and growing mainstream standard is far more appealing to me than writing web apps in Lisp-like language that once was a great choice (compared to ES5) but is no longer in that position.

I hope ClojureScript continues to be a niche strong language but I'm really hapoy with the progress being made with JS as a language and ecosystem. Fatigue (what the article is about) is self inflicted IMO.


Nothing is hard to do in CLJS but finding the right way to do things can be hard. For example, why doesn't core.async include promises and even better some async/await equivalent? Why does core.async push CSP as the built in async model to the exclusion of all other async patterns? Why are those only found in some 3rd party libraries?

>Nothing is hard to do in CLJS but finding the right way to do things can be hard.

So you're saying that you have to learn the language and its ecosystem. Please explain how that's different from any other language.

>For example, why doesn't core.async include promises and even better some async/await equivalent?

Because it has different design goals.

>Why are those only found in some 3rd party libraries?

Because most people find the core.async approach to work well. However, since such libraries exist and have great documentation, I fail to see the problem.

In fact, not baking things into the language itself is one of the greatest benefits of Clojure. The language itself is minimal and makes very few assumptions. This means that it can be extended through libraries to many kinds of domains. The more assumptions the core language makes the more rigid it becomes.

The thing is many people try ClojureScript and end up leaving while many others do stay. I am in the former group and my reasons are exactly what i stated but you are right to point out that my reasons may not be everyone's reasons, which I never assumed. Hence the Rant tag. Fair enough, some people find use of CSP for simple scenario of concurrent wait-for-all async management a natural fit but i find it an overkill. Promises are fine but I find async/await syntax much more easy to understand.

I do hope CLJS stays a strong niche language but any hope of it taking over the world is unlikely, IMO.

I'm not saying that ClojureScript is for everybody. Obviously, different people like different things and that's why we have so many different languages available.

However, the reason that async/await is difficult to do in ClojureScript as the main reason for leaving it is a strange one. It's clearly still very easy to do, even if ES7 version might be slightly cleaner at the cost of being baked into the core language semantics.

When you compare all the things that are much uglier in JavaScript compared to ClojureScript, it's a bit of a silly argument to cherry pick async semantics in my opinion.

I wouldn't expect ClojureScript to take over the world either. It's obviously never going to displace JavaScript, but it's reasonable to expect that it will continue to grow in popularity and that anybody who wants to work with it will be able to do so professionally.

I didn't leave because of core.async being exclusively CSP. That was a big annoyance (and couldnt find the promise library) I left because ES7 and next year ES8 and year after ES9 are bound to give us what we need from a modern language without resorting to coding in a Lisp-like labguage, ClojureScript is extremely expressive but something about the Lisp form makes me spend too much time thinking about the code rather than the problem domain (product features) It does produce tight code so it is a better medium for expressing algorithms but I found that it moves my focus from thinking about features to thinking about algorithms (a strange attractor?) and in the end very few people (Lisp users mostly) will be able to maintain the code... So what am I doing writing a web app in a Lisp like language unless i really enjoy thinking about algorithms more than UX... What matters to me is having a good modern language with large enough eco system and that I could use to build kick ass UX. Modern JS and React-Flux-Immutable suffice. When i want to do heavy data processing I would probably miss ClojureScript and Clojure but the UI is not where I would want to do heavy data processing... I really thought about it based on all these factors and decided to jump back to JS. That was my choice. I don't expect it to be everyone else' choice...

>I left because ES7 and next year ES8 and year after ES9 are bound to give us what we need from a modern language without resorting to coding in a Lisp-like labguage

I'm not sure what that's supposed to mean exactly. I don't really understand what the "resorting" part refers to here. Clojure is a modern language with that has excellent syntax with tangible advantages over syntax found in most languages.

The syntax is very uniform and follows the principle of least astonishment well. The s-exps provide additional visual information about relationships in code making it more scannable. Finally, the syntax facilitates structural editing making it much easier to manipulate in the editor.

>ClojureScript is extremely expressive but something about the Lisp form makes me spend too much time thinking about the code rather than the problem domain

Perhaps that might have something to do with the fact that you've only used Lisp for 6 months, while you probably have years of experience working with Algol style syntax you're familiar with.

There's absolutely nothing inherent in Lisp syntax that distracts from the business logic. If anything, my experience is that it puts you closer to the business logic as there's a lot less syntactic noise.

>and in the end very few people (Lisp users mostly) will be able to maintain the code

That's completely false. My team has been using Clojure for the past 5 years and we've never had trouble hiring people to work with it. None of the people we've hired over the years had any experience with Clojure or even FP for the most part. The average learning curve to becoming productive tends to be a couple of weeks. We also hire co-op students every 4 months and all of them have learned the language quickly and enjoyed working with it.

A new hire doesn't have to become an expert to start doing useful things. Learning the basics takes very little time, and they can pick up new concepts as they need to. Personally, I wouldn't hire somebody who was unwilling to work with a new language as it implies the sort of rigidity that antithetical to the developer mindset.

> So what am I doing writing a web app in a Lisp like language unless i really enjoy thinking about algorithms more than UX

That's funny since ClojureScript provided the first environment for developing web apps where you could get instant feedback on the UI making it much easier to focus on UX.

Having a live environment with a REPL makes it much easier to experiment as it cuts down the time between making a change and seeing the effect. This is one of the greatest tools for being able to experiment with the UI and provide the a good UX.

>What matters to me is having a good modern language with large enough eco system and that I could use to build kick ass UX

This is precisely why I, and many others, use ClojureScript. If Js is your idea of a modern language I simply don't know what else to say here to be honest.

Again, if you prefer working with Js that's perfectly fine. However, your rationalization of that decision is flimsy at best, and really boils down to the fact that you'd rather use something you're more familiar with.

You are vested in Clojure/Script and biased toward it. Obviously you are biased due to the heavy investment you hve made. I see so many disadvantages in ClojureScript: Lisp is super small in terms of adoption. Lisp is like using an RPN calculator, for uber nerds not for everyone. Who will maintain my code? The few people I know who know ClojureScript? How hard is it to find a ClojureScript dev or anyone interested in working on it? Can my company hire hundreds of engineers who love it and are easy to replace if they leave. If you say yes then you are contradicting actual experience i have had and dismissing it due to shear bias, not based on objective facts and data-supported evidence. Clojurescript's biggest problem, however, is that it has people like yourself who want to shove Lisp Is The Truth down everyone else' throat which people like myself have no tolerance for :)

>Lisp is super small in terms of adoption

Sure, but that's not very interesting in and of itself. The question is whether there's enough of a community to make the language viable and whether you can get a job using it.

Thousands of people are happily working with ClojureScript today, and lots of companies make accommodations such as remote work.

>Who will maintain my code? The few people I know who know ClojureScript?

I've always found this argument very strange myself. My experience is that the language is usually a small aspect of what's involved in maintaining a project. You have to learn tools, libraries, and the architecture around the project. This tends to vary greatly place to place. Learning the language is just a small aspect of that and anybody who's not capable of learning a new language probably won't do a good job with the rest either.

So to answer the question, the person you work with and train to use the language usually. As I've already pointed out, I've trained lots of people to work with Clojure and it doesn't take long for people to become productive.

>How hard is it to find a ClojureScript dev or anyone interested in working on it?

Not very, lots of people apply specifically because they want to try a new language. Last guy we hired had prior experience working with PHP and C#, and never touched a functional language in his life. His reason for applying was precisely that he wanted to try working with Clojure. He finished his first project and put it in production in his first 6 months on the job with minimal supervision.

>Can my company hire hundreds of engineers who love it and are easy to replace if they leave.

The fact of the matter is that good engineers aren't easy to replace when they leave. This has nothing to do with their choice of language.

> Clojurescript's biggest problem, however, is that it has people like yourself who want to shove Lisp Is The Truth down everyone else' throat which people like myself have no tolerance for :)

I'm not shoving any truth down your throat, at no point did I suggest that you should switch back to ClojureScript from Js. In fact, I've repeatedly stated that you should use Js if you like it.

I'm just pointing out the fallacies that you're stating when you're fumbling to justify the reason you switched back. Something nobody asked you to do by the way.

You started out complaining that core.async is hard to use. When I pointed out that there's a promises library you pivoted to complaining that libraries are hard to find, even though it's the first result for "promises clojurescript" on Google. When I asked you what specifically was hard to do, you said that it's just "an argument plot", and now you've moved on to some vague notions regarding difficulty of hiring developers to work with ClojureScript.

Why don't you just say that the actual reason that you like Js better is that you're more comfortable using it. That's a perfectly fine answer.

Perhaps you could instead provide an example of a concrete problem that you believe to be difficult to tackle with CLJS.

>promise-a by itsef does not solve callback hell it simply turns it into a never-ending-chain-of-thens but async/await (built on top of promise) does make things easily comprehensible. How do i use async/await in CLJS?

There's a long discussion here, which I'm pretty sure you're already aware of, on the tradeoffs:


Each approach has its downsides, but clearly core.async and promises work just fine here.

>More importantly why shouldn't i use something like ESLisp if I am into lisp but want to work with JS features directly? Why would I want to mix JS with CLJS amd require everyone who maintains my code to know both?

Language semantics is why. ClojureScript has much cleaner semantics than Js and languages that provide syntax sugar on top of it. It's immutable by default, has clean and consistent syntax, and far less gotchas than Js.

Nobody actually mixes Js with ClojureScript. People write libraries backed by Js internally, but the users of these libraries don't have to know or care about that.

The real question is why would somebody want to learn the giant clusterfuck that ES6/7 constitutes when far saner alternatives are available.

> i gave up on CLJS after it was evident to me that JS is maturing and has copied a lot of the stuff I like from CLJS plus some stuff from C# like async/await.

Adding features to an already poorly designed language does not make it better. You end up with a giant kitchen sink language that takes inordinate brainpower to work with. We've already seen that this is a bad idea with languages like C++ and Scala. And no, you can't just learn a snae subset of the language, because sooner or later you have to deal with code written by other people.

If working with a giant quirky mess that looks like this https://i.imgur.com/AjSTP20.png is you cup of tea then who am I to stop you, but I certainly question that it's a rational choice. :)

> What nudged me out of my love affair with CLJS is when I needed to implement a really simple async pattern in CLJS.

What? Async/await in CLJS is:

(defn async-fn [] (go true))

(go (<! (async-fn)))

How is that syntactically and conceptually complicated compared to async/await?

Why don't you go further and try/catch that to make it usable in a real app? How do you handle async errors?

Install an exception handler on the channel or return exceptions on the channel. The latter is more common. I've written my own macros to make the latter case pleasant (<10 loc), but I believe the go-catching and <? macros from glossop provide the same functionality.

(defmacro go-catching [& body] `(go (try ~@body (catch js/Error e# e#))))

(defmacro <? [chan] `(let [res# (<! chan)] (if (instance? js/Error res#) (throw res#) res#)))

Used like this:

(go-catching (<? (async-fn)))

Can you expand that to the concurrent scenario?

Show us how you implement this simple and very common concurrent pattern with ClojureScript. I've seen stuff that implement this in ClojureScript and it ain't pretty (to say the least) Impress me! :)

In ES7:

async function fAsync() {

try { var results = await Promise.all([asyncOpA, asyncOpB, asyncOpC]) } catch (e) { ... } }

From reading core.asyncs documentation, it sounds like this should do the trick:

(go (try (let [ops [asyncOpA asyncOpB asyncOpC]] (core.async/take (count ops) (apply core.async/merge ops))) (catch js/Error e ...)))

Where asyncOp* uses go-catching.

I couldn't find example in the docs for that library showing concurrent async ops with simple try/catch type error handling. So it's still not clear to me how you would rewrite the above shown async/await concurrent scenario using this library.

Just use promesa/all then catch :)

Moreover, it has funcool/cats bindings, so you can use promises in mlet and alet macros if you are into monad thing ;)

Oh right, that makes sense but does not make async code organize the way synchronous code does (as async/await sugar enables) but is a fair deal if you don't mind your async code using a different organizing pattern or if you specifically want it to be that way... :)

Re: cats

Not a big fan of abstractions that don't contribute to code simplicity. What is the percentage of programmer who dig monads? Less than 1% probably.

You're just cherry picking though. When it comes to complexity there's plenty more of it in Js than there's ever likely to be in ClojureScript.

I am biased. Just as you are.

Objectively speaking, Js is a far more complex language than ClojureScript.

It's a trivial matter to wrap promise/all in a core.async channel, providing the exact orginzation pattern you're looking for.

Show me the code! Go ahead and let's see how pretty that is, and son't forgeg error handling and concurrency.

I've provided all the code you need to put the pieces together quite trivially. Using go-catching, <? and the promise library (or just the core.async snippet I wrote earlier), you should be able to write the following:

(go-catching (<? (async-all [asyncOpA asyncOpB asyncOpC])))

And yes, that handles errors exactly like synchronous code does. The total number of lines for implementing go-catching, <? and async-all shouldn't take more than 20-30 loc, if not less.

Now, if 20-30 loc is too much for you to write, then by all means use JS.

So what you're saying is that you can't be arsed to spend 15 minutes to learn a library, but you're ok gobbling up all of ES6/7 without problems?

That's an argument plot, not a genuine question. :)

ah so just trolling then :P

I'm basically saying this. At work we've started to move from Ember to React over a year and a half ago, directly because of the work David Nolen has done in the space. And now we have Redux wrapping an Immutable.js map, and are trying to piece together the rest of the stack that is om.next. It would be wayyyyyyy easier and better and less hacky to just write clojurescript. Getting people on board is sadly super difficult

Any write ups why your team moved from Ember to React? Seems like the recent tenets of Ember coincide with Reacts's componentized architecture and one-way data. Also if you were able to convince the team to go from Ember to React, appears as though the opportunity to switch to clojurescript was there (although react is the hotness right now so convincing was probably easier).

Question (from a newbie): Why didn't you stay with Ember, now that it has a similar engine as React yet comes with a CLI tool and strong community conventions that get rid of any build tool frustrations?

I'll assume the main keywords are "one and a half year ago". Me personally, I like the fact that React is a library wheras Ember is a framework. React doesn't dictate how you code your program, while Ember does.

Also you don't really need to use a flux library or Redux if you're using Reagent, it's pretty much all set up for you.

I've been using ClojureScript/Reagent for about a year now and all this JS tooling talk goes way over my head, I haven't needed to use any tooling other than lein cljsbuild for a while now, and it's glorious. If the Clojure community / ClojureScript was more approachable to beginners I think ClojureScript would be taking over right now.

Honestly, I think it's more approachable than Js tooling for somebody who's not familiar with either. You can have a working ClojureScript project up and running in literally 1 step, and only have to install 2 things to do that:

Install OpenJDK: http://www.azul.com/downloads/zulu/

Install Leiningen: http://leiningen.org/

Create a new project and run it:

lein new reagent myapp cd myapp

lein figwheel

Once figwheel starts, you can edit src/cljs/myapp/core.cljs and any changes you make will be reflected live in the browser without having to reload the page. Now consider what you'd need to setup to get the same thing with Js/React.

I think the problem is that a lot of people are already familiar with Js and tooling around it, so integrating more tools piecemeal doesn't feel as hard as diving into a whole new ecosystem.

Lisp is just a non-starter for a lot of people. Maybe it's an irrational bias but it's also widely prevalent.

I think Lisp in all its flavors is in the same bucket with Haskell, i.e. not a language that will ever go mainstream but an important laboratory for exploring ideas that eventually trickle down into more mainstream languages.

Clojurescript is a case in point. Statistically its userbase is zero but it's been the source of several useful techniques.

The relative numbers of users to other languages are not really interesting. The question is whether there are enough people using ClojureScript for it to be viable long term and can you get a job using it.

The answer to both questions is a yes. There are thousands of people working with ClojureScript today and there are lots of companies hiring for Clojure/Script jobs at this very moment.

In fact, the demand appears to outpace supply resulting in benefits such as accommodation for remote work (https://www.reddit.com/r/Clojure/comments/3yhm7k/looking_for...).

Thanks to the irrational bias against Lisp you're also competing against a smaller pool of developers when you look for Clojure jobs. Seems like a win to me.

I've been hearing this argument since I was heavily into Common Lisp in the early 2000s. Personally I like lisps so I hope Clojurescript does establish a viable niche.

But it's not the case that number of users is irrelevant. If I commit to Clojurescript (or Haskell, or any other niche language), I'm cutting my prospective job market down by 95%+. This means fewer companies I can work with, fewer places I can live, and fewer gigs available overall. Some might consider the tradeoff worth it but I don't.

I didn't say that the number of users is irrelevant. There needs to be a minimum user base to make a language viable, however beyond that it's just tradeoffs.

While you might be cutting down the job market, you're also focusing on companies that are forward thinking, get to work with great technology, and get perks such as remote work. The most exciting part for me is that you get to shape the future of the ecosystem. Being on the ground floor of a new technology means that you get a lot of say in how it will evolve. For me the tradeoff was absolutely worth it, but I can understand how it's not for everyone.

Isn't Om Next built on ideas pioneered in Relay and Falcor, not the other way around?

To be fair, there's been quite a bit of cross-pollination, but the original surge in popularity for React came about because of the pioneering work by David Nolen to show how to fully unlock the promise of React's approach when coupled with immutable data structures and a functional mindset (Basically everything presented in the original version of Om.)

I have a suggestion to this, but I don't know how to get it out there. I can't build a library because the point is to not depend on libraries.

My suggestion is that if your going to build an application in the browser, your project needs an architecture that will last beyond today's libraries and tooling. You want to recognize what's unique about your app and express those parts without touching the DOM or network, even if they seem trivial now.

My particular favorite way to do that is using an event bus to create a catalog of custom/domain-specific events, with views emitting operation- or command-like events and internal models emitting new states. This is basically the important part of Flux without the special concepts (stores, dispatcher) that you may be fine without, and is already available in jQuery, Backbone, node's EventEmitter, and many other libraries out there.

React and immutability and the rest of Flux are all very reasonable next steps if somehow you come to need them, but you are likely not spreading your UI development across hundreds of engineers. Unnecessary new stuff is just going to steer your conversations towards libraries and away from your domain.

Redux or anything similar to it seems pretty close to this, assuming you always want to stick to its basic architecture (atomic immutable application state with "reducers" that take a state and an action and return the new resulting state).

Redux is so small that it's hard to see why you would need to switch away from it if you're keeping the same architecture, but even if you wanted to it ought to be fairly easy, since reducers are pure functions and actions are (or should be) simple JSON-able data.

The actual rendering of state to DOM is done completely separately by registering callbacks that listen for application state changes.

Of course, if you're using some other architecture to manage application state, results may vary.

Totally. But if I'm being extreme I would say that keeping your application state "memoized" into a single value may or may not be necessary for your application. If it's not, you've just coupled all of the data models in your application to into the same entity, which makes it easier to turn those couplings into dependencies, which makes them harder to test and use separately later.

How can I write reusable components if my domain logic must be separate from my view logic?

The "separation" between your business logic and your view logic is really better thought of as a decoupling.

Let's say for example that your application is a game of solitaire. Rendering the cards is a view concern. Interpreting UI events as game actions is a view concern. Accepting or rejecting those game actions is business concern. Animating that acceptance or rejection is a view concern. Persisting or restoring your moves or game state to an API is a business concern with some networking glued to the side of it.

That's sort of a trivial example, but the event catalog for your application might look like this:

name: GAME_STATE, payload: A JSON representation of the card stacks

name: PLEASE_MOVE, payload: A representation of an attempted move

name: MOVE_REJECTED, payload: The card that tried to make an illegal move

A move event would result in a new state event or a rejection event. Your rendering components don't need to know how that happens or who controls the state. Your core components don't need to know if this game is being played on a server or a browser. Your move events might come from a swarm of multiple players. An analytics component can listen to the bus and fire off things that it's looking for.

That's fine if my application is a game of solitaire. But what happens when I want to distribute it as a component, <Solitaire />? I can't, because it's not self-contained.

You could package <SolitaireView/> and SolitaireGame together and distribute that? For somebody who just wants to drop a game of solitaire on their page that would work.

I was responding to a question about separating "the unique parts of your app" from other concerns like DOM and the network. I interpreted "the unique parts of your app" to be the way application state is represented and modified, which is a pretty reasonable definition for the common term "business logic."

Library-agnostic reusable components is another question, and certainly a good one. There doesn't seem to be a good answer right now. Web Components appears to be intended to solve that problem, but it isn't looking so good in my opinion.

I would probably go with a similar approach to reducers in Redux: a simple function that takes a state object and returns some library-agnostic representation of DOM. Of course there is no standard representation of DOM that I know of, but you could just output a plain JS object representing the DOM tree. There are probably many libraries out there offering a way to represent DOM that could easily to plugged into (with a simple wrapper) whatever new DOM rendering library is hot.

Many of the newer Javascript libraries seem massively over-engineered compared to what you actually gain over using jQuery, or even just plain Javascript. I don't want to detract from the complexity of what some of these frameworks can achieve but at the same time it's not like they are doing complex 3D or machine learning.

For me it's about readability and maintainability. I can come back to a program weeks, months or years after it is written; I most likely want to just be able to read, understand and edit it quickly. As soon as something has a huge infrastructure, setup, tooling, transpiling or whatever it just becomes burdensome.

Intercooler.js (http://intercoolerjs.org/) demonstrates a good philosophy.

It seems like no one asks "Just because we can use Javascript for everything, should we?"

Pros: AJAX for loading content makes requests smaller making your app more performant.

Cons: The Javascript framework requires a 1xx KB download before content can be rendered, making your app less performant, hurting SEO, and breaking the back button (no, I don't want to scroll again from the top through the 5 posts I already read when I come back to your site).

You hate maintaining an entire application in Javascript so you get to learn all the joy of transpilers and a build system to build whatever not Javascript language you chose and your tens of module dependencies because you decided everything had to be done in Javascript or TypeScript or ES2015 or CoffeeScript or ES7. Oh and when a new language supersedes the language you decided to use, you happily spend weeks moving your codebase to a new language, thinking "Wow static typing in 2015?! My code is so much more maintainable now!"

It says it all that the benchmark for comparing frameworks is TodoMVC, a simple CRUD application for which client side rendering is unnecessary. People are not thinking at all about the pros and cons of client-side rendering and reaching for it for any web applications.

Google doesn't use AngularJS for Gmail. They use GWT to render HTML on the server. Side note: AngularJS 2 beta is 500KB. Fucking laughable. Oh and they suggest loading both the AngularJS 1 and AngularJS 2 frameworks on your page to help you migrate.

Facebook doesn't use ReactJS for Facebook. They use PHP to render HTML on the server. Edit: Yes Facebook uses ReactJS for a lot of side stuff, but not for big items like their newsfeed.

Twitter doesn't use client side rendering. They tried it but reverted, because the time to first see the content was too long.

People are building a mountain of abstractions and investing so much time to over-engineer everything in Javascript. WHY?!

> Facebook doesn't use ReactJS for Facebook. They use PHP to render HTML on the server.

This is false. Facebook is a huge user of React—it's one of their "pros" over Angular (which Google doesn't use as much).

The entire Instragram site is built with React, and all new development is with it[1], as well as parts of their existing UIs[2]. They are gradually replacing everything with it because redoing the whole site at once is impossible to do. They are also putting a ton of work into React Native and use it in some of their products [3].

Facebook seems to put some of their smartest engineers in the React and React Native teams as well as related projects like Immutable.js, and grab talent as quickly as they can (like Dan Abramov). It's silly to think that they're spending so much money on it for nothing.

[1] https://www.quora.com/Who-is-using-Facebook-React

[2] https://groups.google.com/forum/#!topic/reactjs/5K4fXu1aCTs

[3] https://facebook.github.io/react-native/showcase.html

I didn't mean to imply Facebook doesn't use ReactJS at all. The point was they use it on a need by need basis, not all in SPA all the time.

Ah I see. Sorry for misreading. Still better than Angular's situation though, and I'd argue React Native is more important/more likely to be fully used at Facebook.

> The Javascript framework requires a 1xx KB download before content can be rendered, making your app less performant, hurting SEO...

False. React can be rendered on the server and sent in the initial request using ReactDOM.renderToString.

> You hate maintaining an entire application in Javascript...

No I don't. I'd rather write an entire application in JS than write an application (backend and frontend) in two different languages, or write a frontend as a series of ad-hock JS scripts. If I hated maintaining an entire app in JS, why would I maintain it using JS? I use JS for everything because I prefer it to the alternatives.

> a simple CRUD application for which client side rendering is unnecessary.

No one needs to do an SPA. The world got by just fine without it. For me, the reasons to do an SPA with ES2015 modules had to do with simplifying my frontend architecture. JQuery is easier to get wrong compared to the render-everything mindset of React.

> Google doesn't use AngularJS for Gmail.

Good for them. Angular sucks IMHO. That being said, Gmail came long before Angular, and why migrate when you have a working product?

> Facebook doesn't use ReactJS for Facebook.

Facebook doesn't use ReactJS for --everything-- on Facebook. The fact that React can be gradually migrated into an existing application is one of React's greatest strengths.

Facebook do, however, use React for Instagram. They even use webpack for this.

> Twitter doesn't use client side rendering.

Define client side rendering. When I scroll down on the page and new items magically appear, I would say that is client side rendered. The time to first see the content, using React, could be done by first rendering React on the backend. But why migrate when you got a working product?

> People are building a mountain of abstractions and investing so much time to over-engineer everything in Javascript. WHY?!

Is it over-engineering when it solves a problem and does nothing more than it has to? React renders views, that's it. You can render on the frontend, backend or both. React is easier to use than having many different JQuery-based scripts.

In short. React does one thing. It does it well, and it simplifies my UI code. How is this over-engineering? I could say the same for gulp (for me, easier than bash scripts), webpack (easier than makefiles), ( node+express (waaaaay easier than Java or C#), Immutable.js (makes things easier to reason about) and the rest of my pure JS-stack.

"Google doesn't use AngularJS for Gmail" - IMHO This is non-reason for a start. Why will they suddenly start migrating their main product which was built a long time before Angular was developed. Meanwhile most of the new websites at Google are being developed using Angular - google trends, google fiber, DoubleClick etc.

> Facebook doesn't use ReactJS for Facebook. They use PHP to render HTML on the server.

Being able to render your javascript server side with isomorphic (or universal) javascript is one of React's big selling points.

ReactJS is used for the Facebook's people search page (mobile web version). Most Facebook web pages are renderer on server with PHP/HACK.

You say it's about maintainability. Well, that's the whole point of frameworks. Your team grows, your app gets bigger, time to add some more structure to your code. Extract the common patterns into re-usable modules. Enforce conventions. Eventually, in your quest against frameworks, you have created a framework. Except probably worse, and with no documentation.

Take React for example. It's not over-engineered. React is fantastic. I can't imagine how we would have build some of our UI without it. But you're right that there's a bunch of cruft/overhead that comes with it too. Build tools are hard to setup. Front-end architectures are in their infancy. In this sense, it's under-engineered rather than over. I just don't see where the fact that awesome frameworks are hard to use turns into the idea that they are "massively over-engineered".

I agree with your standpoint (first two paragraphs).

> Intercooler.js

Why not '<a data-action="/click">' (HTML5 data-* attributes feature!) instead of the non-standard '<a ic-post-to="/click">' ? http://caniuse.com/#feat=dataset

The problem is that new and better ways to do things come along (ES2015 versus JS, webpack versus grunt/gulp), but the old ways hang around like a bad smell.

How the heck as a beginner are you meant to fight your way through all the noise of the old, bad ways of doing things? How is a beginner meant to know that really they should be using ES2015 and webpack rather than JS and gulp/grunt? How does a beginner even come to understand that in the reactJS world they might be reading something relevant, but then again they might be reading something completely irrelevant and in compatible (i.e. ES2015 verus JS).

Really when a new technology comes along that is a clear "winner", serious consideration should be given to just getting rid of the "old" way.

Unless Grunt and Gulp are going to somehow make a big comeback, the should be loudly killed off.

Damn - whenever I read the React documentation I have to filter out all the irrelevant code that is not ES2015. Why is all that non-ES2015 code there still?

Old tech should be visibly and loudly killed. No wonder its hard for beginners - its all the damn noise made by the "old" ways of doing things.

The react ecosystem is filled with the living dead - technology that has died but just won't go away.

Things should remain backward compatible but only for a very short window, it's really unhelpful to have many many different ways of doing the same thing, it fragments everything including the learning curve. Witness Perl.

Beginners (and I am one) don't need to be shown every possible way to do things - they need be given a rock solid, opinionated path on the current right way to get the job done. I don't care if that opinionated path changes every month, I just want to not have to work it out by fighting through two years of zombie tech to eventually figure it out.

Things should remain backward compatible but only for a very short window, it's really unhelpful to have many many different ways of doing the same thing, it fragments everything including the learning curve. Witness Perl.

Sounds like a terrible way to build commercial software.

The problem isn't that old things don't die away quickly - far from it - the problem is that we have too many new things coming in that keep changing every few days.

I'm building a 10k line coffeescript app that works on top of react. All I care about is getting a toolchain to compile the coffeescript and generate source maps.

I don't care about dicking around with npm and node and grunt other than to make the build process work.

Tell me why I should care about grunt or gulp or webpack?

React introduces a massive win over traditional ways of building UIs that makes learning how to write apps with it worth learning. Why should I care about learning grunt and then learning gulp and then learning webpack, when all I'm using it for is to compile my coffeescript?

If I could get away with a Makefile, I probably would.

> If I could get away with a Makefile, I probably would.

You kinda can. I'm seriously considering that in conjunction with <http://entrproject.org/> for watching file changes.

I wrote the book Automate With Grunt out of anger at the terrible docs for Grunt and my displeasure that there was yet another build system out there. And just as the book was released, Gulp came along. Then Webpack. And now there's tools like Brunch.

I still use Grunt, because I spent time learning it. And I'll be damned if I'm going to waste time learning a new tool without a really good reason other than "Coke vs Pepsi".

(edited for organization because I'm tired.)

Nitpick - Grunt is a task runner, Gulp and Brunch are build tools, Webpack is just a module bundler, it's not a full build tool - it's more a replacement for r.js than for Gulp (and it's remarkably faster than r.js).

After trying out Grunt and Gulp, I found Gulp to be more to my liking because the tasks are written as actual JS code, not as a pile of configuration. Plus, it runs the tasks in parallel if they don't depend on each other, whereas Grunt defaults to running them sequentially.

Sure but they all end up being used as a build tool. Webpack may be a module bundler, but it has hot reloading, live reloading, and plugins to transpile. Watch any React tutorial and the first thing they have you do is set up a Webpack config that gives you a live-reloading build system with ES2015. And it's a different one than the one I used 5 months ago.

It's nice that there are people willing to address problems, but it would be nice for web development to grow out of its "oooh shiny" phase.

> Watch any React tutorial and the first thing they have you do is set up a Webpack config that gives you a live-reloading build system with ES2015.

To be honest, I prefer learning by reading specs/documentation, tinkering and Google-ing specific bits, not by watching tutorials, so I did not know this. That's not ideal conceptually, but it does mean one less tool in the pipeline, which is not a bad thing for beginners.

> it would be nice for web development to grow out of its "oooh shiny" phase.

Absolutely. Just as long as it doesn't swing to the other extreme, like PHP does, where 12-year-old and deprecated techniques are still entrenched at the top of Google... :)

Damn - whenever I read the React documentation I have to filter out all the irrelevant code that is not ES2015. Why is all that non-ES2015 code there still?

Because browsers don't fully support ES2015 yet? not everyone wants to use/learn new buggy transpilers, new build tools, add more boilerplate, etc..

> I don't care if that opinionated path changes every month

Good for you, you'll feel right at home because that's exactly what's happening in JS-land, and it's a major reason many of us opt to stay the hell away from such a fad-driven development ecosystem.

Sell me on Webpack, and, in particular, on why I should care about this particular bit of plumbing.

My (simplistic) understanding is that webpack is more simple than grunt and gulp to configure. Backed up by my observation that most of the most current projects seem to be embracing it - that's enough for me, it's the current winner so it's what I use. I don't have time and I'm not interested in doing a detailed technical analysis - my approach is just to try to understand what technologies are the latest - and on the assumption that they are the latest because they are better, and on the assumption that previous technologies that did the same thing will be superseded - I use them.

You can criticise this approach as just following the trends but I take this approach because it would be stupid to try to understand every single component of the ecosystem and then make my own careful choices - what is everyone else using right now? Probably good enough unless I know some good reason not to use it.

I am a beginner and struggle hard to understand the vast array of tech I need to do reactJS development. It hurts me very badly sometimes and I feel stupid because I don't grasp it all, but I have to get shit built so for the most part I'm just doing what others are doing and as I go I am learning more and more and in areas that I have gained real understanding I then make my own educated decisions about exactly how to do it in the right way.

> webpack is more simple than grunt and gulp to configure

That's the first time I've heard that one. In my opinion, what makes Webpack great is its raw power and module-based (rather than file-based) focus. Browserify is easy to work with and get started with but less powerful. (Granted, it's quickly catching up.) Webpack is a lot of things, but easy to configure is not one of them.

By the way, Webpack doesn't really replace Grunt or Gulp. It replaces Browserify. That said, if you use Webpack, you can easily get by with npm scripts instead of Grunt/Gulp.

This response sums up something important about the Javascript development community that I cannot put into words.

I think it sums up the Beginner Community in general, not the JS community. You see this with beginners in everything.

You take the struggles of a beginner as an indictment on the broader professional JS development community?

It has nothing to do with them being a "beginner".

My reaction to your comment is likewise ineffable and mysterious.

The JavaScript "community" feels like more a large country.

I believe (and hope) this is not representative of the JS community.

Given that front ends have a huge visual component, it kind of makes sense that developers would approach them like clothing fashion: you don't have to watch the designers to look reasonably good, or even pay attention to construction, you just have to watch everyone else.

Well, at least that's what I picked up from this rather honest opinion.

Don't take this the wrong way - I mean this with the most respect possible.

You shouldn't be recommending software to anyone.

I'm sorry you feel that way.

I know a huge amount about software development and work with a wide range of technologies.

Learning some completely new field like browser based development is best done by just jumping in and trying to make stuff work. You learn along the way and much of it will be unfamiliar. Over time things will become more and more familiar until you start to develop expertise across the entire field.

If you are suggesting that instead I should learn by sitting down for six months in an ivory tower and learn all the theory and function of every part of the software ecosystem that I plan to work with so that I can then take every step of my journey as an expert, then you are misguided.

All software developers live in a fog of ignorance which they work to push back. No one knows everything. The best way to push back the fog of igorance is to start working with the technology to get real stuff done. To do so, it is necessary to make pragmatic decisions such as "well it looks like everyone in this field is using technology X - so that's what I'll use until I know enough to decide otherwise".

Are you someone with a deep knowledge of JS and react development? If yes, did you step in to it as an expert in all things? Did you use things without knowing why? Of course you did. Everyone has to.

I completely agree with your characterization of how beginners can feel. That said,

> If you are suggesting that instead I should learn by sitting down for six months in an ivory tower and learn all the theory and function of every part of the software ecosystem

It's not simply a choice between "learn for 6 months" and "use whatever the latest thing is". You seem to be advocating for the later, which I think is just as unworkable a solution as the former. For instance, a nice medium ground would be to read the github README as well as the front-page website of the candidates.

Also, as someone else here pointed out, you can't kill off gulp/grunt even if webpack exists, because webpack is not a task runner, and some people use the task-runner features of gulp to do more than combine modules, etc.

You admitted to being a beginner - a beginner shouldn't be recommending technology choices beyond that a particular choice might help people get started. There is too much a beginner does not know was his/her point.

> You admitted to being a beginner

He said he was a front end JS beginner. He also mentioned being a seasoned software engineer overall.

His advice is completely sound, and a very valid approach: Want to learn a new platform/ecosystem? Take whatever is the most popular and make stuff work. It's the fastest way to learn by far and with an free bonus you get actual valuable software.

Nobody flames people who learn Rails while learning Ruby! What's the matter with you guys?

The only mistake the GP made was "admit" on HN that he's a beginner at something.

From my limited POV, this is how I see most of the newcomers to JS community currently behaves. And it's a good example of 'learning by doing', which is the advice that everyone gives around here.

- Do some research, look what successful/smart/sane people are using/working on, and why.

- Jump in, hack stuff, make things work.

- Learn while creating. Discover the insights behind the choices that people you're following made.

- Start making your own informed choices.

As long as you're not stuck in the step 2, and advance beyond doing what everyone is doing, you're probably on the right track.

That's how I learned to build maintainable/scalable/successful applications.

It worked out perfectly for me.

Edit: typo, clarified first sentence.

I am not sure why the parent compares webpack to gulp/grunt. The latter are generalized task runners (think "make"), but the former is a tool for bundling together many small JS files into one.

Webpack (and browserify, a competitor that's very similar) bring you a module system so that dependencies are explicit with a require() call and you don't have a global namespace with hundreds of objects. JS doesn't have any such system built in. Packaging it into one file in the end, which they do, is necessary for performance so you don't make hundreds of network requests.

I think it's due to Webpack replacing/eliminating much of what we used to do "manually" in Grunt/Gulp such as transpiling, building, combining, etc.

In most of my projects, I no longer needed Grunt for anything aside from deploying to production, etc.

Bundling JS files into one big file is obviated by http2.

You still have the round-trip time for each level of dependencies if they're resolved on the client, at the very least. And a real-world performance comparison where the recursive dependencies are listed up front but sent in separate requests shows unbundling losing:


In order to be sold on webpack you need to understand the stack of problems it solves. I tried to do this during a talk last year; the relevant part is https://youtu.be/VkTCL6Nqm6Y?t=9m39s

What do you think about jspm and systemjs - the way it separates front end vs back end dependencies and generates a config.js was very nifty.

Haven't used it, but I don't believe it has code splitting?

Webpack isn't really plumbing like a task runner, it's primarily a dependency wrangler. If you have a page template, which declares dependencies on various partials, each of which declares dependencies on images and JS modules and CSS partials, then Webpack can grok all those dependencies and do things like bundling the images/JS/CSS needed for this or that subset of pages (along with hot loading, source maps, etc.).

Of course, it can also do stuff like minification and transpilation while it does this, so it tends to get compared to grunt/etc. But the magic of webpack isn't the bundling, it's that you can build highly modular pieces of web content and leave webpack to work out what needs bundling.

I do not think any way of doing things should be killed. People should educate themselves to be able to choose the tool they feel comfortable to do what they need. It is simply as that. If the old tools work and you like them, use them. If you are a beginner and do not know what tools you should use it is your problem. I agree that the things could be better but I think that this idea of making everything super easy for beginners is not a thing we should always focus first. I do not meant to sound harsh but I do not know if things could be much better considering all the things happening with JS on the last years.

Why not just npm scripts instead of webpack/grunt/gulp?

Because just bash would be insane to get the features of something like webpack or gulp.

I can hardly relate. Perhaps I got lucky, but my experience with the React ecosystem has not been painful. Coming from Angular previously ($watch? isolate scope?? transclusion???), it was a breath of fresh air. It might also be due to my avoidance of certain rabbit holes that are prevalent around React.

One of those being the React community's love affair with immutability (immutable.js, Redux, etc). JavaScript is not itself designed around the concept of immutability. Mixing the concepts has only led me to fight with the language and the existing ecosystem. Immutable patterns work best in a world where most things are immutable to begin with, not when you're trying to coerce a world of mutable tools to be immutable.

I'll admit, walking on some of these landmines initially was pretty painful, but I've been working with large codebases in React (SPAs and projects with tens of thousands lines of code) that I feel I've discovered the right paths to take. Here's my takeaways for modern frontend projects using React:

- Keep code organized in modules (a la CommonJS) so code doesn't become a big ball of mud.

- Use React Router to enforce that organization.

- Stick to vanilla JS- ES5/ES6/ES7--it's better documented.

- Use Grunt, and then add in Gulp when needed, otherwise you'll be writing a lot more boilerplate.

- Use Browserify, not Webpack--it doesn't try to do everything.

- Use a reactive data paradigm to keep data flow simple (observables, e.g. Mobservable works really well) instead of Flux/Redux/*ux.

- Stick to real CSS and use namespaces (or web components), not React's hijacked inlined version of it.

These practices have helped the teams I've worked in get stuff done and have scaled quite well.

There's some trickiness around drizzling data down a hierarchy of views (creating redundant Params for modules) and around action handling outside of Flux (state should live in the controller, so how does a child module pass the action back up gracefully?). How do you addresss those?

I'm all for uni-directional data flow and React's concept of being explicit by passing data down through props. When it comes to application state however, that's when I whip out React's context (now documented https://facebook.github.io/react/docs/context.html). I follow the pattern of Redux/Baobab of having a monolithic state and partitioning it by module namespace (to avoid data dependency issues, e.g. Flux's waitFor hell http://christianalfoni.github.io/javascript/2015/02/06/plant...). Each module manages its slice of state and exposes an API for encapsulation. This also plays really well with React Router. In other words, the application state and the actions that can be performed on the state are passed down through the context. I prefer Redux's concept of smart/dumb components (https://medium.com/@dan_abramov/smart-and-dumb-components-7c...) to make sure the application state isn't being spaghettied all over the code. With Mobservable, there's a specific part of their documentation which I think does a decent job of explaining a similar set up: https://mweststrate.github.io/mobservable/best/store.html

I seriously don't understand the issue here.

I find the overhead completely negligible. I've worked on many React apps. I've worked on innumerable apps in other, different frameworks, tools, etc. too. I still find my React stack (I say "my" because I'm sure my stack is different than yours in one way or another) to be the best solution, and this debate to be tedious.

That said, I feel like every ecosystems works this way: Complaints about lack of good tools/solutions, myriad tools/solutions are built, then there are complaints about the overabundance of tools and complexity of the ecosystem, so everyone abandons whatever the status quo is, and then...back to square one.

> (I say "my" because I'm sure my stack is different than yours in one way or another)

I think that's the problem. For a beginner what is their stack? It's a wild west of 'this months hip library' and for a beginner it's unintelligible.

> It's a wild west of 'this months hip library' and for a beginner it's unintelligible.

What's wrong with the "just pick one" approach??

Can you point me to one that'll help me actually get something workable up and running? You say you have one; I assume it's something you've put together over the time you've worked with React, and not something you just pull in from someone else's repo.

1. Do you have yeoman? http://yeoman.io/

2. I generally have `react-fullstack` installed

3. Run `yo react-fullstack`, `cd my_project`, `npm start`

Personally, I think its a bit overkill. I tend to delete most of it and add Bootstrap myself, but its a decent way to start a project.

Search for and pick a generator that suites your needs: http://yeoman.io/generators/

I use very basic npm script with browserify to watch/build the output. browserify uses babelify transformer.

The massive amount of great tooling and debugging for React is a strength not a weakness.

If people are overwhelmed by React I feel it is likely because:

1. they haven't yet grokked the implications of how re-rendering every single time changes how they have to store the state of their app. (von neumman)

2. related to that, the choice of how to store that state and dispatch to a backend is not baked into React

3. it is harder to build an app up slowly because you have to have a rough idea of what the structure of your app state looks like ahead of time.

So, you're forced to actually know more about your UI, UX, and design before you implement it. It takes longer to implement but once it is done, it's done and easy to improve upon - it's not fragile.

For hacking something together it might not be the way to go. But for a well thought out implementation of an app which interacts a lot with it's backend, I think it's the only way to go now.

I also feel like people will be missing the React wave at their peril. We're on the verge of being able to cleanly abstract out an applications delivery mechanism whether its native, mobile, or web. That is because of things like React and ReactNative and it's immutable render-every-time approach.

> So, you're forced to actually know more about your UI, UX, and design before you implement it.

I hope that's not accurate, because if it is, it's an enormous step backward.

Good software is always about novelty. (The non-novel parts should become libraries, frameworks, services, etc.) Building novel things requires a lot of exploratory work. And exploratory work goes best when your cost of change is low, which means keeping your batch size as small as possible. Anything that forces you to know more means larger batch sizes and higher risks of failure.

Most of the improvements in software methods over the last 20 years are related to smaller batch sizes and easier exploration of a problem domain. I'd hate to think React is pushing against that trend.

It's not. You can change stuff and build stuff incrementally just fine.

I was going say the same thing, a little differently.

Only other comment is around having to know your entire app start up front. If you break up your app into micro apps each of which implement a given feature of your site then it's much easier to handle that way.

I think people try to get started with react and they jump to the boilerplates that are 'production ready'. Those boilerplates include routers, frameworks to bind routers to state, frameworks for server-side rendering, some new ES7 syntactic sugar, a bleeding edge module bundler like Webpack...the list goes on. They may or may not be a great combination of frameworks, but each has their own learning overhead.

So people confuse learning react or learning redux with learning how to use every single framework shipped in the common react boilerplates. It can take weeks of studying or learning enough about those frameworks to understand how they all work.

React itself is moving along at a healthy pace. Popular frameworks around react change about every week which causes this fatigue that OP speaks of. The most important thing IMO is learning the core concepts behind react, flux, redux, react-router, and worry about product client/server rendering and module bundling later.

I was lucky that I started on React from within Meteor. Meteor builds everything automatically, and does not require you to spend 5 days tweaking a brittle series of config files.

Last week, I wanted to start a React app that talks to a Phoenix API and found out there's a ton of different ways to create a react app. That sucks. There is no 'one obviously better way.' Kudos to Ember for being great in that area. React needs to have an obvious way to start and run an app. Not this gulpwebifypack config garbage

Proof is in the pudding, check it out! http://sergiotapia.me/2015/09/18/react-and-meteor-match-made...

I was thinking to put React.js in my adopt circle, but I spent a couple of days setting up the Node.js gulp-vinyl-browserify-babelify nonsense, and it really is a witch's brew of configuration hocus pocus. Its compelling to know that React is backed by Facebook, but React is simply verbose and comes with too much stuff packed into one package.

Whats the alternative? Thanks to hacker news i bookmarked vuejs.org and finally got a chance to come back to it. I made a couple of pages with vue.js, and I think there is a lot less stuff to do. There's no JSX. Your HTML peppered with vue.js directives is your templating language. There's no server side rendering, but that may be a good thing in the end. Fewer dependencies, less learning curve, less ecosystem to swallow in a single gulp. I hired a fresh grad from the Philippines, and he was able to pick it up and run with it immediately. I've only been using vuejs over Christmas, but I'm looking forward to seeing what else it can do. I'll post a small PHP-backed CRUD app if people are interested.

React can do strongly-typed views. I use Typescript, and I can build the DOM either in JSX or by nesting React.DOM.div() and friends, and the Typescript compiler will yell at me if I use an event handler/variable/etc. that does not exist in the code. Why would I go back to an opaque templating language after that?

It all depends. React as of right now is the only viable option that has decent server side rendering for 80%+ of web apps it's a must for SEO, FB integration etc. Until Angular 2.0 ships and Ember get's fastboot completed there is no other major viable option.

DoneJS as well. It includes Web components, a browser module loader, and has the most complete server side rendering of any framework. https://www.google.com/url?sa=t&source=web&rct=j&url=http://...


by "major" I meant something that has recognizable market share.

Im don't know a lot about SEO but afaik Google crawls javascript pages. Do you still take an SEO hit in that case?

> gulp-vinyl-browserify-babelify nonsense

Use Webpack. It replaces the need for all of these and does a much better job.

"Replace this garbage with this other newer garbage."

Doesn't that just glue them all together? We're using it at work, and we brought in an in-house React person, but I have no idea what the config does/signifies, and every time they change something, I absolutely don't understand why or how it works. (Our tests currently don't work. I mean, they can run - unless there's an error, in which case it exits early with a 0 status, without running any of the subsequent tests.)

This is partially on me - I should read the shit out of the docs - but so far it seems like it just paints over the complexity a little.

Late update: read through some of the webpack source code. As near as I can tell, it completely ignores most of the options passed to it via the CLI. (For example, --colors seems to have zero effect on anything.)

After 300+ lines of config spread over 3 files.

What does all that stuff have to do with React? Isn't it just a bunch of general purpose JavaScript tools that you decided that you needed to use?

Yeah you're right. I conflated the two issues in my comment.

This is probably my biggest criticism of React (and by extension similar such as Angular 2, although React's choice of JSX is a clear exacerbation of this problem) - the move towards more tooling is terrible for what should be something simple. HTML/CSS/JS are not rocket science - in themselves, they're simple languages for building a user-facing app. It is developers making things more complicated by having us use a whole smorgasbord of tooling to optimize for using [insert feature] instead of trying to keep things as simple as possible.

I just hope that over the next few years that this simplifies so that we don't need to have build tooling run everything.

> the move towards more tooling is terrible for what should be something simple.

I couldn't disagree more. I think the advances in tooling around web development is extremely exciting and absolutely necessary if we as an industry want to get our act together writing complex web applications. It's worse for getting new people into programming or web development, but there are always pretty simple drop-in scripts people can use to play with things like Babel, React, or even crazy stuff like full client-side module loading with SystemJS: https://gist.github.com/cem2ran/9be3dd3499566302d5ae

> HTML/CSS/JS are not rocket science - in themselves, they're simple languages for building a user-facing app.

I think that's extremely dismissive, and woefully underestimates the difficulties one faces building a complex long-lived web application.

Angular choses TS (well it's optional but so is jsx).

This is also my no.1 pain point with typescript - they focus on the typechecking part only - you want new JS features ? Use custom js transpilers, polyfills, etc. This means setting up custom typings, build system, module loader, etc.

JS land is just a huge mess to put it nicely because of th inherent problem with browser portability but its made much worse by the low barrier to entry community full of noise. I wish Dart had a better JS interop and faster compiler, in theory it solves all of my JS pains (excellent std lib, sane semantics, default package manager, modules from start, etc.) - in practice it produces big js files, compiling takes forever once you include frameworks, talking to JS is c ffi level of tedious (from what I understand they are working on improving it but its still non trivial with a significant performance overhead)

Looking at that module : https://www.dartdocs.org/documentation/js/0.6.0/

The only documentation is bare-bones examples - 0 docs about conversion between dart<->js objects/collections/closures etc. when crossing JS interfaces. You will agree that this is an area which requires very precise description of semantics - after all we are bridging two dynamic languages with two incompatible object interfaces one on top of the other - reverse engineering the semantics sounds like a nightmare.

From here : https://github.com/dart-lang/js-interop-deprecated I was able to find this : https://docs.google.com/document/d/1X0M7iQ1PraH50353OnjKidgr... which was last updated in 2014 and I'm not sure if it's relevant.

Hm, I found that one of the strengths of React is that it's so easy to sidestep a lot of the complexity of it, if you're not building a true SPA. We use React to add some interactivity to our forms and dashboards, so we only need to use state & props. No Flux/Redux/etc backends, and not much messing around with webpack & co.

This is something I have observed about every language/framework front end combo I have ever used and I have done it long enough to go all the way back to Qt 3 and even before. There is no terse way to describe a UI. Period. C++ or Java I understand they are typed languages with an avowed aim of giving the programmer fine grained control over the program. Objective C may have become popular more recently but it too is an older typed language. The unbrevity of JavaScript is inexcusable and it extends to every UI framework it offers. Tooling is no way to try and ease the problem.

The last time I felt productive doing UIs was with WinForms and before that VB6.

At the end of the day, this is what the web community will ultimately end up re-inventing.


> There is no terse way to describe a UI

Did you ever seen Tk?

Tk was only ever feasible for very simple, often throw-away, UIs, and not much more than that. Tk can't be compared to Qt or the other full-featured UI toolkits that exist.

I think the problem is that the people using React see the grand architecture in Relay / Falcor / Om.next, and are trying to recreate those API's using current libs. There are still a lot of parts missing when you try to build an app with the same abstractions as the aforementioned libraries, and I think the author is correct about 2016 being a year where those gaps are filled.

What we really need is a translation of om.next to javascript. That library summarizes all the good ideas from Netflix and Facebook into a small library for every day use. The fact that it's in Clojurescript makes it a non-starter for others, too bad because it's a really great eco-system.

edit, list technologies: React + Redux is a good start, but we need composable queries and a router (falcor) or reconciler (om.next) that manages data fetching / caching. JLongster has done some experimentation here with datascript integration https://github.com/jlongster/redux-experiments/blob/master/s...

People jumped the Angular / Ember ship for React because those frameworks were too complex. Then they realized they needed additional features. Now there's a push to unify these features into a framework...

You have to put your complexity somewhere.

I believe in Angular's case the changes from 1.x to the 2.x branch didn't help much either.

Nodded my head all through the article. Project setup hurts. "What folder do I put my components in? Even the ones that only get used on one page?"

We need a DHH.js to rise up and bring us "Rails, for React".

Opinionated programming was/is Rails' major contribution to the web world, as far as I'm concerned. By providing a baseline of things you need (directory structure, modules, logic flow, etc.) it made starting a project easy. In fact, it's just a single command.

I think having all of these (ever changing) options is a sign of Javascripts immaturity; it's not bad, it's just growing pains. Hopefully someone will step up with a cookbook of best practices which will be respected and used throughout the community.

I put my components into app/components. This is the one, true directory structure. All other directory structures are wrong. \s

Build tools are partly necessary because of how many old crusty browsers hang around out there. I mean, I still work on an app that has to support IE8. That's just ridiculous. As it is, ES6/ES7 imports make a lot of the issues of JS inclusion a thing of the past, but the build tools are necessary for packing these together and transpiling down to ES5, to support older browsers. The other tools you see in the React ecosystem do take time to learn for sure. The whole React/Flux paradigm takes a while but once you get it there's not many surprises. I do feel the fatigue though just as the author does. There's a million ways to do what the browsers should just do natively already. In a few years we hopefully won't have to worry about this anymore.

Just use Elm instead of Javascript + Frameworks

Simple, Fast, Reactive, Functional


I agree. I've been using Elm on one of my current projects and my experience with it has been great. Of course, I do hate Javascript with a passion, so there's always that bias to consider.

there's NO <insert language/framework/tool here> fatigue, it all depends on YOU & how you're willing to LEARN continuously

Let's put it like this, there are many ways to build a house, but you don't see a builder without at least hammer & nails right?

One day you see another builder with a nail gun, do you ask the builder about the machine or do you keep building a house using JUST hammer & nails?

After sometime, you see another builder building a house without using nails at all

After sometime, you see another builder 3D printing a house...

The flaw with this analogy is that when you need to revisit the house you built with a hammer and nails, you can continue using your nail gun. In S/W development, you have to go back to using the hammer and nails (or at the very least have a strong understanding of the hammer and nails). Furthermore, once you've built a house, it's built, and the work you will be doing on it will be minimal. Software development is almost the opposite.

> The flaw with this analogy is that when you need to revisit the house you built with a hammer and nails, you can continue using your nail gun.

Say clients wanted a kitchen completely remodeled, you still don't have to use hammer and nails or nail gun --- I could easily demolish the kitchen and 3D print the new kitchen

What you know/done before doesn't necessarily dictate what you'll [can] do (which is the case on the Web)

Client: I need a modification to this cabinet so I can put in a double stove.

Carpenter: Welp, we are gonna have to demolish the whole kitchen. So with the estimate of a full kitchen remodel you are looking at $80k

Client: ...

I guess my analogy is being scrutinized (so to speak), that being said; YES!, that WILL happen if the carpenter doesn't know any better (or is a crook).

A smart/savvy (or whatever you want to call it) carpenter will easily do the modification[S] without tearing down the entire kitchen. Just like you can drop React into an existing project.

Enough ketcheh! Let's talk Jabascript gais!

Yeah, this is something I struggle with: Always trying to find something new to learn and not mastering anything. It is exhausting, but ultimately it depends on me.

That said, to me the React ecosystem is the opposite of "convention over configuration" which can frustrate a lot of beginners. There's no popular `rails new` or `ember new` to get you started.

I use React, but I never jumped on all the other various projects surrounding React, because (as far as I could tell) none of them solved any problems that I was having.

Just do the simplest thing that works. This is the same hype as Angular 1 had. People will move on eventually.

meteor works nicely with React. It may not be the most optimum route (problems with webpack, outdated node, crappy testing) but is a decent curated way to get started.

The official react stack will be supported going forward, and the velocity of changes is not quite as much as the a-la-carte JS environment.

It's interesting that first little JavaScript libraries and one-liners were popular in the 1990s.

Then AJAX and large framework libraries like Yahoo YUI, Ext JS, Google Web Toolkit (GWT) got popular.

Then JQuery a more lightweight library got popular. Then John Resig's (JQuery) book "Pro JavaScript Techniques" (2006).

Later Douglas Crockford's book "JavaScript the Good Parts" (2008) were highly influential. HTML5 and JavaScript5 came along. A new wave of JS5 vanilla style influenced by JS5 and Crockford's book got traction and more and more replaced JQuery (2010 onwards). HTML5 browsers got widespread, the JS performance got a lot faster (JIT VMs) and attracted a lot more developers.

CoffeeScript and new single-page frameworks like AngularJS and Ember.js got popular ca. 2012.

Google initially focused on Dart language as a replacement for Javascript and later transpiled to JS (beside others). Microsoft aquirehired ex-IBM group now known as Monaco code editor (VS Online, VSCode, etc) and created TypeScript that suits their C++/C# massive code base and coding pattern better. They influenced the development of ES6/7 to include "classes" syntax, etc.

Google added "Shadow DOM" feature to Chrome and proposed it as a new HTML5 feature. http://www.html5rocks.com/en/tutorials/webcomponents/shadowd...

Shadow DOM hasn't been integrated in other browser (http://caniuse.com/#feat=shadowdom ) though Facebook thought the idea was good ("Virtual DOM") and re-implemented the idea as JavaScript library; what is now known as ReactJS framework (got popular in 2014).

On the otherside NodeJS with NPM and its ecosystem of many tiny libraries got popular in 2011.

ES6/7 got popular on server and client side (though later still needs a transpiler step).

So we are again with huge JS framworks on the client side (1MB minified JS files are common but not funny on mobile devices). And highly modular small libraries on the server side (NodeJS).

Probably in time when full ES6/7 and Shadow DOM support gets traction in all modern browser, we will see another wave of more lean vanilla ES6/7 code without the huge libraries. You can write a super responsive and fast JS web app in less than 300KB code. You ask for trouble with your 1+MB JS file, especially on mobile devices that will crash or the users has to wait 30+sec on a cellular connection.

Lean vanilla JavaScript is great and high performant. Over-engineered frameworks make your life easier to start but will make it harder to stay in touch and maintain. Hopefully ShadowDOM browser support gets traction.

The fat vs thin client cycle has been happening for far longer than web dev. It's been going pretty much since we have interactive computers. Neither strategy is really the right one, it depends on the context of what you're trying to do. If only all young programmers could be taught a history of programming class where they analyze old deprecated technologies that used to be popular, and form an understanding why they rose to prominence and why they faded away. Maybe we could avoid new generations making the same mistakes over and over again with different technologies.

Applications are open for YC Winter 2022

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