Six years old. Still very astute. Still very true.
Tuesday, March 30th, 2021
Thursday, March 11th, 2021
It’s official. The extremely niche browser behaviour I documented is a bug.
When service workers met framesets
Oh boy, do I have some obscure browser behaviour for you!
To set the scene…
I’ve been writing here in my online journal for almost twenty years. The official anniversary will be on September 30th. But this website has been even online longer than that, just in a very different form.
Here’s the first version of adactio.com.
Like a tour guide taking you around the ruins of some lost ancient civilisation, let me point out some interesting features:
- Observe the
.shtmlfile extension. That means it was once using Apache’s server-side includes, a simple way of repeating chunks of markup across pages. Scientists have been trying to reproduce the wisdom of the ancients using modern technology ever since.
- See how the layout is
100vh? Well, this was long before viewport units existed. In fact there is no CSS at all on that page. It’s one big
tableelement with 100% width and 100% height.
- So if there’s no CSS, where is the
border-radiuscoming from? Let me introduce you to an old friend—the non-animated GIF. It’s got just enough transparency (though not proper alpha transparency) to fake rounded corners between two solid colours.
if (navigator.appName == "Netscape")
Note that these are not iframes, they are frames. Different thing. You could create single page apps long before Ajax was a twinkle in Jesse James Garrett’s eye.
If you view source, you’ll see a React-like component system. Each
frameset component contains
frame components that are isolated from one another. They’re like web components. Each frame has its own (non-shadow) DOM. That’s because each frame is actually a separate web page. If you right-click on any of the frames, your browser should give the option to view the framed document in its own tab or window.
Now for the part where modern and ancient technologies collide…
If you’re looking at the frameset URL in Firefox or Safari, everything displays as it should in all its ancient glory. But if you’re looking in Google Chrome and you’ve visited adactio.com before, something very odd happens.
Each frame of the frameset displays my custom offline page. The only way that could be served up is through my service worker script. You can verify this by opening the framest URL in an incognito window—everything works fine when no service worker has been registered.
I have no idea why this is happening. My service worker logic is saying “if there’s a request for a web page, try fetching it from the network, otherwise look in the cache, otherwise show an offline page.” But if those page requests are initiated by a
frame element, it goes straight to showing the offline page.
Is this a bug? Or perhaps this is the correct behaviour for some security reason? I have no idea.
I wonder if anyone has ever come across this before. It’s a very strange combination of factors:
- a domain served over HTTPS,
- that registers a service worker,
- but also uses framesets and frames.
I could submit a bug report about this but I fear I would be laughed out of the bug tracker.
Still …the World Wide Web is remarkable for its backward compatibility. This behaviour is unusual because browser makers are at pains to support existing content and never break the web.
Technically a modern website (one that registers a service worker) shouldn’t be using deprecated technology like frames. But browsers still need to be able support those old technologies in order to render old websites.
This situation has only arisen because the same domain—adactio.com—is host to a modern website and a really old one.
Maybe Chrome is behaving strangely because I’ve built my online home on ancient burial ground.
It’s all to do with navigation preloads and the value of
event.preloadResponse, which I believe is only supported in Chrome which would explain the differences between browsers.
According to this post by Jake:
event.preloadResponse is a promise that resolves with a response, if:
- Navigation preload is enabled.
- The request is a GET request.
- The request is a navigation request (which browsers generate when they’re loading pages, including iframes).
event.preloadResponseis still there, but it resolves with
Notice that iframes are mentioned, but not frames.
My code was assuming that if
event.preloadRepsonse exists in my block of code for responding to page requests, then there’d be a response. But if the request was initiated from a frameset, it is a request for a page and
event.preloadRepsonse does exist …but it’s undefined.
I’ve updated my code now to check this assumption (and fall back to
This may technically still be a bug though. Shouldn’t a page loaded from a frameset count as a navigation request?
Friday, February 26th, 2021
One of the other arguments we hear in support of the SPA is the reduction in cost of cyber infrastructure. As if pushing that hosting burden onto the client (without their consent, for the most part, but that’s another topic) is somehow saving us on our cloud bills. But that’s ridiculous.
Thursday, February 11th, 2021
The problem with developing front end projects isn’t that it’s harder or more complicated, it’s that you made it harder and more complicated.
Web development did not change. Web development grew. There are more options now, not different options.
You choose complexity. You can also choose simplicity.
Wednesday, February 10th, 2021
I can relate to the sentiment.
Starting a new project? Make sure to write your project idea down because by the time you are finished setting up the vast boilerplate you have probably forgotten it.
Monday, January 25th, 2021
You catch more flies with honey than Tailwind.
Monday, January 18th, 2021
The juxtaposition of The HTTP Archive’s analysis and The State of JS 2020 Survey results suggest that a disproportionately small—yet exceedingly vocal minority—of white male developers advocate strongly for React, and by extension, a development experience that favors thick client/thin server architectures which are given to poor performance in adverse conditions. Such conditions are less likely to be experienced by white male developers themselves, therefore reaffirming and reflecting their own biases in their work.
Wednesday, December 23rd, 2020
This is great! The folks at Basecamp are releasing the front-end frameworks they use to build Hey. There’s Turbo—the successor to Turbolinks:
It offers a simpler alternative to the prevailing client-side frameworks which put all the logic in the front-end and confine the server side of your app to being little more than a JSON API.
With Turbo, you let the server deliver HTML directly, which means all the logic for checking permissions, interacting directly with your domain model, and everything else that goes into programming an application can happen more or less exclusively within your favorite programming language. You’re no longer mirroring logic on both sides of a JSON divide. All the logic lives on the server, and the browser deals just with the final HTML.
Yes, this is basically Hijax (which is itself simply a name for progressive enhancement applied to Ajax) and I’m totally fine with that. I don’t care what it’s called when the end result is faster, more resilient websites.
Compare and contrast the simplicity of the Hotwire/Turbo approach to the knots that React is tying itself up in to try to get the same performance benefits.
Wednesday, October 28th, 2020
Portals and giant carousels
I posted something recently that I think might be categorised as a “shitpost”:
Most single page apps are just giant carousels.
Extreme, yes, but perhaps there’s a nugget of truth to it. And it seemed to resonate:
I’ve never actually seen anybody justify SPA transitions with actual business data. They generally don’t seem to increase sales, conversion, or retention.
For some reason, for SPAs, managers are all of a sudden allowed to make purely emotional arguments: “it feels snappier”
If businesses were run rationally, when somebody asks for an order of magnitude increase in project complexity, the onus would be on them to prove that it proportionally improves business results.
But I’ve never actually seen that happen in a software business.
A single page app architecture makes a lot of sense for interaction-heavy sites with lots of state to maintain, like twitter.com. But I’ve seen plenty of sites built as single page apps even though there’s little to no interactivity or state management. For some people, it’s the default way of building anything on the web, even a brochureware site.
It seems like there’s a consensus that single page apps may have long initial loading times, but then they have quick transitions between “pages” …just like a carousel really. But I don’t know if that consensus is based on reality. Whether you’re loading a page of HTML or loading a chunk of JSON, you’re still making a network request that will take time to resolve.
Leaving aside the fact that is literally what the browser cache takes of, I’ve seen some circular reasoning around this:
To be fair, in the past, the experience of going from page to page used to feel a little herky-jerky, even if the response times were quick. You’d get a flash of a white blank page between navigations. But that’s no longer the case. Browsers now perform something called “paint holding” which elimates the herky-jerkiness.
So now if your pages are a reasonable size, there’s no practical difference in user experience between full page refreshes and single page app updates. Navigate around The Session if you want to see paint holding in action. Switching to a single page app architecture wouldn’t improve the user experience one jot.
This is the problem that Jake set out to address in his proposal for navigation transitions a few years back:
Having to reimplement navigation for a simple transition is a bit much, often leading developers to use large frameworks where they could otherwise be avoided. This proposal provides a low-level way to create transitions while maintaining regular browser navigation.
I linked to Jake’s excellent proposal in my shitpost saying:
But then I added—and I almost didn’t—this:
Now you might be asking yourself what Paul said out loud:
Excuse my ignorance but… WTF are portals!?
Portals are a proposal from Google that would help their AMP use case (it would allow a web page to be pre-rendered, kind of like an iframe).
That was based on my reading of the proposal:
…show another page as an inset, and then activate it to perform a seamless transition to a new state, where the formerly-inset page becomes the top-level document.
It sounded like Google’s top stories carousel. And the proposal goes into a lot of detail around managing cross-origin requests. Again, that strikes me as something that would be more useful for a search engine than a single page app.
But Jake was not happy with my description. I didn’t intend to besmirch portals by mentioning Google AMP in the same sentence, but I can see how the transitive property of ickiness would apply. Because Google AMP is a nasty monopolistic project that harms the web and is an embarrassment to many open web advocates within Google, drawing any kind of comparison to AMP is kind of like Godwin’s Law for web stuff. I know that makes it sounds like I’m comparing Google AMP to Hitler, and just to be clear, I’m not (though I have myself been called a fascist by one of the lead engineers on AMP).
Clearly, emotions run high when Google AMP is involved. I regret summoning its demonic presence.
After chatting with Jake some more, I tried to find a better use case to describe portals. Reading the proposal, portals sound a lot like “spicy iframes”. So here’s a different use case that I ran past Jake: say you’re on a website that has an iframe embedded in it—like a YouTube video, for example. With portals, you’d have the ability to transition the iframe to a fully-fledged page smoothly.
But Jake told me that even though the proposal talks a lot about iframes and cross-origin security, portals are conceptually more like using
rel="prerender" …but then having scripting control over how the pre-rendered page becomes the current page.
Put like that, portals sound more like Jake’s original navigation transitions proposal. But I have to say, I never would’ve understood that use case just from reading the portals proposal. I get that the proposal is aimed more at implementators than authors, but in its current form, it doesn’t seem to address the use case of single page apps.
we haven’t seen interest from SPA folks in portals so far.
I’m not surprised! He goes on:
Maybe, they are happy / benefits aren’t clear yet.
From my own reading of the portals proposal, I think the benefits are definitely not clear. It’s almost like the opposite of Jake’s original proposal for navigation transitions. Whereas as that was grounded in user needs and real-world examples, the portals proposal seems to have jumped to the intricacies of implementation without covering the user needs.
I guess the web I want includes giant carousels.
Friday, October 16th, 2020
Monday, September 28th, 2020
A great presentation on taking a sensible approach to web development. Great advice, as always, from the blogging machine that is Chris Ferdinandi.
The web is a bloated, over-engineered mess. And, according to developer and educator Chris Ferdinandi, many of our modern “best practices” are actually making the web worse. In this talk, Chris explores The Lean Web, a set of principles for a simpler, faster world-wide web.
Tuesday, September 22nd, 2020
Sunday, August 30th, 2020
The radioactive properties of React.
Wednesday, August 19th, 2020
Monday, August 17th, 2020
Mind the gap
In May 2012, Brian LeRoux, the creator of PhoneGap, wrote a post setting out the beliefs, goals and philosophy of the project.
The beliefs are the assumptions that inform everything else. Brian stated two core tenets:
- The web solved cross platform.
- All technology deprecates with time.
That second belief then informed one of the goals of the PhoneGap project:
The ultimate purpose of PhoneGap is to cease to exist.
Last week, PhoneGap succeeded in its goal:
Since the project’s beginning in 2008, the market has evolved and Progressive Web Apps (PWAs) now bring the power of native apps to web applications.
Today, we are announcing the end of development for PhoneGap.
I think Brian was spot-on with his belief that all technology deprecates with time. I also think it was very astute of him to tie the goals of PhoneGap to that belief. Heck, it’s even in the project name: PhoneGap!
I recently wrote this about Sass and clamp:
jQuery is the perfect example of this. jQuery is no longer needed because cross-browser DOM Scripting is now much easier …thanks to jQuery.
Successful libraries and frameworks point the way. They show what developers are yearning for, and that’s where web standards efforts can then focus. When a library or framework is no longer needed, that’s not something to mourn; it’s something to celebrate.
That’s particularly true if the library of code needs to be run by a web browser. The user pays a tax with that extra download so that the developer gets the benefit of the library. When web browsers no longer need the library in order to provide the same functionality, it’s a win for users.
In fact, if you’re providing a front-end library or framework, I believe you should be actively working towards making it obselete. Think of your project as a polyfill. If it’s solving a genuine need, then you should be looking forward to the day when your code is made redundant by web browsers.
One more thing…
I think it was great that Brian documented PhoneGap’s beliefs, goals and philosophy. This is exactly why design principles can be so useful—to clearly set out the priorities of a project, so that there’s no misunderstanding or mixed signals.
If you’re working on a project, take the time to ask yourself what assumptions and beliefs are underpinning the work. Then figure out how those beliefs influence what you prioritise.
Ultimately, the code you produce is the output generated by your priorities. And your priorities are driven by your purpose.
You can make those priorities tangible in the form of design principles.
You can make those design principles visible by publishing them.
Friday, July 31st, 2020
Smashing Podcast Episode 21 With Chris Ferdinandi: Are Modern Best Practices Bad For The Web? — Smashing Magazine
I really enjoyed this interview between Drew and Chris. I love that there’s a transcript so you can read the whole thing if you don’t feel like huffduffing it.
Saturday, July 18th, 2020
A good explanation of the hydration problem in tools like Gatsby.
Sunday, May 17th, 2020
This is a very clear description of the differences between libraries and frameworks, along with the strengths and weaknesses of both.
A library is a set of building blocks that may share a common theme or work well together, but are largely independent.
A framework is a context in which someone writes their own code.
I very much agree with the conclusion:
If your framework can be a library without losing much, it probably should be.
Wednesday, May 13th, 2020
Reef is an anti-framework.
It does a lot less than the big guys like React and Vue. It doesn’t have a Virtual DOM. It doesn’t require you to learn a custom templating syntax. It doesn’t provide a bunch of custom methods.
Reef does just one thing: render UI.