Skip to content

Commit

Permalink
feat: alterProjectStyles and hydrid usage
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed Oct 5, 2019
1 parent da5042a commit 4012b86
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 5 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,20 @@ htmlStream.on('end', () => {
> This example is taken from [Parcel-SSR-example](https://github.com/theKashey/react-imported-component/tree/master/examples/SSR/parcel-react-ssr)
from __react-imported-component__.
# Hybrid usage
The advanced pattern described in [Optimizing CSS Delivery](https://dev.to/thekashey/optimising-css-delivery-57eh) article proposes to:
- inline critical CSS for a first time customers
- use cached `.css` files for recurring
This library does not provide a way to distinguish "one" cohort of customers from another, although, provides an API to optimize the delivery.
- use `createCriticalStyleStream`/`getCriticalStyles` to __inline__ critical CSS
- use `createStyleStream`/`getUsedStyles` to use `.css` files
- use `alterProjectStyles` with `filter` options to create two different sets of styles: not yet _cache_ set for `critical` styles, and the _cached_ ones for `used`.
- yes - you have to use or two transformers, or call two functions, one after another.
> Theoretically - all styles "critical" now, are "cached" ones next view.
# Performance
Almost unmeasurable. It's a simple and single RegExp, which is not comparable to the React Render itself.
Expand Down
24 changes: 22 additions & 2 deletions __tests__/react.integration.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import {
parseProjectStyles,
createLink,
getCriticalStyles,
discoverProjectStyles, getUsedStyles
discoverProjectStyles, getUsedStyles, alterProjectStyles
} from "../src";
import {StyleDefinition} from "../src/types";

describe('File based css stream', () => {
let styles: StyleDefinition;

beforeEach(() => {
styles = discoverProjectStyles(resolve(__dirname ,'css'), name => {
styles = discoverProjectStyles(resolve(__dirname, 'css'), name => {
const match = name.match(/file(\d+).css/);
return match && +match[1];
});
Expand All @@ -27,6 +27,26 @@ describe('File based css stream', () => {
expect(() => getUsedStyles("", styles)).toThrow();
});

it('skip: test', async () => {
await styles;
const s1 = getCriticalStyles('<div class="class2 someclass">', styles);
const s2 = getCriticalStyles('<div class="class2 someclass">',
alterProjectStyles(styles, {filter: (x) => x.indexOf('file2') !== 0})
);
const s3 = getCriticalStyles('<div class="class2 someclass">',
alterProjectStyles(
alterProjectStyles(styles, {filter: (x) => x.indexOf('file2') !== 0}),
{filter: (x) => x.indexOf('file1') !== 0}
)
);

expect(s1).not.toBe(s2);
expect(s2).not.toBe(s3);
expect(s1).toMatch(/data-used-styles=\"file1.css,file2.css\"/);
expect(s2).toMatch(/data-used-styles=\"file1.css\"/);
expect(s3).toBe('');
});

it('memoization: test', async () => {
await styles;
const s1 = getCriticalStyles('<div class="class2 someclass">', styles);
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {discoverProjectStyles, parseProjectStyles} from './scanForStyles'
import {discoverProjectStyles, parseProjectStyles, alterProjectStyles} from './scanForStyles'
import {getUsedStyles, getCriticalStyles, getCriticalRules} from './getCSS';
import {createStyleStream} from "./reporters/used";
import {createCriticalStyleStream} from "./reporters/critical";
Expand All @@ -9,6 +9,7 @@ import {enableReactOptimization} from "./config";
export {
discoverProjectStyles,
parseProjectStyles,
alterProjectStyles,

getUsedStyles,
getCriticalStyles,
Expand Down
33 changes: 31 additions & 2 deletions src/scanForStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {StyleDef, StyleDefinition, StyleFiles, StylesLookupTable, SyncStyleDefin
import {mapStyles} from "./parser/utils";
import {buildAst} from "./parser/toAst";
import {StyleAst} from "./parser/ast";
import {assertIsReady} from "./utils";

const RESOLVE_EXTENSIONS = ['.css'];

Expand Down Expand Up @@ -114,7 +115,7 @@ export function discoverProjectStyles(rootDir: string, fileFilter: (fileName: st

const styleFiles: StyleFiles = {};
// prefill the obiect to pin keys ordering
files.map( file => styleFiles[relative(rootDir, file)] = undefined as any);
files.map(file => styleFiles[relative(rootDir, file)] = undefined as any);

await Promise.all(
files.map(async (file) => {
Expand All @@ -137,4 +138,32 @@ export function discoverProjectStyles(rootDir: string, fileFilter: (fileName: st
);

return result;
}
}

export interface AlterOptions {
// filters available styles
filter(style: string): boolean,
}

export const alterProjectStyles = (def: StyleDefinition, options: AlterOptions): StyleDefinition => {
assertIsReady(def);

return {
...def,
ast: Object.keys(def.ast).reduce((acc, file) => {
const astFile = def.ast[file];
const shouldRemove = (
!options.filter || !options.filter(file)
);

// dont add this file to the result file list
if (shouldRemove) {
return acc;
}

acc[file] = astFile;

return acc;
}, {} as StyleAst)
}
};

0 comments on commit 4012b86

Please sign in to comment.