-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathserver.ts
130 lines (103 loc) · 2.76 KB
/
server.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* eslint no-console: 0 */
'use strict'
import { performance } from 'perf_hooks'
import express from 'express'
import tracealyzer from 'tracealyzer'
import type { Browser } from 'playwright'
import { Server } from 'http'
type TracealyticsResults = ReturnType<typeof tracealyzer>
export interface FPSStatsEntry {
type: string
timeStamp: number
meta: {
details: {
FPS: number
isFinal: boolean
}
}
}
export interface ProcessedFPSEntry {
FPS: number
timestamp: number
isFinal: boolean
}
export interface RenderResult {
id: string
phase: 'update' | 'mount'
actualTime: number
baseTime: number
startTime: number
commitTime: number
}
export type PageStatsResult = Awaited<ReturnType<typeof capturePageStats>>
declare global {
interface Window {
getFpsStats: () => FPSStatsEntry[]
renderResults: RenderResult[]
}
}
const timeout = (ms: number) => new Promise((res) => setTimeout(res, ms))
export function runServer(port: number, sources: string): Promise<Server> {
const app = express()
app.use(express.static(sources))
return new Promise((resolve, reject) => {
// eslint-disable-line
app.use((err) => {
reject(err)
})
const server = app.listen(port, () => {
//console.log(`Server started on ${port}`);
resolve(server)
})
})
}
export async function capturePageStats(
browser: Browser,
url: string,
traceFilename: string | null,
delay = 30000
) {
const page = await browser.newPage()
await page.evaluate(() => {
window.performance.setResourceTimingBufferSize(1000000)
})
const context = await browser.newContext()
let fpsValues: ProcessedFPSEntry[]
let traceMetrics: TracealyticsResults | undefined = undefined
const trace = !!traceFilename
//console.log(`Loading page for version ${version}...`)
if (trace) {
page.on('load', async () => {
await timeout(1000)
context.tracing.start({ name: traceFilename })
})
}
await page.goto(url)
const start = performance.now()
if (trace) {
await timeout(delay + 1000)
await context.tracing.stop()
traceMetrics = tracealyzer(traceFilename)
} else {
await timeout(delay)
}
const end = performance.now()
const fpsStatsEntries: FPSStatsEntry[] =
JSON.parse(
await page.evaluate(() => {
return JSON.stringify(window.getFpsStats())
})
) || []
const reactTimingEntries: RenderResult[] =
JSON.parse(
await page.evaluate(() => {
return JSON.stringify(window.renderResults)
})
) || []
fpsValues = fpsStatsEntries.map((entry) => {
const { FPS, isFinal } = entry.meta.details
return { FPS, timestamp: entry.timeStamp, isFinal }
})
await page.close()
return { fpsValues, traceMetrics, start, end, reactTimingEntries }
}