From 0ecabfefc0a1bdd930495440d78f33ab4fc7cd59 Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Tue, 8 Oct 2019 12:16:44 +1100 Subject: [PATCH 1/5] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 15f162c..c93b0b5 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ Detects used `css` files from the given HTML, and/or __inlines critical styles__. Supports sync or __stream__ rendering. +Read more about critical style extraction and this library: https://dev.to/thekashey/optimising-css-delivery-57eh + ## Code splitting This is all about code splitting, Server Side Rendering and React, even if React has nothing to do with this library. From 9dcc7608b298d63e56cdbdd3998fdfc92615543b Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Thu, 10 Oct 2019 15:28:58 +1100 Subject: [PATCH 2/5] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c93b0b5..9af88a6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@

used-style


- Get all the styles, you have used to render a page. + Get all the styles, you have used to render a page. + (without any puppeteer involved)

From 48777a75e26816f0cacfb2b7aa3e3930b220d4d8 Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Thu, 10 Oct 2019 15:29:12 +1100 Subject: [PATCH 3/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9af88a6..ec37714 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

used-style


- Get all the styles, you have used to render a page. + Get all the styles, you have used to render a page.
(without any puppeteer involved)

From 18d5cba4c85700e967239d6e1f655be97ecd4d04 Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Thu, 7 Nov 2019 21:15:58 +1100 Subject: [PATCH 4/5] Update README.md --- README.md | 61 ++++++++++++++++++------------------------------------- 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index ec37714..3faedaa 100644 --- a/README.md +++ b/README.md @@ -19,54 +19,31 @@ Supports sync or __stream__ rendering. Read more about critical style extraction and this library: https://dev.to/thekashey/optimising-css-delivery-57eh -## Code splitting -This is all about code splitting, Server Side Rendering and React, even if React has nothing to do with this library. - -Code splitting is a good feature, and SSR is also awesome, but then you have -to load all the used `scripts` on the client, before making a page alive. -Everybody is talking not about `.css`, but only about `.js`. - -That's done, in a different ways. That's not a big task, as long as the _usage_ of code splitted blocks -is _trackable_ - you are using it, and components defined inside. - -CSS is harder - you might just use random classes and what next? You are just importing CSS here and where, -sometimes indirectly, and there is no way to understand what's happening. - -> While it's possible for webpack to add a `Link` to document header once some `Component` uses some `Style`, -you can't do the same in the __concurrent__ server environment - there is no to add a Link. - -Code splitting libraries solved it straight forward - by building resource graph, and fetching all -bound resources to that graph, but tracking is hard, and quite bound to the bundler, and could delay content sending. - -## Solution -1. Scan all `.css` files, extracting all the style names. -2. Scan resulting `html`, finding all the `classNames` used. -3a. Calculate all styles you need to render a given HTML. -3b. Calculate all the files you shall send to a client. -4. Inject styles or links -5. Hoist or remove styles on clientside startup - -> Bonus: Do the same for streams. - -> Bonus: Do it only for really `used styled`, not just imported somewhere. +- πŸš€ Super Fast - no browser, no jsdom, no runtime transformations +- πŸ’ͺ API - it's no more than an API - integrates with everything +- 🀝 Works with `strings` and `streams` +- ⏳ Supports preloading for the real style files + +## How it works +1. Scans all `.css` files, extracting all the style names. +2. Scans resulting `html`, finding all the `classNames` used. +3. Here there are two options: +3a. Calculate all __styles__ you need to render a given HTML. +3b. Calculate all the style __files__ you have send to a client. +4. Inject `` or `` +5. After page load hoist or removes critical styles replacing them by the "real" ones. ## Limitation -In the performance sake `used-styles` inlines a bit more styles than it should - -it's just harder to understand what shall be done. +For the performance sake `used-styles` inlines a bit more styles than it should - it inlines everything it would be "not fast" to remove. - inlines all `@keyframe` animations -- inlines all `html, body` and other simple selectors (aka css-reset) -- inlines all rules matching last part of a selector - -> And, hopefully - -- __inlines all classes used in HTML code__ +- inlines all `html, body` and other tag-based selectors (hello css-reset) +- inlines all rules matching last part of a selector (`.a .b` would be included if `.b` was used but `.a` was not) ### Speed >Speed, I am speed! -For the 516kb page, which needs 80ms to renderToString resulting time for `getCriticalRules`(very expensive operation) -would be around __4ms__. +For the 516kb page, which needs __80ms__ to `renderToString`(React) resulting time for the `getCriticalRules`(very expensive operation) would be around __4ms__. # API ## Discovery API @@ -321,7 +298,9 @@ Almost unmeasurable. It's a simple and single RegExp, which is not comparable to - [critical](https://github.com/addyosmani/critical) - a super slow puppetter based solution. Able to extract critical style "above the fold". - [inline-critical](https://github.com/bezoerb/inline-critical) - slow jsdom based solution. Generates one big style block at the beginning of a file, and replaces all other `links` by async variants. However, it does not detect any critical or used styles in provided HTML - HTML is used only as a output target. πŸ‘Ž -`used-styles` is faster that libraries listed above, optimized for multiple runs, as well as +- [critters-webpack-plugun](https://github.com/GoogleChromeLabs/critters) - is the nearest analog of used-styles, build on almost same principles. + +`used-styles` is faster that libraries listed above, and optimized for multiple runs. # License MIT From 738f8f6d5df18497bc3fc053c115268f62112e81 Mon Sep 17 00:00:00 2001 From: Anton Korzunov Date: Fri, 8 Nov 2019 11:11:45 +1100 Subject: [PATCH 5/5] Update README.md --- README.md | 60 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 3faedaa..7bdce13 100644 --- a/README.md +++ b/README.md @@ -22,16 +22,25 @@ Read more about critical style extraction and this library: https://dev.to/theka - πŸš€ Super Fast - no browser, no jsdom, no runtime transformations - πŸ’ͺ API - it's no more than an API - integrates with everything - 🀝 Works with `strings` and `streams` -- ⏳ Supports preloading for the real style files +- ⏳ Helps preloading for the "real" style files + +Works in two modes: +- πŸš™ inlines style __rules__ required to render given HTML - ideal for the first time visitor +- πŸ‹οΈβ€β™€οΈinlines style __files__ required to render given HTML - ideal for the second time visitor (and code splitting) + +Critical style extraction: +- 🧱 will all all used styles at the beginning of your page in a __string__ mode +- πŸ’‰ will _interleave_ HTML and CSS in a __stream__ mode. This is the best experience possible + ## How it works -1. Scans all `.css` files, extracting all the style names. -2. Scans resulting `html`, finding all the `classNames` used. +1. Scans all `.css` files, in your `build` directory, extracting all style rules names. +2. Scans a given `html`, finding all the `classes` used. 3. Here there are two options: -3a. Calculate all __styles__ you need to render a given HTML. +3a. Calculate all __style rules__ you need to render a given HTML. 3b. Calculate all the style __files__ you have send to a client. -4. Inject `` or `` -5. After page load hoist or removes critical styles replacing them by the "real" ones. +4. Injects `` or `` +5. After the page load, hoist or removes critical styles replacing them by the "real" ones. ## Limitation For the performance sake `used-styles` inlines a bit more styles than it should - it inlines everything it would be "not fast" to remove. @@ -39,7 +48,6 @@ For the performance sake `used-styles` inlines a bit more styles than it should - inlines all `html, body` and other tag-based selectors (hello css-reset) - inlines all rules matching last part of a selector (`.a .b` would be included if `.b` was used but `.a` was not) - ### Speed >Speed, I am speed! @@ -47,19 +55,19 @@ For the 516kb page, which needs __80ms__ to `renderToString`(React) resulting ti # API ## Discovery API -Use to scan your `dist` folder to create a look up table between classNames and files they are described in. +Use to scan your `dist`/`build` folder to create a look up table between classNames and files they are described in. 1. `discoverProjectStyles(buildDirrectory, [filter]): StyleDef` - generates class lookup table > you may use the second argument to control which files should be scanned `filter` is very important function here. It takes `fileName` as input, and returns -`false`, `true`, or a `number` as result. `False` value would exclude chunk from the set, while `number` -would change the order of the chunk. -Keeping chunk ordering "as expected" is required to preserve style declaration order, which is important for many +`false`, `true`, or a `number` as result. `False` value would exclude this file from the set, `true` - add it, and `number` +would change __the order__ of the chunk. +Keeping chunk ordered "as expected" is required to preserve style declaration order, which is important for many existing styles. ```js -// with chunk format [chunkhash]_[id] +// with chunk format [chunkhash]_[id] lower ids are potentialy should be defined before higher const styleData = discoverProjectStyles(resolve('build'), name => { // get ID of a chunk and use it as order hint const match = name.match(/(\d)_c.css/); @@ -93,7 +101,7 @@ const Header = () => ( ```js import {enableReactOptimization} from 'used-styles'; -enableReactOptimization(); // +enableReactOptimization(); // just makes it a but faster ``` # Example @@ -130,15 +138,14 @@ You __may combine__ both methods, to prefetch full styles, and inline critical C ! Keep in mind - calling two functions is as fast, as calling a single one ! ### Stream rendering -Please keep in mind - stream rendering in `NOT SAFE` in terms of CSS, as long as __it might affect the ordering of selectors__. -Only pure BEM and Atomic CSS are "safe", _just some CSS_ would not be compatible. +Please keep in mind - stream rendering in __NOT SAFE__ in terms of CSS, as long as __it might affect the ordering of selectors__. +Only pure BEM and Atomic CSS are "safe", _just some random CSS_ might be not compatible. Please __test__ results before releasing into production. > If you do not understand why and how selector order is important - please __do not use__ stream transformer. -Stream rendering is much harder, and much more efficient. -The idea is to make it efficient, and not delay Time-To-First-Byte. And the second byte. +Stream rendering is much harder, and much more efficient, giving you the best Time-To-First-Byte. And the second byte. Stream rendering could be interleaved(more efficient) or block(more predictable). @@ -146,8 +153,7 @@ Stream rendering could be interleaved(more efficient) or block(more predictable) In case or React rendering you may use __interleaved streaming__, which would not delay TimeToFirstByte. It's quite similar how StyledComponents works ```js -import {discoverProjectStyles, createLink} from 'used-styles'; -import {createStyleStream} from 'used-styles/react'; +import {discoverProjectStyles, createLink, createStyleStream} from 'used-styles'; import MultiStream from 'multistream'; // generate lookup table on server start @@ -167,12 +173,12 @@ async function MyRender() { const lookup = await stylesLookup; // create a style steam const styledStream = createStyleStream(lookup, (style) => { - // _return_ link tag, and it will be appended to the stream output - return createLink(`dist/${style}`) -}); + // _return_ link tag, and it will be appended to the stream output + return createLink(`dist/${style}`) // `); @@ -193,10 +199,10 @@ MultiStream(streams).pipe(res); htmlStream.pipe(styledStream); ``` -__!! THIS IS NOT THE END !!__ Interleaving links and react output would produce break client side rehydration, -as long as _injected_ links are not rendered by React, and not expected to present in the "result" HTML code. +__!! THIS IS NOT THE END !!__ Interleaving links and react output would break a client side rehydration, +as long as _injected_ links were not rendered by React, and not expected to present in the "result" HTML code. -You have to move injected styles prior rehydration. +You have to move injected styles out prior rehydration. ```js import { moveStyles } from 'used-styles/moveStyles'; moveStyles();