Skip to content

Commit

Permalink
track used selectors via WeakMap, fixes #21
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed Jun 8, 2020
1 parent c3dfb45 commit 9826c82
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 28 deletions.
26 changes: 10 additions & 16 deletions src/getCSS.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { kashe } from 'kashe';
import { StyleAst } from './parser/ast';
import { extractUnmatchable, fromAst, getUnmatchableRules } from './parser/fromAst';
import { FlagType, StyleChunk, StyleDefinition, UsedTypes, UsedTypesRef } from './types';
import { FlagType, SelectionFilter, StyleChunk, StyleDefinition, UsedTypes, UsedTypesRef } from './types';
import { assertIsReady, getStylesInText, unique } from './utils';

export const getUnusableStyles = kashe(
Expand Down Expand Up @@ -74,17 +74,15 @@ export const getUsedStyles = (str: string, def: StyleDefinition): UsedTypes => {
return getUsedStylesIn(getStylesInText(str), def);
};

const astToStyles = kashe(
(styles: string[], def: StyleDefinition, filter?: (selector: string) => boolean): StyleChunk[] => {
const { ast } = def;
const { fetches, usage } = astToUsedStyles(styles, def);
const astToStyles = kashe((styles: string[], def: StyleDefinition, filter?: SelectionFilter): StyleChunk[] => {
const { ast } = def;
const { fetches, usage } = astToUsedStyles(styles, def);

return usage.map(file => ({
file,
css: fromAst(Object.keys(fetches[file]), ast[file], filter),
}));
}
);
return usage.map(file => ({
file,
css: fromAst(Object.keys(fetches[file]), ast[file], filter),
}));
});

export const wrapInStyle = (styles: string, usedStyles: string[] = []) =>
styles
Expand Down Expand Up @@ -121,11 +119,7 @@ export const extractAllUnmatchableAsString = kashe((def: StyleDefinition) =>
const criticalRulesToStyle = (styles: StyleChunk[], urlPrefix = ''): string =>
wrapInStyle(styles.map(({ css }) => css).join(''), unique(styles.map(({ file }) => `${urlPrefix}${file}`)));

export const criticalStylesToString = (
str: string,
def: StyleDefinition,
filter?: (selector: string) => boolean
): string => {
export const criticalStylesToString = (str: string, def: StyleDefinition, filter?: SelectionFilter): string => {
assertIsReady(def);
return criticalRulesToStyle(astToStyles(getStylesInText(str), def, filter), def.urlPrefix);
};
Expand Down
7 changes: 3 additions & 4 deletions src/parser/fromAst.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { kashe } from 'kashe';
import * as postcss from 'postcss';
import { SelectionFilter } from '../types';
import { SingleStyleAst, StyleBody, StyleRule, StyleSelector } from './ast';

const separator = process.env.NODE_ENV === 'production' ? '' : '\n';
Expand Down Expand Up @@ -41,13 +42,11 @@ const findMatchingSelectors = (rules: SelectorLookUp, selectors: StyleSelector[]
const findUnmatchableSelectors = (selectors: StyleSelector[]): StyleSelector[] =>
selectors.filter(rule => rule.pieces.length === 0);

export const fromAst = (rules: string[], def: SingleStyleAst, filter?: (selector: string) => boolean) => {
export const fromAst = (rules: string[], def: SingleStyleAst, filter?: SelectionFilter) => {
const blocks: StyleSelector[] = [];
const lookup: SelectorLookUp = new Set(rules);
blocks.push(
...findMatchingSelectors(lookup, def.selectors).filter(
block => !filter || filter(`${block.selector}${block.media.join('')}`)
)
...findMatchingSelectors(lookup, def.selectors).filter(block => !filter || filter(block.selector, block))
);

return convertToString(blocks, def);
Expand Down
9 changes: 5 additions & 4 deletions src/reporters/critical.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Transform } from 'stream';
import { isReact } from '../config';
import { criticalStylesToString, extractAllUnmatchableAsString } from '../getCSS';
import { StyleSelector } from '../parser/ast';
import { CacheLine, StyleDefinition } from '../types';
import { assertIsReady, createLine, findLastBrace } from '../utils';

Expand Down Expand Up @@ -30,13 +31,13 @@ export const createCriticalStyleStream = (def: StyleDefinition) => {
const line = createLine();
let injections: Array<string | undefined> = [];

const usedSelectors = new Set<string>();
const usedSelectors = new WeakSet<any>();

const filter = (selector: string) => {
if (usedSelectors.has(selector)) {
const filter = (_: any, rule: StyleSelector) => {
if (usedSelectors.has(rule)) {
return false;
}
usedSelectors.add(selector);
usedSelectors.add(rule);
return true;
};

Expand Down
15 changes: 11 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {StyleAst} from "./parser/ast";
import { StyleAst, StyleSelector } from './parser/ast';

export type StylesLookupTable = Record<string, string[]>;

Expand All @@ -19,16 +19,23 @@ export interface SyncStyleDefinition {
}

export interface StyleChunk {
file: string,
file: string;
css: string;
}

export type FlagType = Record<string, boolean>
export type FlagType = Record<string, boolean>;

export interface StyleDefinition {
isReady: boolean;
lookup: StylesLookupTable;
ast: StyleAst;
urlPrefix: string;
then(resolve?: () => void, reject?: () => void): Promise<void>;
}
}

/**
* A function used to control which selectors should be used
* @param selector - DEPRECATED
* @param {StyleSelector} rule - a reference to a rule
*/
export type SelectionFilter = (selector: string, rule: StyleSelector) => boolean;

0 comments on commit 9826c82

Please sign in to comment.