The mythical “fast” web page
calendar.perfplanet.com
calendar.perfplanet.com
Am currently consulting big ecommerce bussiness on how to improve page load. I made them this 'fastest page in the world' demo: https://turboeshop.com/fastestpageintheworld/ - kindly please check it out. And here is fastest page with Google Analytics: https://turboeshop.com/newstackonly/. 325 ms for fully loaded time CSS + images + HTML + JS + GA loaded + Measurement Protocol hits sent.
This is what fast website is: a) inline purged css; b) everything loaded from one domain, 100% cached. c)inlined js(vanilla + web component if you need one); d) inlined images up to 4kb; e) larger images loaded from cache from same domain. f) gtag.js and analytics.js -> from cache; g) Measurement protocol hits sent from async proxy on edge. h) 100% cloudflare cache hits; i) Cloudflare workers for dynamic bits; That's all what it takes. Don't read articles- just make it fast, it's really that simple :)
And as svelte was mentioned - if you want to improve a website that is bigger than your personal blog, you don't use svelte, react, gatsby or any other of that breed as it's impossible to do serious marketing with a website that's hydrated (svelte's web components is a wonderful thing though and is totally nice addition to marketing stack). I mean no insult to anyone with my strong opinions and would be glad to have discussions in comments.
UPD: Added note on Cloudflare & Cloudflare workers.
Gatsby devs or advocates would argue removing the js removes the preloading of pages that helps make Gatsby faster. Although this is true, in my experience removing hydration is often a better trade off. It of course depends on the site.
Additional benefit: privacy
If you leave out the cookies as well, you don't even need to ask for allowing cookies.
I use this approach for my cryptocurrency portfolio site [1], comments welcome
For speed, also check cryptomarketplot.com - essentially the same techniques
It's a bit ugly but I imagine with some proper CSS the could make it nicer looking but still fast.
The fonts kill it. On my iPad the page had finished loading but I could not see any text until finally the font had finished loading.
Don’t use external fonts!
If I mark "remember my username", and I hit citibank.com, can't the banking back end start fetching my account snapshot when my browser hits / and then send over that data as soon as I authenticate?
I'm out of the loop so maybe this is already done or too complicated?
Obviously you can "cheat" by having a start page with no data or something similar, but that's not what we are trying to achieve
But if the client data is small enough, that wouldn't actually reduce the latency to speed up the page load, if these assumptions hold:
- Getting the decryption key is subject to an authorisation round trip; current data fetch is subject to the same round trip; and the client data is small so sending it takes about the same time as sending the key.
But the round trip can be brought to a minimum by not requiring a large page full of HTML/CSS/JS to be send on auth - just requiring the client data (or key as you suggested).
All the parts which don't depend on client data can be preloaded asynchronously after the login page is shown, including a template for the page ready to be populated when client data is received.
So:
- Make the login page as fast as possible, using inlined data etc. like any static page. Make the page cacheable, probably validated with an Etag. The remembered "your name" field can be populated, that's fine even if it's cached because the browser cache ("Cache-Control:private") is unique to the user.
- Have the login page preload all non-client-data dependent resources for the next page asynchronously, but ensure these don't start fetching until all resources for the login page itself have finished being fetched.
- When password is entered, perform auth and get client data in a single round trip, combine with the templates just loaded to load the new page.
- Use 0-RTT TLS for everything.
Each interaction will be about as fast as possible while validating with the server, but you can go further if you're ok with relaxing that:
- Make the first page load "instant" by changing the cache policy to validate after a timeout instead of just on Etag.
- Asynchronously preload all the resources for the authenticated next page except the client data.
- Make the authenticated next page "instant" by detecting when the user appears to have paused typing in the password field (or immediately without pause if it's refilled by a password manager or user paste into it), and before they hit enter or click submit, send speculative auth requests which return client data if they succeed, but don't treat the user as properly authorised until they do enter/submit. When they do, use the preloaded client data if it's already arrived (and the password field hasn't changed), and also send an auth-confirm request.
You could conceivably pre-render the backend results before hand but then on first load the visiting user would not see her latest transactions --which is a very frequent use case.
As a side note, it's amazing how modern banking sites keep being really fancy interfaces to years old COBOL backends.
A few other things: GZIP and HTTP2 help a lot
I guess both counts. :)
But I agree with you that core problem is that many websites are ACTUALLY slow and bloated.
1. Tailwind CSS classes extracted with purge-css, all inlined.
2. Favicon inlined, small images (<4kb) inlined. Not sure what’s the best threshold. Here is all https://turboeshop.com/inlinedimages/ is all page in one requests. Meaning two big images that are https://turboeshop.com/fastestpageintheworld/ were inlined - results are way worse. So larger images - definitely excluded.
3. Gzip stuff(as one commenter below commented, not done in turboeshop.com/fastestpageintheworld/).
4. Everything from same domain and subdomain. If you want cloudinary or friends, I guess they are only allow subdomain. This is totally OKeish exemption. Or maybe there is a way to work around that cloudinary serves, Cloudflare caches.
5. JS - inlined. Cash.js maybe if you need jquery replacement, or just vanilla. Little content on vanilla js nowadays :), https://gomakethings.com/articles/ is something interesting. Don’t want to flame here, am not js expert, maybe someone can elaborate.
6. For compex components - svelte web components (or stencils or lithtml) - I’d prefer svelte but am not sure what’s best.
7. Google analytics a) - there is new google analytics (GA4) with measurement protocol2 and new server side google tag manager. Serve side gtm does two things a) serves gtag.js; b) accepts measurement protocol hits and sends to GA. Take a look how it’s done - https://www.simoahava.com/gtm-tips/build-custom-universal-an... , it’s very similar as cloudflare workers, cool stuff. But it’s hosted on Google App Engine, thus - slow. But you don't need google's server anymore, you control full infra, so why not setup simple cache here.
8. Google analytics b) To owerome latency to Google App engine, so you make async proxy in cloudflare workers - one worker to proxy for gtag.js download, one for serving gtag.js from your own domain. <script src=“http://yourdomain.com/workers/gtag/js?id=G-1234455> . Basicly just serve from js cache and check every once in a while if google hadn’t changed their code. Same for GA hits. It used to be google-analytics.com/collect endpoint, server side gtm allows to host collection yourself. You again make worker-proxy, define it in gtag’s transport_url:'https://turboeshop.com/measure' setting and make sure worker returns non-blockingly, and just then forward the measurement protocol hit from worker async-ly with event.waitUntil().
9. Google analytics c) The gtag.js/analytics.js is a huge file and you have no control, so maybe just use https://github.com/segmentio/analytics.js instead or check out https://www.thyngster.com/app-web-google-analytics-measureme... (search “navigator.sendBeacon”) - craft measurement protocol yourself and send it to gtm. I plan on investigating this but have not yet done that.
10. All the stuff (fb tracking pixel, etc.) you are used to just ‘putting in html’, you instead send as measurement protocol hit dimension and do ETL in google tag manager.
11. All the 3rd party stuff that demands to be executed client-side - you just don’t use that :D (or use, but wisely)
12. HTML - bussiness as usual.
13. So after page reload - double check if all requests are done/received from your own domain. Use curl on each of them to find header CF-cache-status: HIT. They have this ‘varied’ or similar status which means something I can’t remember, but I always fix stuff till ‘Hit’ :)
14. I guess that’s it. Enjoy your own fastest website in the world :)
Everything about McMaster-Carr's site is built for speed and ease. I can literally have an idea, find the category, identify the specific part, and complete an order in about twenty seconds. (I've done this during a phone call. In the time it took my coworker to articulate the part he was looking for and finish his sentence, I was able to reply "It'll be here tomorrow.")
HomeDepot on the other hand sometimes takes 20 or 30 seconds to render the page to the point that I can see prices. I just checked with a page whose URL was already in my history, an unusually brisk 7 seconds. (Gag!) How do they screw it up so bad? I honestly don't understand how a web page can take so long to do anything.
Access Denied You don't have permission to access "http://www.homedepot.com/" on this server.
Reference #18.669a1702.1607500613.3482d63b
I lol'ed.
For example Safeway, a popular grocery chain, is blocked.
Sometimes the block comes with a scary warning saying that the site has detected a hacking attempt, and stopped your IP at the firewall.
Core library: https://github.com/nfriedly/node-unblocker Example web app: https://github.com/nfriedly/nodeunblocker.com
I don't keep a copy of it online anymore because the ones I put up got a little too popular, but if you don't tell anyone else, you should be able to use it indefinitely.
- EU IP? Blocked.
It's beyond silly.
Having said that, it's just good form to specify why exactly a request was denied rather than spitting out an "access denied" response and call it a day. Be liberal in what you receive, conservative in what you send, yada yada.
It's like I'm querying a well set up database, but without having to type SQL.
Even for professionals you often don’t know what to call a part, but punch in a few words and it “gets” what you’re going for. Add tot hat pretty reliable next day shipping even when ordering at 4pm and it’s not so surprising that Amazon hasn’t eaten them, even though they launched Amazon Industrial like ~7-10y ago
One thing I only realized when living in the US is that the reason that online shopping is so much more advanced in the US than in the EU is not just the more homogeneous market. Due to tax rules (state sales tax on mail orders) mail order has always had a competitive edge in the US, leading to a many companies already being set up with a deep back-catalogue and strong inventory metadata when the internet hit.
I've had great experiences with Gatsby on Netlify in that regard, we've built a number of websites using it. With Gatsby you get the benefits of a React webapp but without the downsides, things like preloading on hover, instant rendering, service workers acting as content caches, etc.
Instead Gatsby just brings its own set of downsides. Gatsby does not scale very well and has horrific dev and build times when it needs to ingest a medium quantity of entries.
The McMaster-Carr mug is an example of marketing done right. It says "we're here to do precisely what you want in exchange for money."
They obviously know how bad their experience is because they throw up an animated splash screen while waiting for their page to load.
I would also shoutout to Mouser for a powerful interface for narrowing down what you want to buy, but its performance does leave something to be desired.
The bigger your website is, the more annoyances you can get away with.
Keep page load to less than 50k, or 100k if you're feeling fancy.
Have a responsive design, unlike this website does, as a lot of people use phones, don't have a PC or are not on a PC.
Don't link everything under the cloud because you can - fonts, frameworks, huge pictures, because it makes your life easier. Self host everything, make it small.
And don't use JavaScript to add an unnecessary layer to 'manage' linking. Clicking on a link is expected behaviour. As are scroll bars. HTML links work perfectly fine and it degrades, nay I say disgraces, user experience.
These basic rubrics will ensure when serving things to 'troublesome' connections, be that bandwidth, blocked 3rd party CDNs or latency, and will largely make sure life will be easier.
Rant incoming - sorry it's been done to death already but I never weighed in before. I will never understand the desire to mess around with custom scrolling on a "normal" page. If you have one of those weird parallax-scrolling visualisations that news sites are often fond of, fine - I don't like them but I understand it's there to present some photography or graphs or whatever in a novel or fancy way. But so many sites that are just serving an article with some pictures override a browser's scroll behaviour in a way that not only adds nothing, but often breaks things. By that I mean it can either just slow or interfere with scrolling in a way that will annoy technical or observant users ... or it can prevent scrolling altogether for a subset of browser/OS or for touch/non-touch users.
But then the warning talks about scroll bars itself.
It's almost impossible not to talk about scroll bars on the web.
It's pointless to make a website ridiculously fast before making the experience as user-hostile as permissible.
https://addons.mozilla.org/en-US/firefox/addon/i-dont-care-a...
Anything that's not required to provide users with the service they're after must either not track them or ask for explicit consent before doing so.
Analytics answer questions like "is this content worth translating", "is that element a good use of screen real estate", "is this browser worth supporting", "how do people find this page (and what are they looking for)". You can't get that out of a feedback form.
> which is not vital
Not every website is run as a charity.
You can have as much design as you like.
Bloated website designs don't need tracking cookies, and tracking cookies are the only type that needs explicit consent.
- Overly-defensive company policies, which ask for consent "just in case"
- A bandwagon effect of "everyone else is doing it"
The first is quite understandable, and has been policy at every company I've worked for/with. One decided to remove all cookies rather than adding a consent popup; the only cookie we used was for "remember me" on login, so we changed the default to false and put a note next to the tick box. Every other company I've worked for/with has decided to add a popup instead; unsurprisingly, they were also setting a whole bunch of tracking and adware cookies.
The problems I have with the "bandwagon" are that (a) popups are more obvious and memorable than not having popups, which biases the bandwagon effect towards the obnoxious behaviour (availability heuristic); and (b) users seeing all these popups think they must be necessary, and misattribute their cause (e.g. thinking GDPR requires them, rather than companies either playing it safe or refusing to stop surveillance).
(If not, than an extension just to find and show the correct decline option when it's cunningly encrypted in a sequence of hidden yes/no/no/no/yes/no type slider options with ambiguously written labels would be nice instead!)
The Website Obesity Crisis https://youtube.com/watch?v=iYpl0QVCr6U
There are thousands of different device-configuration-user possibilities, and for each one you get working, several more you'll never know about will also have an easier time of using your site.
It gets kind of addicting, to be honest. The more browsers I try, the better I get at fixing various compatibility issues and removing all but the absolutely necessary from my pages.
I started out with a pretty minimal design and featureset to begin with, but I've been able to actually expand my compatibility matrix while also adding new features by coding minimally and using "historic" LCD JS for most things.
It's shown me that a) each browser has its beauty and unique features and feel b) most browsers are totally valid access devices and I would like to support them all c) we're at risk of losing all the knowledge of how to build a decent website, and I'd like to preserve that knowledge.
We've built a tool to help measure speed with these sort of issues in mind - https://www.browserstack.com/blog/announcing-speedlab-test-w...
Edit: I’m not trying to overly criticize the page. I hope this is taken in the spirit of the article. A few extra bytes down the wire would’ve made that a much faster and lower friction experience for me.
They should be small (or nonexistent in the case of js), but I believe they should be separate, and proper caching enabled. This means that the first page load may be milliseconds to a second longer, but any other page loads after will be instant since those resources will be pulled from cache.
Note: I am assuming that the web page under load is really small, 50 kb or less.
I welcome anyone who disagrees to say so. I acknowledge that I could still be wrong.
Edit: spelling.
You're never going to be able to overcome physics so you aren't going to somehow make a ten megabyte JavaScript monstrosity load instantly over a spotty 3G connection in the middle of nowhere.
What you can do is give some worst case connection the best chance you can to successfully load your page.
Instead of building it all in the DOM with JavaScript send the client the damn HTML. Send some baseline CSS in a style tag. Use CSS patterns instead of big header images or backgrounds. Use box/text shadows to make elements stand out without images. Bundle as much as possible (CSS sprites, JS bundles, etc) to cut down on external resource requests. Minify and compress the shit out of everything. Include a viewport meta tag.
It's not that difficult to have a good looking and functional page that's literally a single HTML page. A single compressed resource that has everything it needs in a single load.
We're actually in an era where the average web browser is extremely capable and isn't some version of IE. Even super low end Android phones have a very capable browser installed by default. You've got HTML5 and CSS3 along with at least ES6 everywhere. The same is true on the desktop in most areas.
There's also just so much shit you don't need in most pages. Far too many people treat a web page like it's some full blown mini OS. There's also a seeming generation of web devs that have no idea what browsers do and think they need to include the kitchen sink to display some text or load resources. You definitely don't need to override scroll events.
You can never make a universally fast page because you don't control the user's environment. But you can make pages and fast and as light as possible so they're not wasting anyone's time or battery. You can also focus on uncached loads because honestly that's going to be a majority of visits.
To expand on Cthulhu_'s point: I agree with the gist here but I think this is a bit of a simplification. From the user's point of view, fast downloading is only part of the picture. There's also the matter of render time, the dreaded flash of unstyled content, and related irritations such as banners and popups that appear after the page has seemingly finished rendering. (Wikipedia's current fund-raising drive commits this sin, perhaps deliberately.) All of these things contribute to a sense of the page 'getting in your way'. edit Another one for the list: distracting autoplaying videos. The Ars Technica site does this, for instance.
Sites like Pinboard and HackerNews are compact in terms of avoiding bloated JavaScript, but importantly they also stay out of your way in terms of UX.
A 50KB page, about ten pages worth of text (20kb) and the rest markup and CSS, will load in under two seconds on a shitty 3G connection. There will be no unstyled flash and even on super low end devices first paint will happen a fraction of a second after the document finishes loading. You can do a lot of nice styling in 20kb of CSS. You could even include some inline SVG graphics/logo out of that budget.
With compression which every browser supports you've got an even large budget because you can easily see 2:1 compression ratios on text with just GZip.
If you include explicit sizes for things like image and video tags (width and height attributes) the browser won't need to reflow the layout as those resources lazy load in after the page load. There's no popping or things "getting in the way" if you don't write your page like an asshole or pretend you don't know anything about the content ahead of time. Anymore browsers support explicit lazy loading and media source sets. Not using those sorts of features is just laziness or ignorance on the part of web devs.
My first experiences on the Internet were at the end of a shitty dial-up connection with at best a quarter second of latency. Those experiences have stuck with me and I'm appalled and even a bit offended when a "web page" is larger than a copy of Doom. It's especially egregious when a page weighs that much to display a couple paragraphs of text.
Edit: fixed autocorrect typo
You can have a very fancy looking page with a few KB of CSS that will render just fine on even low end modern devices. You'd have to go back almost a decade to find devices that would struggle on such non-demoscene-yet-fancy CSS.
Layout engines in browsers are pretty efficient and a fancy looking page without a bunch of JavaScript churning in the background fucking with the DOM or making a bunch of requests is not that demanding.
The CSS Zen Garden [0] did some fancy ass layouts with CSS 2 and launched in 2003 running on browsers and computers far shittier than today's low end phones and PCs. With CSS3's advancements like transforms, transparencies, and animations there's a lot of effects that can be done entirely in CSS that those old designs needed images to do.
https://www.gsmarena.com/motorola_moto_g7_power-9527.php
3GB of RAM 6.2" screen CPU Octa-core (4x1.8 GHz Kryo 250 Gold & 4x1.8 GHz Kryo 250 Silver) GPU Adreno 506
The battery lasts days, it has an actual compass and it even comes with both a sdcard slot and a headphone jack.
That isn't the lowest of the low but it is 11-16% of the price of a flagship.
on iPhone 6 everything is still pretty responsive.
[1]: https://devdocs.io/dom/serviceworkercontainer/getregistratio... "navigator.serviceWorkers.getRegistrations()"
Full disclaimer, haven't used Wix before, so maybe I'm misunderstanding what it is.
Your usage and content has probably outgrown Wix unless you plan to simply the structure a bit.
I know it's a often a matter of limited time and resources but honestly I would take a bet that more than 50% of the websites you could visit would be unusable or at least functionally unusable without JavaScript.
Hit F12 and go to the Lighthouse tab(?) in dev tools. Very cool!