React/JavaScript fatigue
medium.com
medium.com
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.
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.
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.
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.
OR
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.
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.
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)
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.
- 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.
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.)
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.
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.
</Rant>
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.
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.
.then(() => doSome(thing)) with bare doSome(thing)
and
.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
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?
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.
I do hope CLJS stays a strong niche language but any hope of it taking over the world is unlikely, IMO.
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'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.
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.
There's a long discussion here, which I'm pretty sure you're already aware of, on the tradeoffs:
https://groups.google.com/forum/#!topic/clojurescript/LBy0yi...
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? Async/await in CLJS is:
(defn async-fn [] (go true))
(go (<! (async-fn)))
How is that syntactically and conceptually complicated compared to async/await?
(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)))
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) { ... } }
(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.
Moreover, it has funcool/cats bindings, so you can use promises in mlet and alet macros if you are into monad thing ;)
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.
(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.
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.
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.
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 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.
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.
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.
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 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.
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.
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.
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.
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?!
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
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.
Being able to render your javascript server side with isomorphic (or universal) javascript is one of React's big selling points.
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".
> 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
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.
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.
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.)
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.
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.
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... :)
Because browsers don't fully support ES2015 yet? not everyone wants to use/learn new buggy transpilers, new build tools, add more boilerplate, etc..
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.
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.
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.
Well, at least that's what I picked up from this rather honest opinion.
You shouldn't be recommending software to anyone.
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.
> 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.
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.
- 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.
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.
In most of my projects, I no longer needed Grunt for anything aside from deploying to production, etc.
http://engineering.khanacademy.org/posts/js-packaging-http2....
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.
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.
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 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.
What's wrong with the "just pick one" approach??
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/
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.
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.
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.
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.
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...
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.
Use Webpack. It replaces the need for all of these and does a much better job.
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.
I just hope that over the next few years that this simplifies so that we don't need to have build tooling run everything.
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.
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)
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.
Did you ever seen Tk?
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...
You have to put your complexity somewhere.
We need a DHH.js to rise up and bring us "Rails, for React".
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.
Simple, Fast, Reactive, Functional
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...
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)
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: ...
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.
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.
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.
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.