add terser and report file sizes

This commit is contained in:
mdgriffith 2020-08-01 09:59:24 -04:00
parent 6d9d6ff34b
commit ae59d0e668
4 changed files with 169 additions and 26 deletions

55
package-lock.json generated
View File

@ -4543,6 +4543,15 @@
}
}
},
"fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
"dev": true,
"requires": {
"pend": "~1.2.0"
}
},
"figures": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
@ -7231,15 +7240,6 @@
"type-check": "~0.3.2"
}
},
"lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"dev": true,
"requires": {
"immediate": "~3.0.5"
}
},
"lines-and-columns": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
@ -9252,6 +9252,25 @@
"rollup-pluginutils": "^2.8.2",
"serialize-javascript": "^2.1.2",
"terser": "^4.6.2"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"terser": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
"integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
"dev": true,
"requires": {
"commander": "^2.20.0",
"source-map": "~0.6.1",
"source-map-support": "~0.5.12"
}
}
}
},
"rollup-plugin-typescript2": {
@ -9470,12 +9489,6 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"set-immediate-shim": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
"dev": true
},
"set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@ -10165,9 +10178,9 @@
}
},
"terser": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
"integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.0.0.tgz",
"integrity": "sha512-olH2DwGINoSuEpSGd+BsPuAQaA3OrHnHnFL/rDB2TVNc3srUbz/rq/j2BlF4zDXI+JqAvGr86bIm1R2cJgZ3FA==",
"dev": true,
"requires": {
"commander": "^2.20.0",
@ -10690,6 +10703,12 @@
"integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==",
"dev": true
},
"uglify-js": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.0.tgz",
"integrity": "sha512-Esj5HG5WAyrLIdYU74Z3JdG2PxdIusvj6IWHMtlyESxc7kcDz7zYlYjpnSokn1UbpV0d/QX9fan7gkCNd/9BQA==",
"dev": true
},
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",

View File

@ -37,12 +37,14 @@
"chromedriver": "^84.0.1",
"husky": "^4.2.5",
"node-elm-compiler": "^5.0.4",
"selenium-webdriver": "^4.0.0-alpha.7",
"prepack": "^0.2.54",
"selenium-webdriver": "^4.0.0-alpha.7",
"terser": "^5.0.0",
"ts-node": "^8.10.2",
"tsdx": "^0.13.2",
"tslib": "^2.0.0",
"typescript": "^3.9.7"
"typescript": "^3.9.7",
"uglify-js": "^3.10.0"
},
"dependencies": {
"tree-sitter": "^0.16.1",

View File

@ -13,8 +13,9 @@ import {
InlineMode,
createInlineListFromArrayTransformer,
} from './experiments/inlineListFromArray';
import { prepackFileSync } from 'prepack';
import * as Terser from 'terser';
import { execSync } from 'child_process';
import {
createReplaceUtilsUpdateWithObjectSpread,
@ -101,20 +102,83 @@ export const compileAndTransform = (
fs.writeFileSync(pathInOutput('elm.opt.js'), printer.printFile(initialJs));
if (options?.prepack) {
console.log('here');
// console.log('here');
const { code } = prepackFileSync([pathInOutput('elm.opt.transformed.js')], {
debugNames: true,
inlineExpressions: true,
maxStackDepth: 1200, // that didn't help
});
console.log('there', code.length);
// console.log('there', code.length);
fs.writeFileSync(pathInOutput('elm.opt.prepack.js'), code);
}
minify(pathInOutput('elm.opt.js'), pathInOutput('elm.opt.min.js'));
gzip(pathInOutput('elm.opt.min.js'));
minify(
pathInOutput('elm.opt.transformed.js'),
pathInOutput('elm.opt.transformed.min.js')
);
gzip(pathInOutput('elm.opt.transformed.min.js'));
return {};
};
async function minify(inputFilename: string, outputFilename: string) {
const compress = {
toplevel: true,
mangle: false,
compress: {
pure_getters: true,
keep_fargs: false,
unsafe_comps: true,
unsafe: true,
pure_funcs: [
'F2',
'F3',
'F4',
'F5',
'F6',
'F7',
'F8',
'F9',
'A2',
'A3',
'A4',
'A5',
'A6',
'A7',
'A8',
'A9',
],
},
};
const mangle = {
mangle: true,
compress: false,
};
const input = fs.readFileSync(inputFilename, 'utf8');
const compressed = await Terser.minify(input, compress);
let mangled = null;
if (compressed && compressed.code) {
mangled = await Terser.minify(compressed.code, mangle);
} else {
console.log('Error compressing with Terser');
}
// console.log('mangled', mangled.error);
if (mangled && mangled.code) {
fs.writeFileSync(outputFilename, mangled.code);
} else {
console.log('Error mangling with Terser');
}
}
async function gzip(file: string) {
// --keep = keep the original file
// --force = overwrite the exisign gzip file if it's there
execSync('gzip --keep --force ' + file);
}
function reportInlineTransformResult(ctx: InlineContext) {
const {
splits,

View File

@ -9,6 +9,7 @@ import * as compile from './compile-testcases';
import * as webdriver from 'selenium-webdriver';
import * as chrome from 'selenium-webdriver/chrome';
import * as path from 'path';
import * as fs from 'fs';
const visitBenchmark = async (tag: string | null, file: string) => {
let driver = new webdriver.Builder()
@ -30,6 +31,29 @@ const visitBenchmark = async (tag: string | null, file: string) => {
return { tag: tag, browser: 'chrome', results: result };
};
export interface Stat {
name: string;
bytes: number;
}
const assetSizeStats = (dir: string): Stat[] => {
let stats: Stat[] = [];
fs.readdir(dir, function(err, files) {
if (err) {
console.log('Error getting directory information.');
} else {
files.forEach(function(file) {
const stat = fs.statSync(path.join(dir, file));
stats.push({
name: path.basename(file),
bytes: stat.size,
});
});
}
});
return stats;
};
const run = async function() {
compile.compileAndTransform('testcases/simple', 'Main.elm', {
prepack: true,
@ -38,13 +62,18 @@ const run = async function() {
prepack: true,
});
const assets = {
bench: assetSizeStats('testcases/bench/output'),
simple: assetSizeStats('testcases/simple/output'),
};
let results = [];
results.push(await visitBenchmark(null, 'testcases/bench/standard.html'));
results.push(
await visitBenchmark('transformed', 'testcases/bench/transformed.html')
);
console.log(markdownNewResults(reformat(results)));
console.log(markdownNewResults(assets, reformat(results)));
};
const markdownResults = (results: any): string => {
@ -78,11 +107,35 @@ const markdownResults = (results: any): string => {
return buffer.join('\n');
};
const markdownNewResults = (results: any): string => {
const markdownNewResults = (
assets: { [key: string]: Stat[] },
results: any
): string => {
let buffer: string[] = [];
buffer.push('# Benchmark results');
buffer.push('');
// List asset sizes
for (let key in assets) {
buffer.push('## ' + key + ' asset overview');
buffer.push('');
assets[key].forEach((item: Stat) => {
buffer.push(
' ' +
item.name.padEnd(40, ' ') +
'' +
humanizeNumber(
roundToDecimal(1, item.bytes / Math.pow(2, 10))
).padStart(10, ' ') +
'kb'
);
});
buffer.push('');
}
buffer.push('');
// List benchmarks
for (let key in results) {
buffer.push('## ' + key);
buffer.push('');
@ -175,8 +228,13 @@ function reformat(results: any): any {
}
// adds commas to the number so its easier to read.
function humanizeNumber(x: string): string {
function humanizeNumber(x: number): string {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
function roundToDecimal(level: number, num: number): number {
let factor: number = Math.pow(10, level);
return Math.round(num * factor) / factor;
}
run();