-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
[feat] inlineCss
option
#2620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feat] inlineCss
option
#2620
Conversation
🦋 Changeset detectedLatest commit: 96e824b The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Is the term for this really |
Well, the main reason people want this feature is getting a low score on PageSpeed Insights/Lighthouse. Loading CSS blocks rendering and the site gets a low First Contentful Paint score. Then Lighthouse recommends:
In web.dev's Eliminate render-blocking resources article (Learn more link):
They are using Of course, inlining CSS can mean style attribute of an element. But docs can be written like "inline css inside a |
Co-authored-by: Ben McCann <[email protected]>
Thinking out loud here: is this option granular enough? Will people always have this kind of either-or situation? Wouldn't people instead have some critical styles which should be inlined and then other styles loaded through css normally? |
A simple boolean toggle for everything isn't a good general purpose solution for MPA. The second page re-downloads all css because it cannot be used from the cache. So instead of inlining everything it would be better to only inline critical css to allow fast rendering above the fold without layout shift and continue to serve everything via css file - which would still result in more total bytes transferred, but not the whole css and it keeps caching viable. there are 3rd party solutions like https://github.com/nystudio107/rollup-plugin-critical, which may be used to automate this. Optimizing css itself is only the fist step too, adding prefetch hints for images referenced by critical css, preconnect to cdn, embedding the font (There are even tools to build a custom font only carrying the chars used on the page), ... there are so many things you can to to etch out a little more speed - only to have it ruined by a "mandatory" background video to make it "look cool" or a gazillion of tracking scripts 🙈. In the end an optimized first visit page should carry little critical weight so that deferred bigger resources like script and style can be downloaded while the user is still busy starting the first interaction. I wonder if instead of this boolean we could add stats/information on the sizes of entry pages, similar to bundle sizes reported by build, but at a page level, with separate thresholds and accompanied by documentation on how improve the sizes. edit: there was a little bit of discussion about this on vite discord too https://discord.com/channels/804011606160703521/804067627852365845/868824287459549214 |
Caching is still viable, because all CSS is bundled in JS files. The first page (SSR/prerendered HTML) includes inlined CSS. When Svelte hydrates the page, it downloads JS files which include CSS styles. Then it replaces inlined CSS with the styles from the JS files. When the second page requested, Svelte downloads JS files which include CSS styles. HTML response is only used on first page. If JS files are cached, styles are cached too. The problem with inlining only above the fold content is depending on the Next.js' |
✔️ Deploy Preview for kit-demo canceled. 🔨 Explore the source changes: bc79b0a 🔍 Inspect the deploy log: https://app.netlify.com/sites/kit-demo/deploys/61d57727d5f4ec00081a06a0 |
Thanks — have updated this PR so that it's once again in a mergeable state. In principle I'm in favour of this change (though I wonder if it should be a threshold rather than a toggle — if one page had a very large amount of CSS, you might want that page to use Unfortunately there's one major problem. If you visit a page that has styles from components A, B and C, you'll have this... <style>
/* A */
/* B */
/* C */
</style> ...then if you navigate to a page that has components B, C and D you'll get this: <style>
/* A */
/* B */
/* C */
</style>
<link rel="stylesheet" href="/assets/B.css">
<link rel="stylesheet" href="/assets/C.css">
<link rel="stylesheet" href="/assets/D.css"> If you then navigate back to the first page, you'll load A again. In contrast, when styles are always included as links, the first navigation will only load D, and the second navigation won't load anything at all. Aside from resulting in faster navigation and less wasted bandwidth, this also prevents a situation where the CSSOM is cluttered with duplicated selectors. The CSS loading is done by Vite here — here's where it checks to see if styles are already in the page. I'm not sure what the best solution to this is. Perhaps we include the links as well as the |
✔️ Deploy Preview for kit-demo canceled. 🔨 Explore the source changes: 96e824b 🔍 Inspect the deploy log: https://app.netlify.com/sites/kit-demo/deploys/61de03930691ed0009ac6a8e |
What's the unit in |
fixes #962
Before submitting the PR, please make sure you do the following
Tests
pnpm test
and lint the project withpnpm lint
andpnpm check
Changesets
pnpx changeset
and following the prompts. All changesets should bepatch
until SvelteKit 1.0