페이지 속도를 위한 JavaScript 자산 최적화
게시 됨: 2020-05-05아래의 예는 크고 복잡한 뉴스 웹사이트에서 가져온 것입니다. 그들은 수년 동안 유기적 인 트래픽을 잃어 왔습니다. DOMContentLoaded 이벤트 타이밍은 2615.2 MS입니다. DOM 크기가 매우 크다고 생각할 수 있지만 그렇지 않습니다.
구글이 추천하는 것과 거의 같으며, 이 문서에는 1230개의 HTML 노드만 존재한다.
domContentLoaded 이벤트 타이밍 및 프로세스를 계산하고 DevTools를 사용하여 경쟁업체와 비교할 수 있습니다.
이 예를 살펴보면 DOM 크기가 반드시 임계점은 아님을 알 수 있습니다. 여기서 주요 문제는 Resource Order 입니다. "Main Tab"의 파란색 부분은 HTML 구문 분석을 위한 것입니다. 그러나 이 웹사이트는 HTML 파싱 프로세스가 완료되기 전에 JavaScript 렌더링으로 브라우저를 중단합니다.
(콜 트리 섹션을 사용하여 IT 팀의 유사한 실수를 찾을 수도 있습니다.)
이 예는 JavaScript 자산 최적화의 중요성과 페이지 속도 최적화에서 JavaScript를 무시할 때 무엇이 잘못될 수 있는지를 명확하게 보여줍니다.
이것은 4개의 기사 시리즈 중 세 번째입니다. 이 기사를 더 잘 이해하기 위해 시리즈의 처음 두 기사를 읽을 수 있습니다.
- Javascript 렌더링 및 페이지 속도는 브라우저의 렌더링 엔진이 웹 페이지를 생성하는 방식과 밀접한 관련이 있습니다.
- 또한 이 문서를 시작하기 전에 고급 페이지 속도 측정항목을 이해해야 합니다.
이 기사의 맥락을 제공하기 위해 처음 두 기사의 몇 가지 예를 사용하겠습니다.
Javascript 렌더링이란 무엇이며 페이지 속도에 어떤 영향을 미치나요?
Javascript 렌더링은 DOM 및 CSSOM을 사용하여 생성된 구조를 대화식으로 변경할 수 있는 마지막 페이지 로딩 섹션입니다. 모든 페이지 요소는 사용자가 트리거할 수 있는 형식으로 변경하거나 정상적으로 표시할 수 있습니다. 렌더링 트리에서 액세스할 수 없는 display:none 속성이 있는 모든 요소는 JavaScript로 표시되도록 렌더링하거나 다른 HTML 요소를 통해 DOM에 삽입할 수 있습니다.
JavaScript는 DOM과 CSSOM을 브라우저에서 읽을 때 DOM과 CSSOM을 변경하기 때문에 중단합니다. 따라서 페이지 로드 시간과 속도에 부정적인 영향을 미치지 않도록 하려면 DOM, CSSOM 및 JavaScript 렌더링 간의 관계를 검토해야 합니다.
위는 렌더링 트리의 예입니다. CSSOM 및 HTML 노드의 모든 연동 코드 스니펫은 렌더링 트리에서 의미론적으로 동등합니다. 주의 깊게 살펴보면 "Action Button" HTML 노드가 렌더링 트리에 없음을 알 수 있습니다. 주된 이유는 "디스플레이:없음"입니다. CSS 속성. 이 invisibility 명령 때문에 렌더링 트리에 포함되지 않습니다. 이 트리의 요소가 어떻게 만들어졌는지 보려면 이 시리즈의 첫 번째 기사를 읽어보세요.
사용자 행동에 의존하기 때문에 첫 번째 로드에 나타나지 않을 페이지 요소가 많은 경우 리소스 로드 순서에서 이러한 항목을 분리하여 마지막 행에 넣어야 합니다. 이 시점에서 shadow DOM 또는 가상 DOM을 사용하는 것이 더 나은 옵션입니다.
JavaScript 리소스에 대한 지연 및 비동기 속성
JS 파일을 섹션에 넣고 'defer' 또는 'async' 속성을 사용하지 않으면 DOMContentLoaded 시간이 지연될 수 있습니다. 이러한 상황을 방지하기 위해 이 두 속성을 사용할 수 있습니다. Defer는 JS 파일의 로딩 과정을 지연시키는 것이고 'Async'는 JS와 다른 소스를 병렬로 로딩하는 것입니다. 둘 다 장점과 단점이 있습니다. 여기서는 주요 내용에 대해서만 이야기하겠습니다.
- 기본 JS 파일에서 defer를 사용하면 설치될 때까지 '초기자' 효과를 볼 수 없을 것입니다.
- defer를 너무 많이 사용하면 페이지 로드가 끝날 때 CPU 병목 현상이 발생할 수 있습니다.
이 글이 작성된 이후로 크롬 80 업데이트가 출시되었습니다. 개시자 열에서 이제 어떤 리소스가 어떤 리소스에 의해 호출되었는지 훨씬 쉽게 확인할 수 있습니다. 예를 들어 JS에서 호출한 이미지나 CSS 파일을 볼 수 있습니다. Shift 키를 누른 상태에서 리소스를 스크롤하면 다른 리소스를 로드하지 않고는 사용할 수 없는 리소스도 표시됩니다.
Shift 키를 누른 상태에서 스크롤: 빨간색은 녹색으로 강조 표시된 리소스의 조건부 리소스를 나타냅니다.
더 자세한 리소스 로드 순서, 개시자 및 우선 순위 검토를 위해 Chrome의 새로운 개시자 섹션을 사용할 수도 있습니다. 이를 통해 아래와 같이 매우 길고 비용이 많이 드는 JS 호출 체인을 감지할 수 있습니다.
동일한 사이트에서 길고 비용이 많이 드는 JS 호출 체인의 예. 선택한 리소스 위에는 이니시에이터가 있습니다. 다음 부분은 선택한 리소스에 의해 시작된 리소스를 보여줍니다.
- Deferred JS 파일은 domInteractive 이벤트 이후에 다운로드 되므로 CSS 파일과 이미지에 따라 선택해야 합니다.
- 일부 사용자 추적기 타사 JS 파일을 연기하면 특정 사용자 행동을 추적하지 못할 수 있습니다.
- Defer는 일반적으로 DOM 프로세스를 차단하지 않지만 Async는 차단합니다. 비동기 속성이 있는 JS 파일은 HTML 구문 분석 및 CSSOM 처리 중에 브라우저에서 다운로드됩니다.
- async 속성을 너무 많이 사용하면 CPU 처리 병목 현상이 발생하고 DOM 및 CSSOM 프로세스가 느려질 수 있습니다. 연기하거나 비동기화할 대상을 신중하게 선택해야 합니다.
다음은 비동기 및 지연 속성에 대한 예시 체계입니다. 첫 번째 것은 가져오는 동안 HTML 구문 분석을 분할하지 않고 domContentLoaded 전에 로드됩니다. 두 번째는 HTML 파싱이 완료되기 전에 가져온 JS 파일이 실행되지 않습니다.
Javascript 렌더링 및 성능에 대한 제안 및 팁
실습 예제를 시작하기 전에 JavaScript 렌더링 성능을 개선하기 위한 몇 가지 제안 사항이 있습니다. 이것은 또한 페이지 속도와 브라우저 작동 방식을 더 잘 이해하는 데 도움이 될 수 있습니다.
불필요한 변수를 사용하지 마십시오.
SEO라면 JavaScript 파일에서 불필요하거나 사용하지 않는 변수를 발견할 수 있습니다. 이러한 종류의 오류를 감지하는 데 사용할 수 있는 도구가 많이 있습니다. 아래에서 사용되지 않고 불필요한 변수에 대한 두 가지 기본 예를 찾을 수 있습니다.
var carName= 브랜드+ ” ” + 연도;
document.getElementById("데모").innerHTML = carName;
여기서 "carName" 변수는 필요하지 않습니다. 다음 수정 사항을 제안할 수 있습니다.
document.getElementById("데모").innerHTML = 브랜드+ " " + 연도
또는:
[a, b, c, d, e].forEach(함수(값, 인덱스) {
console.log(인덱스);
});
여기서 "value" 매개변수는 사용되지 않기 때문에 필요하지 않습니다. 제거할 수 있습니다.
[a, b, c, d, e].forEach(함수(인덱스) {
console.log(인덱스);
});
오른쪽에서 더 긴 연결 시간(흰색 선)을 볼 수 있으며 CSS 및 JS 파일은 "비동기" 자바스크립트 덕분에 비대칭 순서로 로드됩니다.
왼쪽은 각 소스가 행으로 로드되기 때문에 연결 시간이 더 짧고 CSS와 JS 파일이 혼합되지 않습니다. 비동기 속성은 TBT 시간을 연장할 수 있으므로 속도 지수를 줄일 수 있으므로 성능 탭에서 성능 추적기 JS 파일에 대해 조사를 수행하고 개발자 팀에 보고해야 하거나 몇 가지 실험을 직접 실행할 수 있습니다.
어려운 작업에 도구 사용
코드 초보자에게는 불필요하거나 사용하지 않는 변수를 찾는 것이 어려울 수 있습니다. 이러한 작업을 위해 Chrome DevTools 또는 Unused(Kami/node-unused: 코드에서 정의되었지만 사용되지 않은 변수를 보고하는 모듈 또는 더 많은 사용되지 않는 변수)와 같은 Node.js 패키지와 같은 일부 도구를 사용할 수 있습니다. 작은 오류라도 발견하면 IT 팀이 JavaScript 파일을 개선하기 위해 귀를 기울일 것이라고 믿습니다.
Chrome DevTools Coverage Report를 사용하여 사용하지 않는 JavaScript 코드 찾기
Chrome DevTools Coverage Report는 사용되지 않은 JavaScript 코드 스니펫을 보여주지만 그다지 실용적이지 않습니다. 코드에서 모든 빨간색 부분을 삭제할 수 있다고 생각할 수 있지만 그렇지 않습니다... 대신 많은 수의 카테고리 페이지에서 완전히 사용되지 않는 함수나 변수를 찾아야 합니다. 이렇게 하면 개발자 팀이 TreeShaking 프로세스를 사용하도록 확신할 수 있습니다.
TreeShaking은 파일에서 죽은 코드를 삭제하는 것을 의미합니다. 시간을 벌기 위해 사용하지 않는 JS 변수와 함수 찾기 패키지를 사용하여 학습하는 것이 좋습니다.
DOM 크기가 작을수록 JavaScript 렌더링에 도움이 됩니다. 모든 (getElementsByTagName) 명령은 DOM을 스캔합니다. DOM 크기가 작을수록 JavaScript를 렌더링할 때 브라우저와 장치의 CPU/네트워크에서 더 적은 리소스가 필요합니다.
새로운 Chrome 80 업데이트로 커버리지 보고서도 변경되었습니다. 기능별 및 블록별 선택 항목이 추가되었습니다. 블록당은 여기에서 기본값입니다.
기능별을 선택하면 보고서에서 큰 차이를 볼 수 있습니다. 이러한 상황의 주된 이유는 기능별 보기에서 모든 기능이 사용 중인지 여부를 확인하기 때문입니다. 함수의 95%가 사용 중인 경우 함수별 옵션은 함수의 대부분이 사용되지만 코드의 5%가 사용되지 않기 때문에 사용하지 않는 코드로 정의합니다.
JS 파일을 압축, 축소 또는 Uglify합니다.
이것은 두 가지 방법으로 수행할 수 있습니다. 먼저 공백과 불필요한 주석을 삭제하십시오. 둘째, JS 파일에 향상된 JavaScript 연산자를 사용하고 바로 사용할 수 있는 기술로 이름, 변수, 함수를 맹글링합니다.
이런 종류의 압축을 위해서는 Arrow Functions에 대해 알아야 합니다. 예를 들어 다음 84자 예제 대신:
기능 화살표 Islev (a, b) {
console.log(a + b);
}
화살표Fonksiyon (5, 6);
화살표 기능을 사용하여 50자로 압축할 수 있습니다 =>
상수 ab = (a, b) => b + a;
console.log(ab(5,6));
또 다른 단축/압축 방법은 If 문에 유효합니다. 63자의 이 코드 조각 대신:
만약 (a<b) {
console.log(ab);
}
또 다른 {
console.log(a+b);
아래의 43자 문자를 사용할 수 있습니다.
(a<b) ? console.log(ab) : console.log(a+b);
압축을 위해 $ 및 _ 기호를 사용하도록 IT 팀에 제안할 수도 있습니다. 대부분의 JavaScript 파일은 DOM을 재해석하는 데 사용됩니다. 이를 위해 많은 document.getElementById(x); 파일의 코드 조각. 이 작업에 $ 기호를 사용할 수 있습니다. 이것은 쓸모없는 크기의 거대한 더미에서 당신을 구할 것입니다.
대부분의 JavaScript 라이브러리는 기본적으로 $를 함수 정의에 사용하지만 $도 알파벳 문자이기 때문에 전부는 아닙니다.
이 상황에서는 IT 팀이 다음을 사용하도록 제안할 수 있습니다.
함수 $(x) {return document.getElementById(x);} .
적절한 렌더링 유형 사용
SEO 호환성 측면에서 JavaScript 및 웹 페이지 렌더링 유형.
SSR Hydration은 일부 JS 구성 요소가 클라이언트 측 렌더링을 사용하여 렌더링됨을 의미합니다. FP 및 FMP에 유용하지만 TTI 및 속도 지수 점수에는 몇 가지 단점이 있을 수 있습니다.
이미지 출처: Notprovided.eu
JavaScript 렌더링 성능을 위한 코딩 모범 사례
- 또 다른 중요한 압축 기여는 "_" 사용에서 나옵니다. 개선된 JavaScript 작성 형식 및 기능을 위해 "underscore.js"를 사용할 수 있습니다. 이런 식으로 내장 JS 함수 없이 더 짧은 JS 함수로 목록과 컬렉션을 조작하면서 더 작은 JS 파일을 만들 수 있습니다.
- 길고 소모적인 변수 변경과 전역 변수 오염을 많이 사용하는 것도 느린 렌더링의 원인입니다. 함수와 전역 변수/긴 변수 유형의 일반적인 범위 선택을 결정해야 합니다. 'Let'과 함께 지역 변수를 사용하는 것이 렌더링에 더 좋습니다. 지역 변수로 인해 브라우저는 다음 변경 사항에 대해 다른 전역 기능 변수를 감사하지 않습니다.
예를 들어 저가형 휴대폰에서 볼 수 있는 것과 같이 보다 현실적인 성능 검사를 시뮬레이션하려면 Chrome DevTools에서 CPU 조절 및 고속/저속 3G 연결 기본 설정을 사용해야 합니다.
이미지 출처: Addy Osmani
- 더 작은 JS 함수와 변수 체인을 사용하면 렌더링 성능에 도움이 됩니다. 또한 "with" 선택기 대신 "this" 선택기를 사용하는 것이 좋습니다. Javascript의 "This" 선택자는 "with"와 달리 로컬 기능 코드이며 let 및 var와 동일한 논리가 여기에서도 유효합니다.
- For 루프 코드 조각에서 명령문을 사용하면 렌더링 속도도 약간 느려집니다. 함수 문이 루프의 각 요소를 반복하기 때문입니다. 루프 요소에 대한 새 변수를 생성하고 For 루프 외부에 있는 함수를 사용하여 이러한 요소를 호출할 수 있습니다.
- HTML 요소에 여러 번 도달하려는 경우 해당 요소에 대한 변수를 만들고 원하는 기능으로 호출할 수 있습니다. JavaScript로 HTML 요소에 도달하는 것은 빠른 프로세스가 아닙니다. 브라우저에 더 많은 부담을 줄 수 있습니다.
Javascript 렌더링 성능을 향상시키는 또 다른 방법은 서비스 워커를 통한 Trisomorphic Rendering입니다. 향후 세션을 위해 일부 JS 파일을 클라이언트의 브라우저 메모리에 넣을 수 있습니다. 이렇게 하면 웹사이트를 오프라인에서 작동할 수 있습니다.
더 나은 이해를 위한 간단한 데모와 서비스 워커와 함께 연습할 수 있는 기회는 여기에서 찾을 수 있습니다.
묶기: JavaScript 및 페이지 속도 최적화가 SEO에 미치는 영향
JavaScript 자산이 페이지 속도를 방해하지 않도록 하기 위해 Defer 및 Async가 어떻게 큰 차이를 만들 수 있는지 살펴보았습니다. 또한 JavaScript 자산으로 페이지 속도를 향상시키는 데 도움이 될 수 있는 몇 가지 "디버깅" 전략과 코딩 팁을 살펴보았습니다.
이제 브라우저가 웹 페이지를 구축하는 방법, 페이지 속도가 측정되고 영향을 받는 방법, JavaScript 최적화가 페이지 로드 시간에서 수행하는 역할을 살펴보았으므로 다음 기사에서는 리소스 로드 순서가 페이지 속도와 크롤링 예산에 미치는 영향을 보여줍니다.
4개의 기사로 구성된 이 시리즈의 이전 기사를 검토하는 데 관심이 있다면 여기에서 찾을 수 있습니다.
- "브라우저가 웹 페이지를 만드는 방법"
- "고급 페이지 속도 측정항목".