Fix performance of splitCssText (#1615)
- Fix bug where the right split point was not being picked for the 3rd section onwards - Fix that it wasn't able to find a split when both halves were identical - Add test to put splitCssText through it's paces with a large file - Introduce a limit on the iteration which causes the 'efficiently' test to fail - Fix poor 'crawling' performance in the 'matching' algorithm for large css texts - e.g. for a (doubled) benchmark.css, we were running `normalizeCssText` 9480 times before `k` got to the right place - Further algorithm efficiency: need to take larger jumps; use the scaling factor to make better guess at how big a jump to make
This commit is contained in:
@@ -7,6 +7,8 @@ import postcss, { type AcceptedPlugin } from 'postcss';
|
||||
import { JSDOM } from 'jsdom';
|
||||
import { splitCssText, stringifyStylesheet } from './../src/utils';
|
||||
import { applyCssSplits } from './../src/rebuild';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import type {
|
||||
serializedElementNodeWithId,
|
||||
BuildCache,
|
||||
@@ -105,10 +107,16 @@ describe('css splitter', () => {
|
||||
// as authored, e.g. no spaces
|
||||
style.append('.a{background-color:black;}');
|
||||
|
||||
// test how normalization finds the right sections
|
||||
style.append('.b {background-color:black;}');
|
||||
style.append('.c{ background-color: black}');
|
||||
|
||||
// how it is currently stringified (spaces present)
|
||||
const expected = [
|
||||
'.a { background-color: red; }',
|
||||
'.a { background-color: black; }',
|
||||
'.b { background-color: black; }',
|
||||
'.c { background-color: black; }',
|
||||
];
|
||||
const browserSheet = expected.join('');
|
||||
expect(stringifyStylesheet(style.sheet!)).toEqual(browserSheet);
|
||||
@@ -137,6 +145,28 @@ describe('css splitter', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('finds css textElement splits correctly with two identical text nodes', () => {
|
||||
const window = new Window({ url: 'https://localhost:8080' });
|
||||
const document = window.document;
|
||||
// as authored, with comment, missing semicolons
|
||||
const textContent = '.a { color:red; } .b { color:blue; }';
|
||||
document.head.innerHTML = '<style></style>';
|
||||
const style = document.querySelector('style');
|
||||
if (style) {
|
||||
style.append(textContent);
|
||||
style.append(textContent);
|
||||
|
||||
const expected = [textContent, textContent];
|
||||
const browserSheet = expected.join('');
|
||||
expect(splitCssText(browserSheet, style)).toEqual(expected);
|
||||
|
||||
style.append(textContent);
|
||||
const expected3 = [textContent, textContent, textContent];
|
||||
const browserSheet3 = expected3.join('');
|
||||
expect(splitCssText(browserSheet3, style)).toEqual(expected3);
|
||||
}
|
||||
});
|
||||
|
||||
it('finds css textElement splits correctly when vendor prefixed rules have been removed', () => {
|
||||
const style = JSDOM.fragment(`<style></style>`).querySelector('style');
|
||||
if (style) {
|
||||
@@ -169,6 +199,34 @@ describe('css splitter', () => {
|
||||
expect(splitCssText(browserSheet, style)).toEqual(expected);
|
||||
}
|
||||
});
|
||||
|
||||
it('efficiently finds split points in large files', () => {
|
||||
const cssText = fs.readFileSync(
|
||||
path.resolve(__dirname, './css/benchmark.css'),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
const parts = cssText.split('}');
|
||||
const sections = [];
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
if (i % 100 === 0) {
|
||||
sections.push(parts[i] + '}');
|
||||
} else {
|
||||
sections[sections.length - 1] += parts[i] + '}';
|
||||
}
|
||||
}
|
||||
sections[sections.length - 1] += parts[parts.length - 1];
|
||||
|
||||
expect(cssText.length).toEqual(sections.join('').length);
|
||||
|
||||
const style = JSDOM.fragment(`<style></style>`).querySelector('style');
|
||||
if (style) {
|
||||
sections.forEach((section) => {
|
||||
style.appendChild(JSDOM.fragment(section));
|
||||
});
|
||||
}
|
||||
expect(splitCssText(cssText, style)).toEqual(sections);
|
||||
});
|
||||
});
|
||||
|
||||
describe('applyCssSplits css rejoiner', function () {
|
||||
|
||||
Reference in New Issue
Block a user