Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add time options to set loading network speed, latency and message #384

Merged
merged 5 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if the cost exceeds the limit.
that use their own bundler or small npm libraries with many files.
* Can calculate **the time** it would take a browser
to download and **execute** your JS. Time is a much more accurate
and understandable metric compared to the size in bytes.
and understandable metric compared to the size in bytes. Additionally, you can customize it via config for every check with network speed, latency and so on.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but we need more examples in docs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion. I've added the documentation to the time plugin and left the reference in the root readme.

* Calculations include **all dependencies and polyfills**
used in your JS.

Expand Down
Empty file added fixtures/time-latency/index.js
Empty file.
21 changes: 21 additions & 0 deletions fixtures/time-latency/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"private": true,
"name": "time-latency",
"devDependencies": {
"@size-limit/time": ">= 0.0.0",
"size-limit": ">= 0.0.0"
},
"size-limit": [
{
"path": "index.js",
"time": {
"latency": "200 ms"
}
},
{
"time": {
"latency": "2.35 s"
}
}
]
}
Empty file.
21 changes: 21 additions & 0 deletions fixtures/time-network-speed/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"private": true,
"name": "time-network-speed",
"devDependencies": {
"@size-limit/time": ">= 0.0.0",
"size-limit": ">= 0.0.0"
},
"size-limit": [
{
"path": "index.js",
"time": {
"networkSpeed": "20 B"
}
},
{
"time": {
"networkSpeed": "20 kB"
}
}
]
}
2 changes: 1 addition & 1 deletion packages/size-limit/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default async function calc(plugins, config, createSpinner) {
check.passed = check.sizeLimit >= check.size
}
if (typeof check.timeLimit !== 'undefined') {
check.passed = check.timeLimit >= check.time
check.passed = check.timeLimit >= check.totalTime
}
if (check.files && !check.files.length && check.path) {
check.missed = true
Expand Down
6 changes: 4 additions & 2 deletions packages/size-limit/create-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,14 @@ function createHumanReporter(process, isSilentMode = false) {
rows.push(['Size', sizeString, sizeNote])
}
if (typeof check.loadTime !== 'undefined') {
rows.push(['Loading time', formatTime(check.loadTime), 'on slow 3G'])
let description =
(check.time && check.time.loadingMessage) || 'on slow 3G'
rows.push(['Loading time', formatTime(check.loadTime), description])
}
if (typeof check.runTime !== 'undefined') {
rows.push(
['Running time', formatTime(check.runTime), 'on Snapdragon 410'],
['Total time', formatTime(check.time)]
['Total time', formatTime(check.totalTime)]
)
}

Expand Down
26 changes: 24 additions & 2 deletions packages/size-limit/get-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ let OPTIONS = {
name: true,
path: true,
running: 'time',
time: 'time',
uiReports: 'webpack',
webpack: 'webpack'
}
Expand All @@ -42,6 +43,14 @@ function isStringsOrUndefined(value) {
return type === 'undefined' || type === 'string' || isStrings(value)
}

function endsWithMs(value) {
return / ?ms/i.test(value)
}

function endsWithS(value) {
return / ?s/i.test(value)
}

function checkChecks(plugins, checks) {
if (!Array.isArray(checks)) {
throw new SizeLimitError('noArrayConfig')
Expand Down Expand Up @@ -181,9 +190,9 @@ export default async function getConfig(plugins, process, args, pkg) {
if (!check.name) check.name = toName(check.entry || check.files, config.cwd)
if (args.limit) check.limit = args.limit
if (check.limit) {
if (/ ?ms/i.test(check.limit)) {
if (endsWithMs(check.limit)) {
check.timeLimit = parseFloat(check.limit) / 1000
} else if (/ ?s/i.test(check.limit)) {
} else if (endsWithS(check.limit)) {
check.timeLimit = parseFloat(check.limit)
} else {
check.sizeLimit = bytes.parse(check.limit)
Expand Down Expand Up @@ -215,6 +224,19 @@ export default async function getConfig(plugins, process, args, pkg) {
}
check.import = imports
}
if (check.time) {
let { latency, networkSpeed } = check.time
if (latency) {
if (endsWithMs(latency)) {
check.time.latency = parseFloat(latency) / 1000
} else {
check.time.latency = parseFloat(latency) || 0
}
}
if (networkSpeed) {
check.time.networkSpeed = bytes.parse(networkSpeed)
}
}
}

return config
Expand Down
32 changes: 32 additions & 0 deletions packages/size-limit/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,38 @@ export interface Check {
* With `false` it will disable webpack.
*/
webpack?: boolean

/**
* Options for `@size-limit/time` plugin.
*/
time?: TimeOptions
}

/**
* Represents the options for the size-limit check time property to customize `@size-limit/time` plugin.
*/
export interface TimeOptions {
/**
* A network speed to calculate loading time of files.
* It should be a string with a number and unit, separated by a space.
* Format: `100 B`, `10 kB`.
* @default "50 kB"
*/
networkSpeed?: string

/**
* Delay for calculating loading time that simulates network latency
* It should be a string with a number and unit, separated by a space.
* Format: `500 ms`, `1 s`.
* @default: "0"
*/
latency: string

/**
* A message for loading time details
* @default "on slow 3G"
*/
loadingMessage?: string
}

export type SizeLimitConfig = Check[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ exports[`renders list of success checks in silent mode 1`] = `
"
`;

exports[`renders loading time with custom message from time options for every check 1`] = `
"
loading message 1
Size: 10 B
Loading time: 200 ms for ~1000 users per month
Running time: 400 ms on Snapdragon 410
Total time: 1.4 s

loading message 2
Loading time: 200 ms on slow 3G
Running time: 300 ms on Snapdragon 410
Total time: NaN ms

"
`;

exports[`renders result for file with gzip 1`] = `
"
Size limit: 99 B
Expand Down
2 changes: 1 addition & 1 deletion packages/size-limit/test/__snapshots__/run.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ exports[`shows debug 1`] = `
"size": 123,
"loadTime": 0.01,
"runTime": 1,
"time": 1.01,
"totalTime": 1.01,
"passed": true
}
],
Expand Down
49 changes: 37 additions & 12 deletions packages/size-limit/test/create-reporter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ it('renders results', () => {
name: 'limitless',
runTime: 0.5,
size: 10,
time: 0.6
totalTime: 0.6
},
{
loadTime: 1,
Expand All @@ -40,7 +40,7 @@ it('renders results', () => {
runTime: 2,
size: 102400,
sizeLimit: 102400,
time: 3
totalTime: 3
},
{
gzip: false,
Expand All @@ -49,8 +49,8 @@ it('renders results', () => {
passed: true,
runTime: 2,
size: 102400,
time: 3,
timeLimit: 4
timeLimit: 4,
totalTime: 3
}
]
})
Expand All @@ -69,7 +69,7 @@ it('renders list of success checks in silent mode', () => {
name: 'limitless',
runTime: 0.5,
size: 10,
time: 0.6
totalTime: 0.6
},
{
loadTime: 1,
Expand All @@ -78,7 +78,7 @@ it('renders list of success checks in silent mode', () => {
runTime: 2,
size: 102400,
sizeLimit: 102400,
time: 3
totalTime: 3
}
]
},
Expand Down Expand Up @@ -132,7 +132,7 @@ it('renders list of failed and success checks in silent mode', () => {
name: 'limitless',
runTime: 0.5,
size: 10,
time: 0.6
totalTime: 0.6
},
{
loadTime: 1,
Expand All @@ -141,7 +141,7 @@ it('renders list of failed and success checks in silent mode', () => {
runTime: 2,
size: 102400,
sizeLimit: 102400,
time: 3
totalTime: 3
},
{
name: 'big fail',
Expand Down Expand Up @@ -291,8 +291,8 @@ it('renders config-less result', () => {
passed: false,
runTime: 0.3,
size: 1000,
time: 0.5,
timeLimit: 0.5
timeLimit: 0.5,
totalTime: 0.5
}
],
failed: true
Expand All @@ -317,8 +317,8 @@ it('renders JSON results', () => {
path: '/b',
runTime: 0.3,
size: 1000,
time: 0.5,
timeLimit: 10
timeLimit: 10,
totalTime: 0.5
}
],
failed: true
Expand Down Expand Up @@ -372,3 +372,28 @@ it('renders Webpack stats help message', () => {
})
).toMatchSnapshot()
})

it('renders loading time with custom message from time options for every check', () => {
expect(
results(['time'], {
checks: [
{
loadTime: 0.2,
name: 'loading message 1',
passed: true,
runTime: 0.4,
size: 10,
time: { loadingMessage: 'for ~1000 users per month' },
totalTime: 1.4
},
{
loadTime: 0.2,
name: 'loading message 2',
passed: true,
runTime: 0.3,
time: { loadingMessage: '' }
}
]
})
).toMatchSnapshot()
})
42 changes: 42 additions & 0 deletions packages/size-limit/test/get-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,48 @@ it('normalizes import', async () => {
})
})

it('normalizes networkSpeed option for time plugin', async () => {
let cwd = 'time-network-speed'
expect(await check(cwd)).toEqual({
checks: [
{
files: [fixture(cwd, 'index.js')],
name: 'index.js',
path: 'index.js',
time: { networkSpeed: 20 }
},
{
files: [fixture(cwd, 'index.js')],
name: 'index.js',
time: { networkSpeed: 20000 }
}
],
configPath: 'package.json',
cwd: fixture(cwd)
})
})

it('normalizes latency option for time plugin', async () => {
let cwd = 'time-latency'
expect(await check(cwd)).toEqual({
checks: [
{
files: [fixture(cwd, 'index.js')],
name: 'index.js',
path: 'index.js',
time: { latency: 0.2 }
},
{
files: [fixture(cwd, 'index.js')],
name: 'index.js',
time: { latency: 2.35 }
}
],
configPath: 'package.json',
cwd: fixture(cwd)
})
})

const allConfigFileExtensions = ['mjs', 'js', 'cjs', 'ts', 'mts', 'cts']
const exportTypes = [
{ exportSyntax: 'export default', moduleType: 'esm' },
Expand Down
Loading