You Really Don’t Need All That JavaScript [video]
youtube.com
youtube.com
With a few built-in "site structure" features in the html standard, the browser could do a large part of what developers end up reimplementing over and over again - both with and without JS. A large part of "knowing about usability" is just knowing how to execute these basic navigation features without goofing up on the many pitfalls available to you.
For example, imagine if there was some kind of Site Structure standard, or Page Structure standard. The browser could then generate standardized navigation elements with perfect UX on every platform, and sure, you can style them, but the basic functionality just works everywhere without having to make advanced javascript/html/css menus that take into account concepts like responsiveness, touch interface, or accessibility.
Not it's not. That's what it was created for, but clearly it's not anymore. People are not publishing just documents anymore, it's a fact that HTML is used for all sorts of things from simple sites to complex applications.
We agree it's not great, for all of these purposes but this ship has sailed, we need to deal with it. Either we create something different and good enough to not die in the water, either we improve HTML so that it supports what people are already using it for.
It really is. Just because some people have a uncanny propensity to mix concerns that shouldn't be mixed, that doesn't mean that a data structure is something else.
Here's another way to think about it. The web is competing with platform-specific apps (iOS, Android, macOS, Windows, etc.) to be the primary computing platform of the world (in terms of how the general population interacts with computers). Your position seems to relegate the web to a secondary/niche platform by definition. Do you agree that the web should be a secondary/niche platform?
Disclosure: Google Web DevRel (work on https://web.dev)
The web/web app paradigm isn't the reason Electron exists. Electron exists to poach web developers into app development, because native code and frameworks are hard. There's no technical reason why we can't go back to native apps, the friction is entirely due to culture and business, and an entire generation of developers who've never written a line of anything that isn't javascript or maybe python.
Also, being able to distribute and run software over a network is a good idea, and it's a logical progression of the purpose of the web, which is to allow open access to information and media. Code is no less a form of media than video, audio, images or text. A web that would let me read whitepapers but not let me emulate an Amiga would be crippled in its potential.
And that notwithstanding the fact that most "web apps" are just documents that use javascript as a front-end framework, and most people's complaints along these lines are aesthetic and emotional, rather than technical.
I don't agree with the "poaching" statement, but I would argue that "frameworks are hard" should be replaced with "desktop gui frameworks are appalingly poor".
Webview-based rendering frameworks trade away native look-and-feel for a myriad of tools and processes and techniques and workflows and expertise that you simply do not get with plain old widget frameworks. GUI developers know this, and in particularly GUI frameworks vendors are well aware of this. In fact, check XAML or QML.
Serious question, what's the issue with react-router?
I'm sure there are situations where using react-router makes sense, but for me it was one of the few packages 'blessed' by the react ecosystem that gave me more trouble than it was worth.
The linked video talks about documentation, which is a great example. Do you think I should have to download an app to read documentation? Should I have to go find my phone to read documentation because they didn't have enough time to also support desktop OSes?
Some claim the added flexibility and easier deployment[1] of web based applications is worth this 3x increase, but usually that's tech staff saying that, not business owners. They want get-it-done-on-budget, not eye candy, if given a clear choice.
We have to come clean and admit that job security is keeping us technical people from being objective on this. A convoluted standard increases demand for specialists.
I suggest the industry form 3 browser-based mini-standards: A) Art/Gaming/Charts/Entertainment, B) Document-oriented (current HTML may almost be good enough), an C) "productivity" oriented data and CRUD.
That way each can focus on doing its niche right instead of trying to be one-size-fits-all.
[1] With a good stateful GUI-markup-over-HTTP standard, we probably wouldn't need local installs to get decent GUI's.
HTML was designed to be a way to create and link documents so that someone or a machine at one end of a distributed network could access it on a different network, not become an app platform. Everything else done beyond that is a perversion of HTML.
It would be interesting if there ever was a standard app container runtime that doesn't use HTML/JS/CSS. I guess that the last serious attempt at that were Java Applets which never took off.
Flutter Web is attempting something like that I suppose. Not that I think it will take off.
It would be probably be a better idea to be more conservative with the adoption of new technology.
XML/DOM representations of graphical state are a lot closer to the Unix ideal that we have in the command line. A big reason why the command line is often more powerful than a graphical interface is because the command line allows users to easily wrap around, extend, pipe, scrape, script, and translate interfaces.
HTML is the evolution of that ideal -- a statement that graphical interfaces should be as flexible and as manipulable as a command line interface.
https://news.ycombinator.com/item?id=24270960
If HTML is no longer being used the way it was intended, is it unreasonable to request A.) A replacement, or B.) an HTML upgrade?
Here's a thread from the w3 mailing list discussing possible scripting languages for HTML back in 1995[0].
And here's Tim Berners-Lee talking about running code in HTML in 1992[1].
You're simply wrong that running code in HTML is a perversion - that was envisioned as a possibility since the beginning, it just took time to manifest.
What wasn't intended was for only one scripting language to dominate. When the script tag was released in HTML 3, the hope was browsers would support multiple languages, which is why it had a type attribute, but that never happened.
[0]https://lists.w3.org/Archives/Public/www-talk/msg00099.html
[1]http://1997.webhistory.org/www.lists/www-talk.1992/0064.html
That's the hard part - any such solution has to compete with the HTML/JS/CSS ecosystem for free.
Imposing structures on webpages as suggested would incur limitations, but it's a necessitated consequence of having content with machine-readable semantics. Think of how we encode characters -- we don't encode them by vector graphics of each character or two-dimensional array of pixels. But rather, we encode characters by concise code points. Yes, we lost flexibility by that. In plain text files we cannot represent different fonts because characters are simply represented with a sequence of code points. But don't the advantages outweigh the disadvantages by a large margin? We can read them in whatever font we like, we can `diff` text files... the list goes on and on. It's unfortunate that web ended up as a huge mess which machines can never reliably comprehend.
For example, HTML has a native <dialog> element, did you know that? https://developer.mozilla.org/en-US/docs/Web/HTML/Element/di...
Most people don't, because it's completely useless without some JavaScript to toggle its "open" attribute. This was by design. The requisite interactivity across elements simply can't happen without a) databinding, or b) a whole turing-complete language. Since we don't have a, we use b.
If all we needed was a bit of JS to wire up state between HTML elements like <dialog> and <details> I think we would still be in a great place, even if we didn't have native data-binding. The bigger issue IMO is that in many cases native elements can't be used either because they fall short of the desired UX and can't be extended/enhanced (e.g. <select multiple>), or browser support isn't widespread enough (e.g. <details>).
Why do you believe the browser should support that with primitives? Advocating for that kind of specialization lies somewhere between forgetting important and basic historical lessons on software engineering or an unsubstantiated belief that now everything will be different.
> A large part of "knowing about usability" is just knowing how to execute these basic navigation features without goofing up on the many pitfalls available to you.
You're leaving out a part where said usability principles lie somewhere between emerging requirements that are still under development or fads that are scheduled to be replaced with the latest and greatest promising idea.
Suffice to say arguing to force them into browser as primitives is demanding that they should be set in stone as is.
He then says that the solution is using an iframe (called a portal.) which looks to be a proposed API. https://web.dev/hands-on-portals/ - this is available as an origin trial in Chrome 85.
So, he's saying that SPAs are bad and we should invest in a Chrome-only feature or future feature that might make it through standards? This makes no sense to me.
There are multiple uses for SPAs. One is building a genuine web application, such as Gmail or a SAAS. SPAs are also used in places they shouldn't, such as news sites, because of the page load problem as mentioned above. Portals would be useful here.
But it gets to the real problem: client side rendering in the past decade has had a lot more thought and effort in tooling, tutorials, and patterns on the client side than server side, especially with mixed mode. (Mixed mode: adding javascript on top of server-side rendering.) The problem is that server-side rendering and mixed mode is not a good development experience. The back button was never a fully solved problem and POST-redirect-GET is essentially an insufficient hack.
If someone wants to talk about making server side rendering for web applications a viable experience, we are likely going to need changes to the standards and we will need to build up a great set of tooling to solve the problem. (Oh, and since it's server-side rather than javascript, each framework or language will have to replicate it just like React, Angular, Vue, and others have done.)
That was my own conclusion, at first I thought "whoa, <portal>? never heard about it but looks cool", I proceeded to search for `HTMLPortalElement` and then I got to a W3C page saying "Draft" and I was like "what? a yet to be standardized feature? thanks, but no thanks, I'll might check it back in 2 years".
I hear you though; I thought this was gonna be another "you don't need React, here's the Vanilla JS that does the same thing" kinda presentation, but was actually intrigued to learn about this <portal> tag. I does seem to address the (main?!) bugbear we have with interactive webpages and the fight between the server and client.
Although I am surprised there's little to no support for it right now - thought at least Chrome would.
https://caniuse.com/?search=portal
Edit: Ofc it can be tried out w/ Chrome if Dev Enabled, but it's not user supported at this time.
Appeals to people who are:
1. Frustrated with the complexity/brittleness of javascript tooling
2. Still learning (oooo, shortcut?)
3. Pining for the good ol' days (conveniently forget ie6)
A better, more realistic talk might have been "how to make a fast, responsive, mobile-friendly site without javascript and here are some new browser features to look forward to" but I'm sure that would have got a lot less clicks.
I can understand the assumption that your audience is a bunch of bootcamp graduates who put React in anything they build. But at a Goto conference, shouldn't you be targeting a more sophisticated audience? What if your product is more like gmail, or Google Docs, or Facebook, or Google Earth, or Youtube? What would you think then of someone who tells you to let go of your desire to control the behavior of the anchor tag?
I don't think so. The video takes a couple of interesting turns for me. I thought it was "JavaScript...bad!", but then he converted to a discussion of <portal>, which I thought is where he would end. But the last few minutes he spends on a much higher level point, which makes me think the portal discussion is just an example. In the spirit of your summary, here's my own:
The web platform is evolving. While some of our work exceeds the capabilities of least powerful part of that platform (HTML/CSS) and therefore requires JavaScript, much of it does not. Notably, as the web platform evolves, features that used to require JavaScript no longer will. This suggests a "principle of least power" argument: make an effort to learn about the new advances in HTML/CSS so you can leverage them for as many features as you can, and push the rest into JavaScript. He contrasts this approach with the "just use JavaScript for everything" approach, which carries with it all the risks he outlines in the first part of the video.
The example involves a common page design: left hand table of contents, right hand (typically most of the width) with current contents (chosen via ToC). Jump to a new section, and the scroll position in the ToC is lost.
He describes how to use a portal to fix this.
Compare with desktop GUI toolkits. The ToC would be its own element (GtkListView or QtWhateverList or NSThisNThat). The contents would be their own element (GtkTextView or QtCanvas or whatever). Both are drawn independently of the other. You can call for an invalidation of part of the window. You do not need to consider them part of a single window rectangle that will always be redrawn in-toto for a page load.
Now, my (weak) understanding of why we've ended up with things like React is that in part they are an attempt to solve this by effectively creating the equivalent of a widget heirarchy inside the browser. When a React implementation of his example gets new content, it doesn't invalidate or even necessarily "redraw" the ToC, and it tells the browser what to do by invalidating certain DOM elements (or even just one DOM element).
I think he misses this as a key reason for the movement towards frameworks.
But ... notice that the browser will probably (I'm not 100% sure about this, would appreciate comment from someone who knows), re-render the entire rectangle the contains the page.
Desktop applications don't work this way. If you turn on Quartz debugging on macOS you can actually see the rects on screen that are re-rendered to reflect invalidation by the application (e.g. after new content needs to be displayed).
Maybe I have this wrong, and React and similar frameworks have leveraged a subtle capability in the browser to invalidate a DOM element as a way to only re-render part of the on-screen rect.
But assuming that I've have this roughly correct, this model in which the "atomic, indivisible rendering unit" for browser apps is the page rect seems fundamentally disadvantaged and mis-designed compared to desktop apps.
React in turn does work to let you, the developer, divide your UI code into discrete components that control the layout of some subset of the page, and lets you declare what the UI should look like at any given point in time based on our data. React then tries to minimize the number of DOM updates that have to be modified to make the previous DOM structure look like the structure you said you want now.
More technically: if you change the content of a desktop text view widget, then there is more or less a straightforward and simple code path from the widget invalidating its own rect to the native window/graphics system causing a re-render of just that rect. The toolkit really has almost no work to do to make this happen, and neither does the native window/graphics system.
But in the browser model, the DOM is an abstract model that may or may not map easily onto window rects. So to decide what will be invalidated in the (native) window, the browser has to essentially recompute the entire window and then decide what to invalidate at the native window/graphics level.
Are you sure about layer compositing on GPUs within the browser? My guess is that this is done mostly by the (desktop/native) toolkit used by the browser and is an optional optimization, since the browsers will function normally without a GPU.
At some level though, I think you're right and that the video is wrong in some deep way: the way I was first told about React made it sound precisely like "it is designed to work more like a desktop toolkit", and given this, the video misses one of the more fundamental reasons for contemporary web frameworks.
- https://www.chromium.org/developers/design-documents/gpu-acc...
- https://www.urbaninsight.com/article/improving-html5-app-per...
- https://hacks.mozilla.org/2017/10/the-whole-web-at-maximum-f...
and also how they handle painting and redrawing in general:
- https://www.phpied.com/rendering-repaint-reflowrelayout-rest...
- https://www.html5rocks.com/en/tutorials/internals/howbrowser...
- https://james-priest.github.io/udacity-nanodegree-mws/course...
So no, browsers don't "recompute the entire window". They know what DOM nodes have been mutated, and are able to fairly efficiently redraw just those pieces of the UI that have changed.
I haven't watched the video yet, but React's approach to defining UI structure and updates is considerably different than your typical desktop UI toolkit (ie, Swing, Windows Forms, MFC, Qt, etc). With those classical frameworks, you generally have a bunch of object-oriented class inheritance hierarchies and manually instantiated child widgets with specific parameters (`button.setWidth(80)`, `button.setPosition(20, 40)`, etc), then add a lot of event listeners to manually modify both the data and the UI.
As I previously mentioned, React expects to work with a "retained mode" environment, such as the DOM, where previously-set UI layouts persist until such time as they are modified. React is explicitly based on determining what the current UI _ought_ too look like based on your current state. The problem that frequently plagued jQuery-type UIs is figuring out how to transition the UI contents from where it was previously to where it needs to be now, taking into account all the possible permutations of what could be shown on screen. With React, you tell it what UI output you want at any point in time based on your current state, and it takes care of figuring out what relatively minimal set of changes actually need to be applied.
I'll have to hunt around a bit harder, because it seems that in general, the people who talk in the most detail about browser rendering don't seem to understand the rendering processes in non-browser apps, and vice versa.
For example, all of the discussions of GPU usage that you linked to all seem to skip over the fact that (most) native desktop apps do the same thing implicitly c/o the toolkit they're using. If your ListView widget is ultimately drawn using Vulkan or Metal etc., then the exact same set of abstraction processes and delivery to the GPU are going in a a native toolkit app as the browser (which is not suprising, really).
AFAICT, React has no access to the browser render tree, and it can only control the DOM. As such, it is really positioned at a very different level in the "drawing stack" than, say, Qt. At the same time, as you point out, it also isn't particularly close to the widget layout models of "classical frameworks" (even constraint-based versions as have become more common in recent years), because it deliberately tries to prevent you from having too much direct control over the current DOM - that's supposed to be driven by the state.
I wish there was a more fruitful meeting place where the experiences of 30+ years of "classical frameworks" could shape and in turn be shaped by the decade plus of "web frameworks". I think that the former has a lot offer the latter and the latter has many ideas and insights that could probably improve the former.
All that said -- SSR is the best of both worlds. To the untrained eye, it looks like a step backwards, but there's more to it than that -- it gives separation (if you want it) for your frontend code that usually moves at a different pace than the backend code, server-side rendering for performance (obviously), and complex client side functionality for building rich experiences. If you can withstand the increase in complexity, you can mostly have your cake and eat it too -- server-side rendered robust client applications.
Even for the most stalwart monolith enthusiast, isn't it nice to make it relatively difficult for your View code to call some Model/Controller/util method/function that it shouldn't be calling? If you go through the trouble of committing to separating your "API" and your "frontend server" (there's a trendy name for this which I have forgotten -- "companion" server? BFF?[1]), you get better focused and hopefully more manageable domains.
All that said, portals are a pretty cool new feature, but I'm not going to hold my breath for them to be ready to use any time soon.
[0]: https://bestofjs.org/timeline
[1]: https://docs.microsoft.com/en-us/azure/architecture/patterns...
Insecurity resulting from a lack of proper training.
The browser is so popular as a software distribution method, it now competes with GTK/QT/Cocoa/etc for (large amounts of) "RAMshare" on your neighborhood desktop.
That's very noticeable when you're browsing. It makes the website feel slow. It's very hard to beat that latency if you're going to update everything from the server.
So you really do need JavaScript to create that snappiness. If you're filtering in the browser with the data that you already received, it's going to feel instant.
I purposefully chose the filtering example because it's something that you can do server-side or client-side. But the server side is always going to feel slower if you're sending all the data in each request and simply changing the rendering.
So where do you draw the line? I think you should only let the server re-render the UI if there's new data being queried and sent. I'm of the opinion that JavaScript should only manage the interactivity of what receives and should be fetching very few data.
Of course this only makes sense if you're using something like Laravel or Rails. But even if you are building a SPA and working against a series of endpoints I think you should make an effort to write those endpoints in such way that you're sending as much data as you can in each request and let the client handle it without requesting again just to re-paint the UI.
There are still some cases where I don’t think there’s an obvious answer in the general case. Photo gallery? Product list in webshop?
As the presenter in the video said, browsers can render HTML documents really fast, this leads to some interesting conclusions.
Assume that you need to render a modal as popup for each item in a grid.
Frontend solution would be to reuse the same modal for every item and just swap in the on-the-fly rendered content for that item. Or maybe even on-the-fly create & render the entire modal when needed.
Backend solution would be to render one modal per item. This is actually easier, just loop & have unique ids (you can even reuse the same loop that you build the grid with) & no need for dynamic loading, rendering, etc. So even if you send more HTML down the line, the page acts smother.
That's exactly how this very site we're on right now works, for instance.
https://media.giphy.com/media/anjRJ4nv9WJzO/source.gif
In my experience, any time a web site reimplements basic browser functionality in JavaScript (e.g. loading spinners, scrolling, navigation) it is slow, buggy, and annoying.
The main reason why you shouldn't do it, is because of SEO. Dynamic sites are considered weak in SEO. Very challenging to get them properly indexed by Google etc. You also got still a lot of engineers who somehow favour the serverside rendering. For inhouse internal apps or b2b apps I would always prefer a clientside app.