What can we learn from how jQuery symbiotically pushed the Web Platform forward?
When Ajax happened we had popular frameworks in Prototype, Dojo, and MooTools, but it was jQuery that took over and went to the next level in popularity and usage.
As we reflect on the popularity of React, it is important to think about “why”, but also how we can bake the good ideas into the platform.
There are elements of React as the current dominant ecosystem (there are always many, and due to the growth of the Web some of the smaller ones are naturally in more usage than the winners of the past!) that remind me of the jQuery era, but there are also important differences to reflect on.
What does jQuery teach us?
One of the great things about jQuery was that it had a simple, powerful idea. It’s entire mindset was “find these items in the DOM, and attach these events to them”. Others had this too, but they were often secondary. Prototype (a big favorite of mine back then) had $ to get an element, and $$ was for selecting.
The fluent API made for a very functional way of working on these elements and events. You didn’t have to create loops over elements all of the time, and it resulted in very clean code for the majority use case (not as much fun if you wanted to do the opposite).
This was all simple enough that “web designers” could easily get up to speed and sprinkle away functionality.
A plugin ecosystem exploded as everyone contorted to reinvent, or just wrap prior scripts into this style. Come up with something you want to do on the selection and add it to the jQuery prototype and you are good to go!
While the simplicity of the ecosystem was fantastic, the community quickly ran into the age old problem of curation. There was just so much duplication and cruft to sift through. It also fakes you out to think that you are building out a lot more than you are. You could add functions that understand The One True Pattern, but there wasn’t a component system that you could build on (unless you picked one of several).
The best part of this era though was how the benefits were embraced by the platform. John Resig didn’t try to build The jQuery Platform, even though plenty of VC’s pushed him to. Instead he helped browsers and we now have items such as querySelector*, dataset, and classList. Once you bake these type of things in, your library becomes a place to hold your opinions, and make the cross browser stuff work (polyfill, prollyfil, and ugly hacks to boot).
I also think that there were plenty of other good side effects. The fluent style of API probably opened peoples minds up in a way that only helped us with promises and rethinking APIs such as XHR vs. fetch.
How is it different with React?
All in all jQuery has evolved along with the Web platform, helping improve things beyond itself.
I think that there is an opportunity to do the same with React, but I am concerned that we could also go in another direction. React came out running in the same way that jQuery did. jQuery was later to the game and ran past Prototype, Dojo, MooTools, and many others. React has done the same to Backbone, Angular, and others.
If you look at the details you can get frustrated as they are not apples to apples. React is a lightweight view layer, not an application framework or platform! These days React is more than its roots, and often refers to all of the pieces that have come out around the edge: Redux et al. Now a days if you walk up to someone at a conference and say “I use React” it is akin to “I use C++”. You then have to explain how you use it: “Oh, I use boost and …” => “Babel, Redux, react-router, ….”.
There is a lot to love about React. I really enjoy the developer experience, mainly the ability to tie together a functional declarative mapping of “given this state, what do I render?” This is so very powerful, and feels like you are back to the world of reloading page. This empowers you to reason through your application, write tests that make sense, and debug the application.
Debugability is hugely important, and I think we may not give it the importance that it deserves. Just ask the Circle CI team how important it is to them to be able to take some application state from a user and replay it to see what was going on? How amazing it is to be able to snapshot the state and get undo/redo in a much saner manner? Game developers have always understood this… you can dump your game state and restart right where you are.
Early on in the React hype cycle we heard that the biggest pro was performance, which in my view was very much missing the mark. Many developers picked it up despite the fact that they didn’t like that ugly JSX thing because they heard it was so fast. Over time they found that the componentization approach was sound and sane, which I think bodes well for us to look at Web Components as they launch cross browser this year, and they loved the flow of the functional data model to the view.
It is pretty obvious that you can think of scenarios where diffing two trees won’t be as fast as mutating some state in the DOM. You can also think of scenarios where you wouldn’t want to make multiple changes to the same parts of the DOM to cause jank and rerendering for no reason. It depends. The DOM used to be so very very slow that you would very much want to make sure that you don’t touch it until you really needed too, but we have also seen that these days the DOM may not be as slow as you think, and React may not be as fast as you think.
What would the real win be? Wouldn’t it be great to let the browser handle more of the load, but let the developer declare the state? That is the world that I would love to strive for, and it requires getting the browsers and web devs together again.
There has been another huge change between when jQuery happened and when React happened: mobile.
Not only do we need to think offline first, and progressively add on capabilities based on what the user agent can do, but we need to start from the understanding that the network is flaky, and the devices are amazing (ignoring many of the crappy ones out there, and the problem is that we can’t ignore them as your current users and next billion users have them) but under powered compared to our desktop counter parts.
We need to push the Web platform to run fantastically well on mobile, and we are getting there… it just requires a push to work together.
React Native showcases the other change. jQuery was pushing to make web development easier on the Web (jQuery Mobile came later and was still more mWeb than WebView IMO). These days developers that are looking to get their services out to their users need to seriously consider iOS, Android, and the Web. The balance of these changes depending on what you are building, for who you are building it, and where they are located (US == iPhone++, India == Android++).
If you take a large development shop, chances are a large percentage of them are web developers. Also, no one really WANTS to minimize their leverage between their iOS, Android, and Web applications. This is where developers will always push to get more leverage, even if it ends in roads that can’t deliver an experience that is top class.
React Native is an example of this, a push to see if we can get more leverage, and it is a huge change from the world of jQuery. At this point the “platform” is React (a la Angular etc) vs. the Web or iOS or Android. To do a great job you need to understand the true computing platform, but this aims to allow you to do more across them. This is where we can get at odds with the Web and try to fight it.
I understand this fight. I begrudgingly switched Bespin to run on <canvas> to deliver the experience that we wanted, but it meant that we lost out on much of the Web (accessibility etc).
I see the same problems occur. Just do a search for content editable and React and you will see similar struggles, which show the fight between React wanted to control the world and the browser having the control.
There is often a fight for control between user space and kernel space. This came to mind again when reading Bryan’s post on unikernels and his case that shows that not only isn’t it more performant, nor secure, but that it never can be. You give up too much by shoving everything into a single purpose kernel, including the debugability point, echoing its importance.
In 2016 I want to find a way to bring a fantastic blend of debugability, developer experience, and performance to the Web and developers all over. We can take lessons from the best routers, data abstractions, and component models. We can build new primitives into the Web platform that will enable not just one framework speed up but all of them.
As we work for a Web that performs up to snuff for users, we need to pull together. Can we pull it off? Can we speed up React and friends now as we evolve together for the future? Or is the Web destined to be a second class citizen?