Рома Ахмадуллин
Дром
Дока — документация про веб
Web Vitals: что это и как мы их собираем?
Оптимизируйте в первую очередь широкоиспользуемые фичи.
// MODULE_DATA
{
"header": {
// данные для шапки
},
"footer": {
// данные для футера
},
// остальные данные для страницы
}
<script
type="text/javascript"
src="module-a.js"
>
</script>
<script
type="text/javascript"
src="module-a.js"
data-module="module-a"
data-module-data="<MODULE_DATA>"
>
</script>
<script
type="text/javascript"
src="module-a.js"
data-module="module-a"
data-module-data="<MODULE_DATA>"
>
</script>
<script
type="text/javascript"
src="module-a.js"
data-module="module-a"
data-module-data="<MODULE_DATA>"
>
</script>
<script
type="text/javascript"
src="module-a.js"
data-module="module-a"
data-module-data="<MODULE_DATA>"
>
</script>
<script
type="text/javascript"
src="module-a.js"
>
</script>
<script
type="application/json"
data-module="module-a"
>
<MODULE_DATA>
</script>
<script
type="text/javascript"
src="module-a.js"
>
</script>
<script
type="application/json"
data-module="module-a"
>
<MODULE_DATA>
</script>
<script
type="text/javascript"
src="module-a.js"
>
</script>
<script
type="application/json"
data-module="module-a"
>
<MODULE_DATA>
</script>
<link
href="x1.jpg"
rel="preload"
as="image"
imagesrcset="x1.jpg 1x, x2.jpg 2x"
fetchpriority="high"
>
<img
data-lazy="true"
data-srcset="x1.jpg 1x, x2.jpg 2x"
data-src="x1.jpg"
/>
<img
data-lazy="true"
data-srcset="x1.jpg 1x, x2.jpg 2x"
data-src="x1.jpg"
/>
<img
data-lazy="true"
data-srcset="x1.jpg 1x, x2.jpg 2x"
data-src="x1.jpg"
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
<img
data-lazy="true"
data-srcset="x1.jpg 1x, x2.jpg 2x"
data-src="x1.jpg"
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
<noscript>
<img
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
</noscript>
<img
data-lazy="true"
data-srcset="x1.jpg 1x, x2.jpg 2x"
data-src="x1.jpg"
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
<noscript>
<img
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
</noscript>
<img
data-lazy="true"
data-srcset="x1.jpg 1x, x2.jpg 2x"
data-src="x1.jpg"
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
<noscript>
<img
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
</noscript>
loading="lazy"
<img
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
/>
<img
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
loading="lazy"
/>
<img
srcset="x1.jpg 1x, x2.jpg 2x"
src="x1.jpg"
loading="lazy"
/>
<svg>
...
</svg>
<svg>
...
</svg>
<img src="icon.svg" />
<svg>
...
</svg>
<img src="icon.svg" />
.icon-button {
mask-image: url(icon.svg);
background-color: gray;
}
const setAverageColorForImages = (images) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
for (const img of images) {
ctx.drawImage(img, 0, 0, 1, 1);
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
img.dataset.avgColor = `rgb(${r},${g},${b})`;
}
};
const setAverageColorForImages = (images) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
for (const img of images) {
ctx.drawImage(img, 0, 0, 1, 1);
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
img.dataset.avgColor = `rgb(${r},${g},${b})`;
}
};
const setAverageColorForImages = (images) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
for (const img of images) {
ctx.drawImage(img, 0, 0, 1, 1);
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
img.dataset.avgColor = `rgb(${r},${g},${b})`;
}
};
const setAverageColorForImages = (images) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1;
canvas.height = 1;
for (const img of images) {
ctx.drawImage(img, 0, 0, 1, 1);
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
img.dataset.avgColor = `rgb(${r},${g},${b})`;
}
};
const setAverageColorForImages = (images) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
canvas.width = 1;
canvas.height = 1;
for (const img of images) {
ctx.drawImage(img, 0, 0, 1, 1);
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
img.dataset.avgColor = `rgb(${r},${g},${b})`;
}
};
const reviewsData = getDataFromBackend();
console.log(reviewsData[0]);
// photoUrl: 'img.jpg'
// photoAverageColor: 'rgb(130, 20, 94)'
const reviewsData = getDataFromBackend();
console.log(reviewsData[0]);
// photoUrl: 'img.jpg'
// photoAverageColor: 'rgb(130, 20, 94)'
const reviewsData = getDataFromBackend();
console.log(reviewsData[0]);
// photoUrl: 'img.jpg'
// photoAverageColor: 'rgb(130, 20, 94)'
import { onINP } from 'web-vitals';
onINP(sendToBackend);
import { onINPAttribution } from 'web-vitals/attribution';
onINPAttribution(sendToBackend);
const sendToBackend = (inpMetricData) => {
const {
value, // значение INP
attribution: {
interactionType, // 'pointer' | 'keyboard'
interactionTarget, // CSS-селектор триггера
inputDelay, // задержка обработки
processingDuration, // время выполнения обработчиков
presentationDelay, // задержка отрисовки
loadState, // статус загрузки страницы
},
} = inpMetricData;
logToBackend(...);
};
<a
href="/123456/"
class="link-to-bulletin"
data-stats-name="link-to-bulletin"
data-stats-track-click="true"
/>
<a
href="/all/"
class="link-to-list"
data-stats-name="link-to-list"
data-stats-track-click="true"
/>
<a
href="/reviews/"
class="link-to-reviews"
data-stats-name="link-to-reviews"
data-stats-track-click="true"
/>
<a
href="/123456/"
class="link-to-bulletin"
data-stats-name="link-to-bulletin"
data-stats-track-click="true"
/>
<a
href="/all/"
class="link-to-list"
data-stats-name="link-to-list"
data-stats-track-click="true"
/>
<a
href="/reviews/"
class="link-to-reviews"
data-stats-name="link-to-reviews"
data-stats-track-click="true"
/>
- alert: InpExitedGreenZone
annotations:
message: '[RUM] INP вышел из зеленой зоны.'
summary: 'INP превысил порог в 200 ms в {{ $labels.app_slug }} на {{ $labels.view_type }}'
dashboard: 'ссылка на дашборд'
runbook: 'ссылка на ранбук'
expr: |
histogram_quantile(
0.75,
sum by (le, app_slug, view_type) (
rate(
frontend_rum_inp_histogram_bucket[1d]
)
)
) > 200
for: 3d