You really don't need all that JavaScript, I promise

This is the text version of this talk, given by Stuart Langridge at Pixel Pioneers in June 2022

# I said, you really don't need all that JavaScript, I promise.
# The web is HTML, CSS, and JavaScript. But most of a page is HTML, and most of the web is pages. You need the words and the pictures more than you need the colours and the buttons. That's why you were hopefully taught HTML first, then CSS, then JavaScript.
# Some people are taught this the wrong way around; they're taught JavaScript first. Or they reach for javascript first when building the web.
# sometimes this ends up with javascript completely taking over!
HTML + CSS + JavaScript
# but the three are designed to be in balance. If you let JavaScript lead, then it takes over. Let's look at why that might not be a great idea.
First meaningful paint
# Zach Leatherman tested a client-rendered React site displaying a tweet against a plain HTML file rendering a tweet.
…with lots of HTML
# Ah, I read that wrong; he tested a React site rendering a SINGLE tweet against an HTML file containing every single one of his 27,000 tweets. 8.5MB of HTML. Which was faster?
Zach Leatherman / @zachleat / Which has a better First Meaningful Paint time? / ① a raw 8.5MB HTML file with the full text of every single one of my 27,506 tweets / ② a client rendered React site with exactly one tweet on it / (Spoiler: @____lighthouse reports 8.5MB of HTML wins by about 200ms) / 6 Sept 2019
# Let's let Zach speak for himself.
Code highlighting
# Let's take a look at another example: Remy Sharp looked into doing syntax highlighting on server and client.
Although the single HTML file is larger with SSR, total transfer size on the SSR version is ~10K smaller. / There is practically zero impact on parsing time even though we know the parsed HTML is twice the size when SSR is in play. /
# This is because SSR is not sending the two JavaScript prism.js files (prism itself and the additional syntax highlighter).
# It is tempting to outsource a bunch of the work from your computer, which you have to pay for and wait for, to the world's largest distributed supercomputer: the web. But the work doesn't go away; you're just making everyone do it instead of you.
Alex Russell / @slightlylate / The takeaway here is that you literally can't afford desktop or iphone levels of JS if you're trying to make good web experiences for anyone but the world's richest users / 14 Jun 2019
# And their computers are not as good as yours. Phones are mostly rubbish.
…so serve less…?
# I have heard people say: serve less JS and then everything works faster! Fortunately you have a willing partner in this...
The network
# The network hates you and wants you to suffer.
1.1% / of people aren’t getting JavaScript enhancements /
# And then you think, well, 1%, that isn't a big deal. And to be honest, that 1%, I feel sorry for them, but they're not really our target audience anyway. It's lots of effort to make our web app available to everybody, and it's just not worth it. Good idea, but we've got priorities and a backlog. Maybe we'll do it next time.
it’s not like this.
The proportion of people that have explicitly disabled JavaScript or use a browser that doesn't support JavaScript only makes up a small slice of people that don't run JavaScript. /
# Most of the people who didn't get your JS should have done.
# talk through all the ways JS can fail to arrive
it’s like this.
# It's not 1% of people who always can't see your site and 99% of people who always can. It's 1% of visits. Almost all the people who don't get your site correctly actually should have been able to. They don't have JavaScript turned off. They're not browsing on a WAP phone over a 2g connection from a shanty town. They're you, in a cellar bar or a hotel room or waiting for the phone network to wake back up.
or worse, this.
# What if they bailed after a few failures? If you're using a web app and it doesn't work, maybe you'll shrug and hit refresh, or toggle your phone into airplane mode and back out again. But when that happens a second time? A third? A fourth? Will you think "huh, native apps don't do this!" and be annoyed? Maybe you won't, because you're a web developer and you understand the difference between the network failing, the browser failing, and the site failing. You understand the technology.
It’s unnecessarily difficult
# But here's the other thing about the supposedly "modern" web. It's really difficult.
# Can you keep up with all this stuff? It's not just me saying this.
Increasingly, there seems to be a sense of fatigue within our industry. Just / when you think you’ve got a handle on whatever the latest tool or technology is, / something new comes out to replace it. / Drew McLellan,
I've discovered how many others have felt similarly, overwhelmed by the choices / we have as modern developers, always feeling like there's something we should / be doing better. / The web is incredible these days, but I'm not sure every app needs to be a / React-based single-page application, because the complexity is so great in a / product's infancy. / Owen / Williams,
SASS, JavaScript dialects, NPM, and build tools solve some shortcomings with front-end technologies, but at what cost? I’d argue that for every hour these new technologies have saved me, they’ve cost me another in troubleshooting or upgrading the tool due to a web of invisible dependencies. /
In the meantime, I could have broken out any text editor and FTP program and built a full site with plain HTML and CSS in the time it took me to get it all running. And the site would have been easier to maintain in the long-run. /
# That's the key point here. There are two arguments given: that all this stuff makes better sites for users, and that it saves developer time and so means more stuff can be developed. Are either true?
I can still take a complete beginner and teach them to build a simple webpage with HTML and CSS, in a day. We don’t need to talk about tools or frameworks, learn how to make a pull request or drag vast amounts of code onto our computer via npm to make that start. We just need a text editor and a few hours. This is how we make things show up on a webpage. / Rachel Andrew,
# I'm not trying to overwhelm you with similar quotations. The thing here is, these are all notable, smart, motivated people who work professionally on and with and for the web, and they're the ones getting overwhelmed. I bet you feel the same.
go to page 2
# this is a link
var Component = React.createClass({ / getInitialState: function() { return {query: ''} }, / queryChange: function(evt) { / this.setState({query:}); / }, / handleSearch: function() { / window.location = '/search/'+this.state.query+'/some-action'; / }, / render: function() { / return ( / Search / ); } });
# this? don't do this. Use HTML when you can. When you can't... well, we'll get to that.
# Why are we doing all this? Let's take a step back.
component reuse / libraries of existing code / consistent starting point / organisational structure / best practices
# There are reasons. And these are good reasons. This stuff is important.
after the fact
# But these seem like after-the-fact rationalisation to me. Given that we've decided as an industry to use these things, what do we get out of it?
# I think the reason people started inventing client-side frameworks is this: page -> click link -> white screen (or existing screen) -> new page browsers don't do the white screen thing any more (it's called "paint holding"). The way it used to work is that if the new page started loading, the browser would wipe the screen, even if it was taking a long time. Now, the existing page isn't removed until the new page actually sends content.
loss of control
# So you lose control over the user experience. And we don't like that, and we are right to not like it. so people wanted to keep control over that, to give their users a good experience, not this blank screen while they were waiting. Page loads are terrible, right? They must be avoided.
loss of control / fetch() / reuse HTML / virtual DOM / different URLs / client-side routing / framework
# so you say, what if instead of the browser loading the new HTML page, what if I did it? that's easy right? just fetch() the html off the server, then put it in the page myself; no white flash. And then you say, but if some of my HTML is the same... and you invent the virtual DOM. And then you say, but now the URL is different... and you invent client side routing. all because the flash of no content is bad.
# It's a pyramid, one thing built on another.
# But it's a pyramid balanced on one tiny point.
control loading
# What if you could control the experience of new page loads WITHOUT having to reimplement page loading yourself? This is what Shared Element Transitions are for.
# The demo at this point is available in three steps: see the first step. The "demo" links along the top move between the three stages. Note that, at time of writing in June 2022, the shared element transition API, which this demo uses, only works in Chrome Dev/Canary. Click the "Stuart Langridge" link to show a transition, in each step of the demo.
const transition = document.createDocumentTransition(); / await transition.start(async () => { / // do whatever you want here / });
# transition.start TAKES A PICTURE of the screen and shows it! It freezes the page.
# This is like how in a 9am Zoom meeting you can set a picture of yourself to show as your camera, and then everyone thinks you're there and really you're making a cup of tea and you've still got a dressing gown on. If any of my clients are here, I have never done that.
# Really think of this like the curtain on a stage. It takes a screenshot of the page, and displays that screenshot. You can then do whatever you like to the page behind the scenes, like load a new page, or change the DOM in this one, and then when you're done, you use CSS animations like you normally would to remove the screenshot and show the new look.
/* default CSS */
# by default you don't have to do ANYTHING. You get a free "fade" from one to the other. That was the first demo I showed, when one page faded into the next. Create a transition and that's it!
::page-transition-outgoing-image(root) { / animation-duration: 2500ms; / }
# but because it's CSS you already know how to change how the animation works. here page-transition-outgoing-image is the screenshot of the page before the transition. So you can animate it how you want: this is how I made the fade go slower.
::page-transition-outgoing-image(root), / ::page-transition-incoming-image(root) { / animation: 500ms ease-out both slide-to-left; / } / @keyframes slide-to-left { / to { / transform: translateX(-100%); / } / }
# and if you wanted the page to slide to the side, you'd use css to do that instead! this is all stuff you already know how to do! different animations, media queries so it works differently on mobile screens, you already know this!
#stuart-schedule-img, #stuart-description-img { / page-transition-tag: animate-my-image; / contain: paint; / }
# and then the other demo, where the image animated separately... what you do is add a page-transition-tag, and then all the stuff with that tag gets a SEPARATE animation. And by default that separate one animates position and size, so the image moved and I didn't have to do ANYTHING. /“Bringing page transitions to the web”, YouTube)
# see the explainer on github; watch Jake Archibald's talk at IO 2022.
# unfortunately now we have to look at the truth. It's Chrome only, and it's SPA only. For now.

but this solves a real problem.
# Most of the time, perhaps, you only want to add some “sprinkles of interactivity” to an existing page. The majority of websites aren’t, and don’t need to be, single-page apps. It's not me saying that, it's REACT saying that. "React has been designed from the start for gradual adoption, and you can use as little or as much React as you need."
# A page which uses Vue components (don't want to go on about just React). Vue doesn't control the page, it just augments it.
Meeting avoidance system / Negative / <script src="vue-status-indicator.min.js">>/script> / <script> / for (let el of document.querySelectorAll("td.status")) { / new Vue({el: el, / components: { VueStatusIndicator: VueStatusIndicator } / }); / } / </script>
HTML: smarter than it used to be
# And HTML on its own does a lot of stuff now that used to have to be built by hand as components. Beware that some people who've been in web development for a little while may remember days when HTML could not do this, and not have learned that now it can, so they may reach for JavaScript components that aren't needed, and then try to justify that afterwards.
<datalist> / <input list="thelist"> / <datalist id="thelist"> / <option>Everyone else</option> / <option>Stuart</option> / </datalist> / Best speaker? / Stuart / Rachel / Rachel! / no, Rachel / really it's Rachel
<fieldset disabled> / disable/enable / Oranges / Apples
CSS scroll-snap / parent { scroll-snap-type: y mandatory; } / child { scroll-snap-align: start; }
# It's not that these are super-revolutionary. It's that each of these things would have a while back required a bunch of JS enhancement and now they don't. But I am not saying to not use JavaScript!
Ana Tudor / @anatudor / Just because you don't understand a simple little CSS solution, it doesn't mean / it's "weird"/ "crazy". Goes the other way as well. Adding a ton of extra elements / just for the sake of having a pure CSS solution when updating a value from the / JS would suffice is just silly. / 14 Sept 2019
# Be sensible! I'm not saying don't use JS! JS is the programming language of the web. It's great. I love it. Don't avoid it! Just don't necessarily let it run everything.
stay in touch
# it's good to stay in touch with the latest tricks. we are in a fast moving industry. but stay in touch with all the ones that are relevant to your job. HTML, and CSS, and JavaScript.
flaki / @slsoftworks / Not knowing stuff is normal. / Not using new and shiny tech is okay. / Feeling bad for all of these is common. / You are not alone. / But you are also completely and perfectly fine, and / you / are / adequate. / 💖 / 15 Sept 2019
# or don't.
fight the good right fight
# don't fight against the web. There's so much in our industry and in the rest of the world that needs fighting. So many ways we need to stand in solidarity with one another and the world. So many people who need your help. If you want to fight, great. Don't fight the web.
the great thing about standards
# frameworks are a great thing to prototype stuff before the web gets it takes a long time to standardise; they make sure that everyone's included, accessibility is good, performance is good. That takes time.
the leading edge
# so use extra stuff if you need things that aren't in the web platform yet but if you're ALWAYS doing stuff that isn't in the web platform yet, is that really right? are you honestly always on the bleeding edge? to make a login form? seriously?
It’s valuable, what we do as an industry. / We have the power to bring knowledge to the whole world. / To connect people together (when they want it), / to be the greatest repository of information that’s ever been known.
That’s what the web is for. / To connect people together when they want it, and / to be the greatest repository of information that’s ever been known. / Let’s keep it that way.
# let's keep it that way, all of us.