How we improved our website's performance
smashingmagazine.com
smashingmagazine.com
Is reducing the total amount of CSS per page so you don't have to calculate the critical CSS at all an option?
To throw my own page into the ring, here's a non-trivial product website of mine where the homepage is 0.3MB total over the wire and renders in 0.4 seconds for me (includes custom fonts, payments, analytics, large screenshot and real-time chat widget):
The major tricks I'm using is keeping the website CSS small (CSS for homepage + rest of site gzips to less than 8KB), inlining all CSS, rendering default fonts before the custom font has loaded, SVG for all images (this saves a ton), and not using JavaScript for content (which blocks rendering).
The screenshot in the header is in SVG format and inlined directly into the page along with the CSS, so the moment the HTML arrives the browser can display all above the fold content. Logos are another good one for the SVG + inline treatment.
Have you considered inlining CSS in the head (as you've done), but then serving it again with a linked css file just before </body>.
Then, with subsequent page loads (of the current or other pages), you don't have to inline any CSS anymore.
Of course this requires that you serve two versions of all your pages, one for if that page is a first hit, and another to be served to users who already have your CSS cached.
I believe that shaving a few additional kb from this already low number isn't worth the proposed complexity.
But this is a tradeoff that everybody has to decide for themselves.
If that's the argument, why not just let them take the (tiny) initial 8kb hit as an external css file, and make the rest of the experience even "zippier"?
One reason is Google will likely ding your Core Web Vitals score for it, which is becoming a ranking signal in May this year (https://developers.google.com/search/blog/2020/11/timing-for...) so you have less of a choice here for what you prioritise.
But haven't tested that yet.
> You're gaining a great first impression at the cost of a poorer experience for every subsequent page load.
Yep, it's unfortunate we still have to make tradeoffs like this. At least in this case, it's less than 8KB added per page vs something more complicated that might break.
HTTP push was getting closer to offering some alternative like what you're suggesting (the server pushes the CSS file to the client in parallel to the initial HTML page, and the client can say if it already has the CSS file) but it's being deprecated now.
The vast majority of users will visit one and only one page.
The big wins are: don't require JS for any content in the page header, use minimal CSS + inline it, strongly prefer SVG images over bitmaps + inline them, use "font-display: swap" + go easy with how many fonts you need.
Do you folks know the entertaining talk http://idlewords.com/talks/website_obesity.htm?
The main trick is to view your web app in a browser, print to PDF and then use Inkscape to auto convert from PDF -> SVG (with some caveats). Worst case you could recreate the screenshot from scratch in a vector editor.
The SVG icons are licensed from https://icons8.com/ (recommended!).
In my browser, I see 1.75 MB sent over the wire and a 2.5 second load time. My big pages of text [1] need 105 kB and load in 0.4 seconds. Their compressed critical CSS is the same size as my entire uncompressed CSS file. They send more CSS bytes than I send bytes in total.
If you want to make a content website fast, it's quite simple: send just the content.
[1] https://allaboutberlin.com/guides/german-health-insurance
FWIW, it does load in an instant for me. (Lighthouse Performance = 99, Speed Index = 0.4s.)
How do people come up with this shit?
- fonts can be unnecessarily huge
- monolithic js = slow. Chunk at build time.
- content-visibility: auto for lazy rendering
The e-commerce platform Magento 2 is packed with this kind of bullshit and is part of the reason my colleagues and I abandoned it for our clients' large e-commerce websites:
https://magento.stackexchange.com/questions/104583/magento-2...
https://old.reddit.com/r/Magento/comments/bli7vz/seriously_w...
https://magento.stackexchange.com/questions/277544/page-load...
https://magento.stackexchange.com/questions/270553/is-it-pos...
OK, that basically describes any kind of software development, but web seems so much worse than anything else. And I say that as someone doing mainly Java backend development who's learned to live with the AbstractProxyFactoryManagerFactory jokes.
Sending reasonably well visually formated text is definitely a reasonable demand though.
As a for instance you your script tag can just include a bunch of @import statements. Thankfully @import statements support media queries [0]. So you get the utility of external style sheets but can load one optimized for the client device. Unlike media queries on link tags the browser doesn't load style sheets (well they're not supposed to) that don't match the media queries.
It's also trivial to include a tiny bit of base styling with every page in a script tag. It doesn't blow any size budgets and makes sure a page is readable even with no external assets.
[0] https://developer.mozilla.org/en-US/docs/Web/CSS/@import
What's the first thing most people do when starting a new project? They ask "what framework should I build this on?" and start their tiny portfolio site built upon a massively overpowered suite of enterprise-level software with a million features they'll never, ever need.
Then they might drop in ten or fifteen separate external libraries because using vanilla HTML, CSS, and JavaScript is just "so 1995".
Then they start thinking about AJAX and microservices because rendering an entire page on the server side is utterly unthinkable in 2021.
Then they cram the site full of third-party services (because your tiny home-brew website will definitely benefit from Newrelic monitoring).
Then they might start on unit testing.
Finally they package everything up using at least seven different dependency managers, because a Github project without 100 useless ancillary files (grunt.js, app.yaml, travis.yml, composer.json, .gitignore, etc. etc.) is obviously not acceptable.
And this is why I hate modern web development.
Quite the opposite. It needs to be hammered into people. Your app isn't Notion or Google Docs. Your app is a form with a login menu and a couple of small logic elements and a date picker.
I really can't understand why so many people rag on frontend development as if we (as frontend developers) are just magpies who gather shiny things and don't care about performance or simplicity.
May be you should try to listen to them more carefully and make an attempt to understand their woes.
Guess what, I'm not picking Spring to make a simple REST api when it takes 5 lines in Expressjs. Why? Spring is complete overkill. So along those lines, should you use React/Redux/Redux-{Thunk,Promise,Observable}/Navigation/etc if you need a simple 2 page site? NO! Jesus christ, you pick the right tool for the right job.
There's a reason though, when you have a highly complex app with insane business rules (that could very well be hidden from the airmchair HN crowd) where you need that complexity. And guess what, if you're highly versed in these "complex" frontend tools (spoiler: they're not complex), then it makes building sites, generally, very easy.
So go ahead, believe what you want and continue to parrot the "the frontend ecosystem is hopeless, needlessly complex and godless" while the rest of us continue developing with these "complex" tools because they make our lives as developers easier.
I'll sleep happy while you wait that one more second for the page to load.
I think what most people are frustrated about with the frontend ecosystem (And many other areas of software) is actually misuse of tools.
For myself, I would appreciate more such takes.
Nice write up but not a big surprise to anyone that blocks analytics tracking, ads, and third party embeds.