Skip to content

Commit

Permalink
Merge branch 'master' into release-dependabot-upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
kikoruiz committed Nov 29, 2023
2 parents 0961166 + 859a260 commit ca0adf4
Show file tree
Hide file tree
Showing 8 changed files with 397 additions and 71 deletions.
9 changes: 9 additions & 0 deletions packages/sui-polyfills/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# CHANGELOG

# 1.19.0 (2023-11-23)


### Features

* **packages/sui-polyfills:** add FlatMap polyfill ([fe6c9db](https://github.com/SUI-Components/sui/commit/fe6c9db2cd1883d34c070db288fce4a5533efe65))



# 1.18.0 (2023-05-04)


Expand Down
2 changes: 1 addition & 1 deletion packages/sui-polyfills/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@s-ui/polyfills",
"version": "1.18.0",
"version": "1.19.0",
"description": "Common polyfills for your project",
"main": "src/index.js",
"scripts": {},
Expand Down
1 change: 1 addition & 0 deletions packages/sui-polyfills/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ require('core-js/features/array/fill')
require('core-js/features/array/find-index')
require('core-js/features/array/find')
require('core-js/features/array/flat')
require('core-js/features/array/flat-map')
require('core-js/features/array/from')
require('core-js/features/array/includes')
require('core-js/features/array/is-array')
Expand Down
13 changes: 13 additions & 0 deletions packages/sui-react-web-vitals/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# CHANGELOG

# 2.0.0 (2023-11-27)


### Features

* **packages/sui-react-web-vitals:** add presentationTime comment ([3aaee12](https://github.com/SUI-Components/sui/commit/3aaee12327952c0fa6919a424fb36c4ac2d344c8))
* **packages/sui-react-web-vitals:** add sub inp metrics to cwv ([3ddbd34](https://github.com/SUI-Components/sui/commit/3ddbd34428e23b7b384780c21d6a84e58ef44fb3))
* **packages/sui-react-web-vitals:** minor updates ([55f1eaf](https://github.com/SUI-Components/sui/commit/55f1eaf0c2779522fef4e1421c02197aa32909d4))
* **packages/sui-react-web-vitals:** update doc ([52bd64d](https://github.com/SUI-Components/sui/commit/52bd64d4aea798efe2ed8b46d645ef96258c2063))
* **packages/sui-react-web-vitals:** update test and props ([1bd4347](https://github.com/SUI-Components/sui/commit/1bd4347296bfebb1e7b48e6ee3c59d7a88e2c58d))



# 1.12.0 (2023-11-07)


Expand Down
6 changes: 3 additions & 3 deletions packages/sui-react-web-vitals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,16 @@ export default function App() {
}
```

#### Allowed pathnames
#### Allowed routes

Use `pathnames` prop if you only want to track a set of pathnames
Use `allowed` prop if you only want to track a set of pathnames or route ids

```jsx
import WebVitalsReporter from '@s-ui/react-web-vitals'

export default function App() {
return (
<WebVitalsReporter pathnames={['/products/:id']}>
<WebVitalsReporter allowed={['/products/:id', 'search']}>
<main />
</WebVitalsReporter>
)
Expand Down
2 changes: 1 addition & 1 deletion packages/sui-react-web-vitals/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@s-ui/react-web-vitals",
"version": "1.12.0",
"version": "2.0.0",
"description": "",
"type": "module",
"main": "lib/index.js",
Expand Down
154 changes: 88 additions & 66 deletions packages/sui-react-web-vitals/src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {useContext, useEffect, useRef} from 'react'

import PropTypes from 'prop-types'
import * as reporter from 'web-vitals/attribution'
import * as cwv from 'web-vitals/attribution'

import SUIContext from '@s-ui/react-context'
import useMount from '@s-ui/react-hooks/lib/useMount/index.js'
Expand All @@ -16,6 +16,12 @@ export const METRICS = {
TTFB: 'TTFB'
}

const INP_METRICS = {
ID: 'ID',
PT: 'PT',
PD: 'PD'
}

// https://github.com/GoogleChrome/web-vitals#metric
const RATING = {
GOOD: 'good',
Expand All @@ -25,41 +31,20 @@ const RATING = {

const DEFAULT_METRICS_REPORTING_ALL_CHANGES = [METRICS.CLS, METRICS.FID, METRICS.INP, METRICS.LCP]

const DEFAULT_CWV_THRESHOLDS = {
[METRICS.CLS]: 100,
[METRICS.FCP]: 1800,
[METRICS.FID]: 100,
[METRICS.INP]: 200,
[METRICS.LCP]: 2500,
[METRICS.TTFB]: 800
}

export const DEVICE_TYPES = {
DESKTOP: 'desktop',
TABLET: 'tablet',
MOBILE: 'mobile'
}

const getNormalizedPathname = pathname => {
return pathname.replace(/[^a-z0-9]/gi, '')
}

const getPathname = route => {
return route?.path || route?.regexp?.toString()
}

const getHasPathOnRoute = route => {
return Boolean(route?.path)
}

export default function WebVitalsReporter({
children,
reporter = cwv,
children = null,
deviceType,
metrics = Object.values(METRICS),
metricsAllChanges = DEFAULT_METRICS_REPORTING_ALL_CHANGES,
onReport,
pathnames,
thresholds = DEFAULT_CWV_THRESHOLDS
allowed = []
}) {
const {logger, browser} = useContext(SUIContext)
const router = useRouter()
Expand All @@ -76,6 +61,10 @@ export default function WebVitalsReporter({
return route?.id
}

const getPathname = route => {
return route?.path || route?.regexp?.toString().replace(/[^a-z0-9]/gi, '')
}

const getDeviceType = () => {
return deviceType || browser?.deviceType
}
Expand All @@ -91,51 +80,86 @@ export default function WebVitalsReporter({
}
}

const computeINPMetrics = entry => {
// RenderTime is an estimate because duration is rounded and may get rounded down.
// In rare cases, it can be less than processingEnd and that breaks performance.measure().
// Let's ensure it's at least 4ms in those cases so you can barely see it.
const presentationTime = Math.max(entry.processingEnd + 4, entry.startTime + entry.duration)

return {
[INP_METRICS.ID]: Math.round(entry.processingStart - entry.startTime, 0),
[INP_METRICS.PT]: Math.round(entry.processingEnd - entry.processingStart, 0),
[INP_METRICS.PD]: Math.round(presentationTime - entry.processingEnd, 0)
}
}

const handleAllChanges = ({attribution, name, rating, value}) => {
const amount = name === METRICS.CLS ? value * 1000 : value
const pathname = getPathname(route)
const hasPathOnRoute = getHasPathOnRoute(route)
const isExcluded = !pathname || (Array.isArray(pathnames) && !pathnames.includes(pathname))
const isAllowed = allowed.includes(pathname)

if (isExcluded || !logger?.cwv || rating === RATING.GOOD) return
if (!isAllowed || !logger?.cwv || rating === RATING.GOOD) return

const target = getTarget({name, attribution})

logger.cwv({
name: `cwv.${name.toLowerCase()}`,
amount,
path: hasPathOnRoute ? pathname : getNormalizedPathname(pathname),
path: pathname,
target,
loadState: attribution.loadState,
...(attribution.eventType && {eventType: attribution.eventType}),
visibilityState: document.visibilityState
visibilityState: document.visibilityState,
...(attribution.eventType && {eventType: attribution.eventType})
})
}

const handleChange = ({name, value}) => {
const handleChange = ({name, value, entries}) => {
const onReport = onReportRef.current
const pathname = getPathname(route)
const hasPathOnRoute = getHasPathOnRoute(route)
const routeid = getRouteid()
const type = getDeviceType()
const isExcluded = !pathname || (Array.isArray(pathnames) && !pathnames.includes(pathname))
const isAllowed = allowed.includes(pathname) || allowed.includes(routeid)

if (isExcluded) return
if (!isAllowed) return

if (onReport) {
onReport({
name,
amount: value,
pathname: hasPathOnRoute ? pathname : getNormalizedPathname(pathname),
pathname,
routeid,
type
type,
entries
})
return
}

if (!logger?.distribution) return

const amount = name === METRICS.CLS ? value * 1000 : value
const tags = [
...(routeid
? [
{
key: 'routeid',
value: routeid
}
]
: [
{
key: 'pathname',
value: pathname
}
]),
...(type
? [
{
key: 'type',
value: type
}
]
: [])
]

logger.distribution({
name: 'cwv',
Expand All @@ -145,33 +169,37 @@ export default function WebVitalsReporter({
key: 'name',
value: name.toLowerCase()
},
{
key: 'pathname',
value: hasPathOnRoute ? pathname : getNormalizedPathname(pathname)
},
...(routeid
? [
{
key: 'routeid',
value: routeid
}
]
: []),
...(type
? [
{
key: 'type',
value: type
}
]
: [])
...tags
]
})

if (name === METRICS.INP) {
entries.forEach(entry => {
const metrics = computeINPMetrics(entry)

Object.keys(metrics).forEach(name => {
logger.distribution({
name: 'cwv',
amount: metrics[name],
tags: [
{
key: 'name',
value: name.toLowerCase()
},
...tags
]
})
})
})
}
}

metrics.forEach(metric => {
reporter[`on${metric}`](handleChange)
if (metricsAllChanges.includes(metric)) reporter[`on${metric}`](handleAllChanges, {reportAllChanges: true})

if (metricsAllChanges.includes(metric)) {
reporter[`on${metric}`](handleAllChanges, {reportAllChanges: true})
}
})
})

Expand Down Expand Up @@ -200,13 +228,7 @@ WebVitalsReporter.propTypes = {
*/
onReport: PropTypes.func,
/**
* An optional array of pathnames that you want to track
*/
pathnames: PropTypes.arrayOf(PropTypes.string),
/**
* An object with METRICS as keys and thresholds as values
* Thresholds by default are those above which Google considers the page as "needs improvement"
* Lower thresholds could be set for fine-tuning, higher thresholds could be set for less noise when reporting all changes
* An optional array of pathnames or route ids that you want to track
*/
thresholds: PropTypes.object
allowed: PropTypes.arrayOf(PropTypes.string)
}
Loading

0 comments on commit ca0adf4

Please sign in to comment.