Skip to content

Instantly share code, notes, and snippets.

@Munter
Last active October 29, 2016 13:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Munter/d7be00f5de6f778328cfa95d20e213c1 to your computer and use it in GitHub Desktop.
Save Munter/d7be00f5de6f778328cfa95d20e213c1 to your computer and use it in GitHub Desktop.
/*
* This transform works on an assumption about browser loading and rendering behavior of CSS:
* When a browser loads CSS in <head> it render blocks untill all CSS in <head> has loaded.
*
* That might be slow.
*
* To appear faster, browsers will render what they have in buffer already if they meet a style <link> in <body>
* before they dive into the render blocking load.
* This lets you potentially inline critical css in <head> and put the bulk of your CSS "below the fold".
* The effect will be a quick render with critical styles applied, just before the render blockign starts.
*
* We can leverage this behavior by letting the developer declaratively define their critical CSS if we
* treat <body> <link> ad "the fold", assuming that everything above it is critical and should have styling applied
* for the render flush that happens just before the <link> starts loading.
*
* Assetgraph can figure out what CSS to extract from the bundle and inline in <head> before the render blocking load starts.
* This way the developer will only have to place the <link> at the relevant place in the DOM and not think any more about
* builds and optimization.
*/
module.exports = function (options) {
options = options || {};
return function (assetGraph) {
// For each html page
// Find the first external HtmlStyle relation inside <body>
// Traverse back up the DOM to find all elements to check critical CSS for
// Find all CSS included on the page
// For each critical DOM-node, check if each style rule applies
// Collect all matching style rules that match critical DOM-nodes
// Create a new stylesheet with critical CSS rules
// Inline critical stylesheet in <head>
};
};
@lawnsea
Copy link

lawnsea commented Oct 28, 2016

So, if I understand this correctly, the idea is to mark "the fold" in the HTML source with a link tag?

@Munter
Copy link
Author

Munter commented Oct 28, 2016

@iawnsea That is exactly the idea. This should let you develop locally without much difference, but when you go to a production build you'll have inlined critical CSS above your <link>

@lawnsea
Copy link

lawnsea commented Oct 28, 2016

@Munter Is this done statically or by rendering the page? If statically, how do you determine what CSS rules are applied if the content is not known until runtime (consider a feed of heterogenous social media cards, e.g.).

@Munter
Copy link
Author

Munter commented Oct 28, 2016

@lawnsea For now I'll only deal with static data. So any javascript stuff would have to go through a pre-rendering of some sort. This can possibly be improved later. Progress so far: https://github.com/assetgraph/assetgraph/blob/feature/critical-css/lib/transforms/inlineCriticalCss.js

@lawnsea
Copy link

lawnsea commented Oct 29, 2016

@Munter Consider https://www.retailmenot.com/view/macys.com, which is server-side rendered, where one has a feed of heterogeneous content cards above the fold. How does your solution handle that? What if the feed is personalized?

@Munter
Copy link
Author

Munter commented Oct 29, 2016

This is purely a static approach. My solution won't handle those cases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment