Профилирование помогает понять реальное влияние timeago.js на производительность приложения и выявить узкие места.
| Инструмент | Применение |
|---|---|
| Chrome Performance | Таймеры, reflow, CPU-нагрузка |
| Chrome Memory | Heap snapshot, утечки памяти |
| Chrome Coverage | Неиспользуемый JavaScript |
| Lighthouse | Комплексная оценка производительности |
| Web Vitals (CWV) | INP, CLS, LCP |
performance.now() |
Точное время выполнения кода |
Шаги:
Что искать:
// Инструмент диагностики
let renderCount = 0;
let cancelCount = 0;
let activeTimers = 0;
const originalRender = import('timeago.js').then(m => m.render);
const originalCancel = import('timeago.js').then(m => m.cancel);
// Обёртки для подсчёта
window.__timeagoStats = {
get active() { return activeTimers; },
get renders() { return renderCount; },
get cancels() { return cancelCount; },
};
import { format } from 'timeago.js';
function benchmarkFormat(iterations = 10000) {
const dates = Array.from({ length: iterations }, (_, i) =>
Date.now() - i * 1000
);
const start = performance.now();
dates.forEach(d => format(d, 'ru'));
const elapsed = performance.now() - start;
console.log(`${iterations} вызовов format: ${elapsed.toFixed(2)}ms`);
console.log(`Среднее: ${(elapsed / iterations).toFixed(4)}ms на вызов`);
}
benchmarkFormat();
Процедура:
HTMLTimeElement с положительным “# New”.Если количество HTMLTimeElement растёт —
cancel вызывается некорректно.
timeago.js меняет textContent, что может вызвать CLS
если:
Замер CLS:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.hadRecentInput) continue;
console.log('CLS entry:', entry.value);
}
});
observer.observe({ type: 'layout-shift', buffered: true });
Предотвращение:
time.time-ago {
min-width: 10ch;
display: inline-block;
}
import { format } from 'timeago.js';
let updateCount = 0;
const startTime = performance.now();
setInterval(() => {
document.querySelectorAll('[datetime]').forEach(el => {
const prev = el.textContent;
const next = format(el.getAttribute('datetime'), 'ru');
if (prev !== next) {
el.textContent = next;
updateCount++;
}
});
const elapsed = (performance.now() - startTime) / 1000;
console.log(`DOM updates/sec: ${(updateCount / elapsed).toFixed(1)}`);
}, 5000);
// monitor-worker.js
let elements = [];
let lastStats = {};
setInterval(() => {
const now = Date.now();
const stats = {
timestamp: now,
elementCount: elements.length,
};
self.postMessage(stats);
}, 5000);
npx lighthouse https://your-site.com --view
Проверять:
render не должна быть в critical path.