Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/Cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export function pathKey(keys: KeyType[]) {
return keys.join(SPLIT);
}

/** Record update id for extract static style order. */
let updateId = 0;

class Entity {
instanceId: string;
constructor(instanceId: string) {
Expand All @@ -17,6 +20,9 @@ class Entity {
/** @private Internal cache map. Do not access this directly */
cache = new Map<string, ValueType>();

/** @private Record update times for each key */
updateTimes = new Map<string, number>();

get(keys: KeyType[]): ValueType | null {
return this.opGet(pathKey(keys));
}
Expand All @@ -43,8 +49,11 @@ class Entity {

if (nextValue === null) {
this.cache.delete(keyPathStr);
this.updateTimes.delete(keyPathStr);
} else {
this.cache.set(keyPathStr, nextValue);
this.updateTimes.set(keyPathStr, updateId);
updateId += 1;
}
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/extractStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default function extractStyle(
let styleText = '';

styleKeys
.map<[number, string] | null>((key) => {
.map<[order: number, style: string, updateTime: number] | null>((key) => {
const cachePath = key.replace(matchPrefixRegexp, '').replace(/%/g, '|');
const [prefix] = key.split('%');
const extractFn = ExtractStyleFns[prefix as keyof typeof ExtractStyleFns];
Expand All @@ -69,14 +69,20 @@ export default function extractStyle(
if (!extractedStyle) {
return null;
}
const updateTime = cache.updateTimes.get(key) || 0;
const [order, styleId, styleStr] = extractedStyle;
if (key.startsWith('style')) {
cachePathMap[cachePath] = styleId;
}
return [order, styleStr];
return [order, styleStr, updateTime];
})
.filter(isNotNull)
.sort(([o1], [o2]) => o1 - o2)
.sort(([o1, , u1], [o2, , u2]) => {
if (o1 !== o2) {
return o1 - o2;
}
return u1 - u2;
})
.forEach(([, style]) => {
styleText += style;
});
Expand Down
70 changes: 70 additions & 0 deletions tests/server.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -345,4 +345,74 @@ describe('SSR', () => {
const pureStyle = extractStyle(cache, true);
expect(pureStyle).toMatchSnapshot();
});

it('extract with order', () => {
// Create 3 components without specified order: A, C, B
const A = () => {
const [token] = useCacheToken<DerivativeToken>(theme, [baseToken], {
cssVar: { key: 'css-var-test' },
});
useStyleRegister({ theme, token, path: ['a'] }, () => ({
'.a': { backgroundColor: token.primaryColor },
}));
return <div className="a" />;
};
const C = () => {
const [token] = useCacheToken<DerivativeToken>(theme, [baseToken], {
cssVar: { key: 'css-var-test' },
});
useStyleRegister({ theme, token, path: ['c'] }, () => ({
'.c': { backgroundColor: token.primaryColor },
}));
return <div className="c" />;
};
const B = () => {
const [token] = useCacheToken<DerivativeToken>(theme, [baseToken], {
cssVar: { key: 'css-var-test' },
});
useStyleRegister({ theme, token, path: ['b'] }, () => ({
'.b': { backgroundColor: token.primaryColor },
}));
return <div className="b" />;
};

function testOrder(
node1: React.ReactElement,
node2: React.ReactElement,
node3: React.ReactElement,
componentMarks: string[],
) {
const cache = createCache();

renderToString(
<StyleProvider cache={cache}>
{node1}
{node2}
{node3}
</StyleProvider>,
);

const plainStyle = extractStyle(cache, true);
const index1 = plainStyle.indexOf(`.${componentMarks[0]}{`);
const index2 = plainStyle.indexOf(`.${componentMarks[1]}{`);
const index3 = plainStyle.indexOf(`.${componentMarks[2]}{`);

expect(index1).toBeGreaterThanOrEqual(0);
expect(index2).toBeGreaterThan(index1);
expect(index3).toBeGreaterThan(index2);
}

// A B C
testOrder(<A />, <B />, <C />, ['a', 'b', 'c']);
// A C B
testOrder(<A />, <C />, <B />, ['a', 'c', 'b']);
// B A C
testOrder(<B />, <A />, <C />, ['b', 'a', 'c']);
// B C A
testOrder(<B />, <C />, <A />, ['b', 'c', 'a']);
// C A B
testOrder(<C />, <A />, <B />, ['c', 'a', 'b']);
// C B A
testOrder(<C />, <B />, <A />, ['c', 'b', 'a']);
});
});