chrome.loadTimes()
는 개발자가 실제 사이트의 성능을 더 잘 이해할 수 있도록 로드 측정항목과 네트워크 정보를 개발자에게 노출하는 비표준 API입니다.
이 API는 2009년에 구현되었으므로 보고하는 모든 유용한 정보는 다음과 같은 표준화된 API에서 확인할 수 있습니다.
- 탐색 시간 2
- 페인트 타이밍
- Navigation Timing 2 및 Resource Timing 2에
nextHopProtocol
를 추가했습니다.
이러한 표준화된 API는 여러 브라우저 공급업체에서 구현하고 있습니다. 이에 따라 Chrome 64에서 chrome.loadTimes()
가 지원 중단됩니다.
지원 중단된 API
chrome.loadTimes()
함수는 모든 로드 및 네트워크 정보가 포함된 단일 객체를 반환합니다. 예를 들어 다음 객체는 www.google.com에서 chrome.loadTimes()
를 호출한 결과입니다.
{
"requestTime": 1513186741.847,
"startLoadTime": 1513186741.847,
"commitLoadTime": 1513186742.637,
"finishDocumentLoadTime": 1513186742.842,
"finishLoadTime": 1513186743.582,
"firstPaintTime": 1513186742.829,
"firstPaintAfterLoadTime": 0,
"navigationType": "Reload",
"wasFetchedViaSpdy": true,
"wasNpnNegotiated": true,
"npnNegotiatedProtocol": "h2",
"wasAlternateProtocolAvailable": false,
"connectionInfo": "h2"
}
표준화된 대체
이제 표준화된 API를 사용하여 위의 각 값을 찾을 수 있습니다. 다음 표는 각 값을 표준화된 API에 매칭하며, 아래 섹션에서는 이전 API의 각 값을 최신 등가 항목으로 가져오는 방법에 관한 코드 예시를 보여줍니다.
특성 chrome.loadTimes() 개
| 표준화된 API 대체 |
---|---|
requestTime |
탐색 시간 2 |
startLoadTime |
탐색 타이밍 2 |
commitLoadTime |
탐색 타이밍 2 |
finishDocumentLoadTime |
탐색 시간 2 |
finishLoadTime |
탐색 시간 2 |
firstPaintTime |
페인트 타이밍 |
firstPaintAfterLoadTime |
해당 사항 없음 |
navigationType |
탐색 시간 2 |
wasFetchedViaSpdy |
탐색 시간 2 |
wasNpnNegotiated |
탐색 타이밍 2 |
npnNegotiatedProtocol |
탐색 시간 2 |
wasAlternateProtocolAvailable |
해당 사항 없음 |
connectionInfo |
탐색 타이밍 2 |
아래 코드 예시는 chrome.loadTimes()
에서 반환하는 값과 동일한 값을 반환합니다. 하지만 새 코드의 경우 이러한 코드 예시를 사용하지 않는 것이 좋습니다. 이는 chrome.loadTimes()
가 에포크 시간으로 초 단위의 시간 값을 제공하는 반면, 새 성능 API는 일반적으로 페이지의 시간 출처를 기준으로 밀리초 단위의 값을 보고하기 때문입니다. 이는 성능 분석에 더 유용합니다.
또한 여러 예에서는 Performance Timeline 2 API (예: performance.getEntriesByType()
)를 선호하지만 더 광범위한 브라우저 지원으로 이전 Navigation Timing 1 API의 대체를 제공합니다. 앞으로는 Performance Timeline API를 사용하는 것이 좋으며 일반적으로 더 높은 정밀도로 보고됩니다.
requestTime
function requestTime() {
// If the browser supports the Navigation Timing 2 and HR Time APIs, use
// them, otherwise fall back to the Navigation Timing 1 API.
if (window.PerformanceNavigationTiming && performance.timeOrigin) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return (ntEntry.startTime + performance.timeOrigin) / 1000;
} else {
return performance.timing.navigationStart / 1000;
}
}
startLoadTime
function startLoadTime() {
// If the browser supports the Navigation Timing 2 and HR Time APIs, use
// them, otherwise fall back to the Navigation Timing 1 API.
if (window.PerformanceNavigationTiming && performance.timeOrigin) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return (ntEntry.startTime + performance.timeOrigin) / 1000;
} else {
return performance.timing.navigationStart / 1000;
}
}
commitLoadTime
function commitLoadTime() {
// If the browser supports the Navigation Timing 2 and HR Time APIs, use
// them, otherwise fall back to the Navigation Timing 1 API.
if (window.PerformanceNavigationTiming && performance.timeOrigin) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return (ntEntry.responseStart + performance.timeOrigin) / 1000;
} else {
return performance.timing.responseStart / 1000;
}
}
finishDocumentLoadTime
function finishDocumentLoadTime() {
// If the browser supports the Navigation Timing 2 and HR Time APIs, use
// them, otherwise fall back to the Navigation Timing 1 API.
if (window.PerformanceNavigationTiming && performance.timeOrigin) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return (ntEntry.domContentLoadedEventEnd + performance.timeOrigin) / 1000;
} else {
return performance.timing.domContentLoadedEventEnd / 1000;
}
}
finishLoadTime
function finishLoadTime() {
// If the browser supports the Navigation Timing 2 and HR Time APIs, use
// them, otherwise fall back to the Navigation Timing 1 API.
if (window.PerformanceNavigationTiming && performance.timeOrigin) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return (ntEntry.loadEventEnd + performance.timeOrigin) / 1000;
} else {
return performance.timing.loadEventEnd / 1000;
}
}
firstPaintTime
function firstPaintTime() {
if (window.PerformancePaintTiming) {
const fpEntry = performance.getEntriesByType('paint')[0];
return (fpEntry.startTime + performance.timeOrigin) / 1000;
}
}
firstPaintAfterLoadTime
function firstPaintTimeAfterLoad() {
// This was never actually implemented and always returns 0.
return 0;
}
navigationType
function navigationType() {
if (window.PerformanceNavigationTiming) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return ntEntry.type;
}
}
wasFetchedViaSpdy
function wasFetchedViaSpdy() {
// SPDY is deprecated in favor of HTTP/2, but this implementation returns
// true for HTTP/2 or HTTP2+QUIC/39 as well.
if (window.PerformanceNavigationTiming) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return ['h2', 'hq'].includes(ntEntry.nextHopProtocol);
}
}
wasNpnNegotiated
function wasNpnNegotiated() {
// NPN is deprecated in favor of ALPN, but this implementation returns true
// for HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.
if (window.PerformanceNavigationTiming) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return ['h2', 'hq'].includes(ntEntry.nextHopProtocol);
}
}
npnNegotiatedProtocol
function npnNegotiatedProtocol() {
// NPN is deprecated in favor of ALPN, but this implementation returns the
// HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.
if (window.PerformanceNavigationTiming) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return ['h2', 'hq'].includes(ntEntry.nextHopProtocol) ?
ntEntry.nextHopProtocol : 'unknown';
}
}
wasAlternateProtocolAvailable
function wasAlternateProtocolAvailable() {
// The Alternate-Protocol header is deprecated in favor of Alt-Svc
// (https://www.mnot.net/blog/2016/03/09/alt-svc), so technically this
// should always return false.
return false;
}
connectionInfo
function connectionInfo() {
if (window.PerformanceNavigationTiming) {
const ntEntry = performance.getEntriesByType('navigation')[0];
return ntEntry.nextHopProtocol;
}
}
삭제 계획
chrome.loadTimes()
API는 Chrome 64에서 지원 중단되며 2018년 말에 삭제될 예정입니다. 개발자는 데이터 손실을 방지하기 위해 최대한 빨리 코드를 이전해야 합니다.