Modernise bench
This commit is contained in:
parent
94f292da38
commit
b630f32087
|
@ -41,12 +41,11 @@ Since speed depends on the input, speed charts show performance relative to the
|
||||||
|
|
||||||
The settings used for each minifier can be found in [minifiers.js](./minifiers.js). Some settings to note:
|
The settings used for each minifier can be found in [minifiers.js](./minifiers.js). Some settings to note:
|
||||||
|
|
||||||
- All minifiers are configured to use esbuild for JS minification asynchronously and in parallel, similar to how minify-html works.
|
|
||||||
- `conservativeCollapse` is enabled for html-minifier as otherwise some whitespace would be unsafely removed with side effects. minify-html can safely remove whitespace with context if configured properly.
|
- `conservativeCollapse` is enabled for html-minifier as otherwise some whitespace would be unsafely removed with side effects. minify-html can safely remove whitespace with context if configured properly.
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
Make sure to install the dependencies listed in [package.json](./package.json) by running `npm i` or `yarn`. Node.js 10 is required, and system dependencies for building [canvas](https://www.npmjs.com/package/canvas), used for rendering graphs, may need to be installed. See the [npm package](https://www.npmjs.com/package/canvas) for more details.
|
Make sure to install the dependencies listed in [package.json](./package.json) by running `npm i` or `yarn`.
|
||||||
|
|
||||||
Run [build.sh](./build.sh) to build @minify-html/js with the local minify-html.
|
Run [build.sh](./build.sh) to build @minify-html/js with the local minify-html.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const chartjs = require('chartjs-node');
|
|
||||||
const results = require('./results');
|
const results = require('./results');
|
||||||
|
const request = require('request-promise-native');
|
||||||
|
|
||||||
const colours = {
|
const colours = {
|
||||||
'minify-html': '#041f60',
|
'minify-html': '#041f60',
|
||||||
|
@ -50,9 +50,9 @@ const chartOptions = (title, displayLegend, yTick = t => t) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const renderChart = async (cfg) => {
|
const renderChart = async (cfg) => {
|
||||||
const chart = new chartjs(900, 650);
|
return await request({
|
||||||
await chart.drawChart(cfg);
|
url: `https://quickchart.io/chart?chart=${encodeURIComponent(JSON.stringify(cfg))}&width=900&height=650&format=png`,
|
||||||
return chart.getImageBuffer('image/png');
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
|
@ -25,32 +25,20 @@ const jsMime = new Set([
|
||||||
'text/x-javascript',
|
'text/x-javascript',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
class EsbuildAsync {
|
|
||||||
constructor () {
|
|
||||||
this.promises = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
queue (code, type) {
|
|
||||||
const id = this.promises.push(esbuild.transform(code, {
|
|
||||||
loader: type,
|
|
||||||
minify: true,
|
|
||||||
minifyWhitespace: true,
|
|
||||||
minifyIdentifiers: true,
|
|
||||||
minifySyntax: true,
|
|
||||||
})) - 1;
|
|
||||||
return `_____ESBUILD_ASYNC_PLACEHOLDER_${id}_____`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async finalise (html) {
|
|
||||||
const jsTransformResults = await Promise.all(this.promises);
|
|
||||||
return html.replace(/_____ESBUILD_ASYNC_PLACEHOLDER_([0-9]+)_____/g, (_, id) => jsTransformResults[id].code.replace(/<\/script/g, "<\\/script"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const minifyHtmlCfg = minifyHtml.createConfiguration({
|
const minifyHtmlCfg = minifyHtml.createConfiguration({
|
||||||
minifyJs: testJsAndCssMinification,
|
minify_js: testJsAndCssMinification,
|
||||||
minifyCss: testJsAndCssMinification,
|
minify_css: testJsAndCssMinification,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const esbuildCss = code => esbuild.transformSync(code, {
|
||||||
|
loader: "css",
|
||||||
|
minify: true,
|
||||||
|
}).code;
|
||||||
|
const esbuildJs = code => esbuild.transformSync(code, {
|
||||||
|
loader: "js",
|
||||||
|
minify: true,
|
||||||
|
}).code.replace(/<\/script/g, "<\\/script");
|
||||||
|
|
||||||
const htmlMinifierCfg = {
|
const htmlMinifierCfg = {
|
||||||
collapseBooleanAttributes: true,
|
collapseBooleanAttributes: true,
|
||||||
collapseInlineTagWhitespace: true,
|
collapseInlineTagWhitespace: true,
|
||||||
|
@ -63,9 +51,8 @@ const htmlMinifierCfg = {
|
||||||
decodeEntities: true,
|
decodeEntities: true,
|
||||||
ignoreCustomComments: [],
|
ignoreCustomComments: [],
|
||||||
ignoreCustomFragments: [/<\?[\s\S]*?\?>/],
|
ignoreCustomFragments: [/<\?[\s\S]*?\?>/],
|
||||||
// These will be set later if `testJsAndCssMinification` is true.
|
minifyCSS: testJsAndCssMinification && esbuildCss,
|
||||||
minifyCSS: false,
|
minifyJS: testJsAndCssMinification && esbuildJs,
|
||||||
minifyJS: false,
|
|
||||||
processConditionalComments: true,
|
processConditionalComments: true,
|
||||||
removeAttributeQuotes: true,
|
removeAttributeQuotes: true,
|
||||||
removeComments: true,
|
removeComments: true,
|
||||||
|
@ -79,39 +66,25 @@ const htmlMinifierCfg = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'@minify-html/js': (_, buffer) => minifyHtml.minifyInPlace(Buffer.from(buffer), minifyHtmlCfg),
|
'@minify-html/js': (_, buffer) => minifyHtml.minify(Buffer.from(buffer), minifyHtmlCfg),
|
||||||
'html-minifier': testJsAndCssMinification
|
'html-minifier': content => htmlMinifier.minify(content, htmlMinifierCfg),
|
||||||
? async (content) => {
|
|
||||||
const js = new EsbuildAsync();
|
|
||||||
const res = htmlMinifier.minify(content, {
|
|
||||||
...htmlMinifierCfg,
|
|
||||||
minifyCSS: code => js.queue(code, 'css'),
|
|
||||||
minifyJS: code => js.queue(code, 'js'),
|
|
||||||
});
|
|
||||||
return js.finalise(res);
|
|
||||||
}
|
|
||||||
: content => htmlMinifier.minify(content, htmlMinifierCfg),
|
|
||||||
'minimize': testJsAndCssMinification
|
'minimize': testJsAndCssMinification
|
||||||
? async (content) => {
|
? (content) => new minimize({
|
||||||
const js = new EsbuildAsync();
|
|
||||||
const res = new minimize({
|
|
||||||
plugins: [
|
plugins: [
|
||||||
{
|
{
|
||||||
id: 'esbuild',
|
id: 'esbuild',
|
||||||
element: (node, next) => {
|
element: (node, next) => {
|
||||||
if (node.type === 'text' && node.parent) {
|
if (node.type === 'text' && node.parent) {
|
||||||
if (node.parent.type === 'script' && jsMime.has(node.parent.attribs.type)) {
|
if (node.parent.type === 'script' && jsMime.has(node.parent.attribs.type)) {
|
||||||
node.data = js.queue(node.data, 'js');
|
node.data = esbuildJs(node.data);
|
||||||
} else if (node.parent.type === 'style') {
|
} else if (node.parent.type === 'style') {
|
||||||
node.data = js.queue(node.data, 'css');
|
node.data = esbuildCss(node.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}).parse(content);
|
}).parse(content)
|
||||||
return js.finalise(res);
|
|
||||||
}
|
|
||||||
: content => new minimize().parse(content),
|
: content => new minimize().parse(content),
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,18 +3,12 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@minify-html/js": "file:../nodejs",
|
"@minify-html/js": "file:../nodejs",
|
||||||
"benchmark": "2.1.4",
|
"benchmark": "2.1.4",
|
||||||
"chart.js": "^2.9.3",
|
"esbuild": "^0.12.18",
|
||||||
"chartjs-node": "^1.7.1",
|
|
||||||
"esbuild": "^0.11.6",
|
|
||||||
"html-minifier": "4.0.0",
|
"html-minifier": "4.0.0",
|
||||||
"minimize": "2.2.0",
|
"minimize": "2.2.0",
|
||||||
"minimist": "^1.2.0",
|
"minimist": "^1.2.5",
|
||||||
"mkdirp": "^0.5.1",
|
"request": "^2.88.2",
|
||||||
"request": "^2.88.0",
|
"request-promise-native": "^1.0.9"
|
||||||
"request-promise-native": "^1.0.8"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "10.x"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node bench.js"
|
"start": "node bench.js"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
const minifiers = require('./minifiers');
|
const minifiers = require('./minifiers');
|
||||||
const mkdirp = require('mkdirp');
|
|
||||||
const tests = require('./tests');
|
const tests = require('./tests');
|
||||||
const {join} = require('path');
|
const {join} = require('path');
|
||||||
const {readFileSync, writeFileSync} = require('fs');
|
const {mkdirSync, readFileSync, writeFileSync} = require('fs');
|
||||||
|
|
||||||
const RESULTS_DIR = join(__dirname, 'results');
|
const RESULTS_DIR = join(__dirname, 'results');
|
||||||
const SPEEDS_JSON = join(RESULTS_DIR, 'speeds.json');
|
const SPEEDS_JSON = join(RESULTS_DIR, 'speeds.json');
|
||||||
|
@ -15,7 +14,7 @@ const AVERAGE_SIZES_GRAPH = join(RESULTS_DIR, 'average-sizes.png');
|
||||||
const minifierNames = Object.keys(minifiers);
|
const minifierNames = Object.keys(minifiers);
|
||||||
const testNames = tests.map(t => t.name);
|
const testNames = tests.map(t => t.name);
|
||||||
|
|
||||||
mkdirp.sync(RESULTS_DIR);
|
mkdirSync(RESULTS_DIR, {recursive: true});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
writeSpeedResults(speeds) {
|
writeSpeedResults(speeds) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const mkdirp = require('mkdirp');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const minifiers = require('./minifiers');
|
const minifiers = require('./minifiers');
|
||||||
const results = require('./results');
|
const results = require('./results');
|
||||||
|
@ -30,7 +29,7 @@ const setSize = (program, test, result) => {
|
||||||
// If `min` is a Buffer, convert to string (interpret as UTF-8) to get canonical length.
|
// If `min` is a Buffer, convert to string (interpret as UTF-8) to get canonical length.
|
||||||
setSize(m, t.name, min.toString().length);
|
setSize(m, t.name, min.toString().length);
|
||||||
const minPath = path.join(__dirname, 'min', m, `${t.name}.html`);
|
const minPath = path.join(__dirname, 'min', m, `${t.name}.html`);
|
||||||
mkdirp.sync(path.dirname(minPath));
|
fs.mkdirSync(path.dirname(minPath), {recursive: true});
|
||||||
fs.writeFileSync(minPath, min);
|
fs.writeFileSync(minPath, min);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to run ${m} on test ${t.name}:`);
|
console.error(`Failed to run ${m} on test ${t.name}:`);
|
||||||
|
|
Loading…
Reference in New Issue