Skip to content
This repository has been archived by the owner on Jun 2, 2022. It is now read-only.

[FSSS-143] Chore: remove unused css (spike) #244

Closed
wants to merge 7 commits into from

Conversation

eduardoformiga
Copy link
Member

@eduardoformiga eduardoformiga commented Jan 17, 2022

What's the purpose of this pull request?

This PR aims to apply some experiments in order to deal with critical CSS, unused CSS, code-splitting.

Edit Note:
The code from this PR was also added on f7ae9c8 on #241. so that we can solve the unused CSS problem there.
So this PR here becomes a study case that we can visit as necessary in the future :)

Context

Lighthouse (LH) started complaining about unused css:

✘ unused-css-rules failure for maxLength assertion
Reduce unused CSS
https://web.dev/unused-css-rules/

Nowadays:

  • Using the build command (yarn build), the CSS from all pages and components are injected inside each page, minified, inside a <style> tag in the <head>. Thus, the browser avoids one more request to fetch a CSS file.

Screen Shot 2022-01-17 at 11 46 12

  • Locally, using develop mode (yarn develop) everything is extracted into a CSS file (commons.css) and imported using <link> in the <head>. This function is the function of webpack's mini-css-extract-plugin.

Screen Shot 2022-01-17 at 13 27 24

Problem

All the CSS is being injected into pages globally, even unused ones.

This is a known issue in Gatsby.
In the v2 version, a technique called code-splitting CSS was used, I imagine that the CSS of each component/page was separate, and only what was used was imported into the pages. But this proved to be problematic #11072.

So in v3, which is the version we are using now, code splitting has become optional and needs to be done manually and all CSS is placed globally on each page as mentioned earlier. Thus, we need to at least scope the CSS so that we don't have either style breaking or unexpected behavior. This generates a lot of unused CSS on the pages. Also known issue #28046#21728#18732 .

Techniques and tools

The technique recommended by web.dev:

Inline critical CSS and defer non-critical CSS

references: #1, #2, #3

Screen Shot 2022-01-21 at 18 43 31

There are some tools and plugins to do this. But we need to know if it matches well with the gatsby/webpack stack and test:
criticalhtml-critical-webpack-plugin.

Another technique is to remove unused CSS, using something like PurgeCSS, which also has gatsby-plugin-purgecss for gatsby.

There is also another technique known as tree-shaking (#4#5).

Screen Shot 2022-01-21 at 18 45 04

css-modules doesn't solve our problem. I did some tests too and what it does is scope our classes well. It uses a hash for this. The final markup is a little worse to read but it solves the class collision problem. It might be a future approach, nowadays we scope using BEM + data-attributes. The css-modules is very class-focused, we would have to adapt the data-attributes, for example. It would solve the collision problem but not the unused CSS problem.

This repository lists some css-in-js techniques. styled-components solves our problem, but I don't particularly like how the final hashed markup looks. We would have to adapt a lot of things in our CSS too.

I think it's worth doing some experiments and trying to adapt the rules of webpack from gatsby like this. Although understanding the initial configuration that gatsby does is a bit tricky.

CSS splitting

commit: 5dc155b
CSS coverage after this Webpack setup:

Before After
Screen Shot 2022-01-17 at 15 58 56 Screen Shot 2022-01-17 at 16 53 24

✅ Code splitting CSS with only the global CSS and the page CSS. Does not include the other page's CSS.

CSS splitting + Critical CSS

commit: 9d00e97
Testing critical CSS only on homepage.
inline critical above the fold CSS and defer uncritical below the fold css

Result: it's not possible to test in the preview environment since we need the puppeteer installed.

Preview Build failed:

error UNHANDLED REJECTION Failed to launch the browser process! spawn /workspace/build/chore/remove-unused-css/vtex-sites/base.store/node_modules/puppeteer/.local-chromium/linux-722234/chrome-linux/chrome ENOENT

Locally:

Screen Shot 2022-01-19 at 21 16 19

❌ Drawback:

  • Lots of unused CSS but only in external CSS files (inside <link rel="stylesheet">).
  • Inlined CSS is not cached.
  • Lots of manual configs. We need to apply this for all static files for instance and we don't know beforehand all the filenames.
  • We need to install the puppeteer in CI.

✅ The critical CSS was applied inline and has a good CSS used rate, but some duplicated CSS needs to be removed yet (from the page's CSS).

CSS splitting + PurgeCSS

commit: 8b08fd3

Screen Shot 2022-01-20 at 13 40 29

❌ PurgeCSS does not support attribute (like data-attributes) or complex selectors: Issue #110.
✅ When we just purge the global.scss we gain almost nothing +- (0,5kb).

CSS splitting + Custom Loaders

❌ Attempts to optimize our CSS with custom loaders like dropCSS, clean-css, CSSO, but the final result doesn't have much difference in the final result.

CSS splitting + Tree shaking.

commit: 8f1b57d

❌ Testing with sideEffects as true, false, and using either loaders or inside the package.json broke the style or doesn't have much difference in the final result.

Conclusion

Let's just keep the code splitting CSS with scoped CSS so far. This technique brings more gains without cumbersome other configs/techniques that bring less for our context.

References

https://www.notion.so/vtexhandbook/WIP-Gatsby-Webpack-Global-CSS-problem-203c96c86bcd48fb930c3d053756fda4

@vtex-sites
Copy link

vtex-sites bot commented Jan 17, 2022

Preview is ready

This pull request generated a Preview

👀   Preview: https://preview-244--base.preview.vtex.app
🔬   Go deeper by inspecting the Build Logs
📝   based on commit b32811e

@eduardoformiga eduardoformiga changed the title Chore: remove unused css (spike) Chore: remove unused css (spike) FSSS-143 Jan 21, 2022
@eduardoformiga eduardoformiga changed the title Chore: remove unused css (spike) FSSS-143 Chore: remove unused css (spike) [FSSS-143] Jan 21, 2022
@eduardoformiga
Copy link
Member Author

The code from this PR was also added on f7ae9c8 on #241. so that we can solve the unused CSS problem there.
So this PR here becomes a study case that we can visit as necessary in the future :)

@eduardoformiga eduardoformiga marked this pull request as ready for review January 22, 2022 00:06
@gvc gvc deleted the chore/remove-unused-css branch January 24, 2022 17:27
@eduardoformiga eduardoformiga changed the title Chore: remove unused css (spike) [FSSS-143] [FSSS-143] Chore: remove unused css (spike) Feb 3, 2022
@eduardoformiga eduardoformiga added documentation Improvements or additions to documentation performance Improvements to performance and removed wip labels Feb 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Improvements or additions to documentation performance Improvements to performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant