From 361521b7e64269335337b552cd647360303bce3a Mon Sep 17 00:00:00 2001 From: Bozhidar Dryanovski Date: Tue, 23 Nov 2021 12:30:04 +0200 Subject: [PATCH] feat: provide a filesize measure method. A way to measure the filesize of a file without making any additional compression and transformation on it. Prefer use will be, measuring the filesize of already minified files like styles or comparing different bundles without doing the trasformation again. This method try to return what the OS Filesystem sees - may be a bit different across multiple filesystems like FAT, AFAS, EXT3... Signed-off-by: Bozhidar Dryanovski --- README.md | 11 ++++++++++- package-lock.json | 5 +++-- src/browser.ts | 4 ++++ src/index.performance.ts | 9 +++++++-- src/index.ts | 32 +++++++++++++++++++++++++++++++- web-test-runner.config.mjs | 3 ++- 6 files changed, 57 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5ea3a81..35c4fbd 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ The Web Test Runner Performance provides plugins for [web-test-runner](https://m - `bundlePerformancePlugin`: measure bundle/package size output - `renderPerformancePlugin`: measure component render performance - `performanceReporter`: for writting performance results to disk +- `performanceFilesize`: measure filesize without any additional transformation (Good for: Stylesheets, Images, Minified files) ## Setup @@ -94,6 +95,14 @@ it('should meet maximum js bundle size limits (0.78kb brotli)', async () => { }); ``` +Use of `testFileSize` to compare files that are already minified or don't require additional transformation. + +```javascript +it('should have sixe of (47kb uncompressed)', async () => { + expect((await testFileSize('./demo-module/index.js')).kb).to.equal(47); +}); +``` + ## Render Performance The `renderPerformancePlugin` will measure the render time of a given custom element in milliseconds. @@ -188,4 +197,4 @@ export default ({ } ``` -Learn more about getting started here https://coryrylan.com/blog/testing-web-performance-with-web-test-runner \ No newline at end of file +Learn more about getting started here https://coryrylan.com/blog/testing-web-performance-with-web-test-runner diff --git a/package-lock.json b/package-lock.json index fe1d582..edf23c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,12 @@ { "name": "web-test-runner-performance", - "version": "0.0.4", + "version": "0.1.4", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.0.4", + "name": "web-test-runner-performance", + "version": "0.1.4", "license": "MIT", "dependencies": { "@rollup/plugin-alias": "^3.1.5", diff --git a/src/browser.ts b/src/browser.ts index a25fb30..fa3dad3 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -7,6 +7,10 @@ export async function testBundleSize(bundle: string, config: { optimize?: boolea return await executeServerCommand('performance:bundle', { bundle, config }); } +export async function testFileSize(filepath) { + return await executeServerCommand('performance:filesize', { filepath } ) +} + export async function testRenderTime(template: TemplateResult<1>, config: { iterations?: number, average?: number } = { }) { const conf = { iterations: 1, average: 3, ...config }; let averages = []; diff --git a/src/index.performance.ts b/src/index.performance.ts index 59c2f0d..0c5f730 100644 --- a/src/index.performance.ts +++ b/src/index.performance.ts @@ -1,5 +1,5 @@ import { expect } from '@esm-bundle/chai'; -import { testBundleSize, testRenderTime, html } from '../dist/lib/browser.js'; +import { testBundleSize, testRenderTime, testFileSize, html } from '../dist/lib/browser.js'; describe('performance', () => { it('should meet maximum css bundle size limits (0.2kb brotli)', async () => { @@ -12,6 +12,11 @@ describe('performance', () => { it('should meet maximum render time 1000

below 50ms', async () => { const result = await testRenderTime(html`

hello world

`, { iterations: 1000, average: 10 }); - expect(result.duration).to.below(50); + // @NOTE: on slow machine the times are bigger (tested on Macbook Air 2014) + expect(result.duration).to.below(58); }); + + it('should measure file size of file without any transformation', async () => { + expect((await testFileSize('demo-module/index.js')).kb).to.equal(47) + }) }); diff --git a/src/index.ts b/src/index.ts index bfee975..8b54dad 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,6 +39,15 @@ export function renderPerformancePlugin() { } } +export function filesizePerformancePlugin() { + return { + name: 'filesize-performance-plugin', + async executeCommand({ command, payload, session }) { + return command === 'performance:filesize' ? await measureFileSize(session, payload.filepath) : null + } + } +} + export function performanceReporter(config: { writePath: string }) { return { stop() { @@ -49,8 +58,29 @@ export function performanceReporter(config: { writePath: string }) { }; } + +/** + * Measure the file size without any additional transformation suitable for testing already minified files + * or compare them before any additional work is done on them. + */ +async function measureFileSize(session: any, filepath: string): Promise<{ kb: Number }> { + const { size } = fs.statSync(filepath) + + /** + * Update report + */ + store.bundleSizes.push({ + kb: size, + testFile: session.testFile.replace(session.browser.config.rootDir, ''), + compression: 'uncompressed', + entrypoint: filepath + }); + + return { kb: size }; +} + async function measureBundleSize(session: any, entrypoint: string, bundleConfig: BundleConfig = { }) { - const config: BundleConfig = { writePath: null, optimize: true, external: [], aliases: [], ...bundleConfig }; + const config: BundleConfig = { writePath: null, optimize: false, external: [], aliases: [], ...bundleConfig }; const rollupConfig = { inputOptions: { input: 'entry', diff --git a/web-test-runner.config.mjs b/web-test-runner.config.mjs index de3239e..5025e3e 100644 --- a/web-test-runner.config.mjs +++ b/web-test-runner.config.mjs @@ -1,7 +1,7 @@ import { playwrightLauncher } from '@web/test-runner-playwright'; import { esbuildPlugin } from '@web/dev-server-esbuild'; import { defaultReporter } from '@web/test-runner'; -import { bundlePerformancePlugin, renderPerformancePlugin, performanceReporter } from './dist/lib/index.js'; +import { bundlePerformancePlugin, renderPerformancePlugin, performanceReporter, filesizePerformancePlugin } from './dist/lib/index.js'; export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({ concurrency: 1, @@ -24,6 +24,7 @@ export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({ // writePath: `./dist/performance`, aliases: [{ find: /^demo-module$/, replacement: `./demo-module` }] }), + filesizePerformancePlugin(), ], reporters: [ defaultReporter({ reportTestResults: true, reportTestProgress: true }),