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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ if the cost exceeds the limit.
* 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.
Additionally, you can [customize time plugin] via config
for every check with network speed, latency and so on.
* Calculations include **all dependencies and polyfills**
used in your JS.

Expand Down Expand Up @@ -50,6 +52,7 @@ We are using [Statoscope] for this analysis.
[Statoscope]: https://github.com/statoscope/statoscope
[cult-img]: http://cultofmartians.com/assets/badges/badge.svg
[cult]: http://cultofmartians.com/tasks/size-limit-config.html
[customize time plugin]: https://github.com/ai/size-limit/packages/time#customize-network-speed

## Who Uses Size Limit

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