프런트 엔드 성능 2021: 배달 최적화

게시 됨: 2022-03-10
요약 요약 ↬ 2021년을…빨리 만들자! 메트릭에서 도구 및 프론트 엔드 기술에 이르기까지 오늘날 웹에서 빠른 경험을 생성하기 위해 알아야 할 모든 것이 포함된 연간 프론트 엔드 성능 체크리스트. 2016년부터 업데이트되었습니다.

목차

  1. 준비하기: 계획 및 측정항목
  2. 현실적인 목표 설정
  3. 환경 정의
  4. 자산 최적화
  5. 빌드 최적화
  6. 배달 최적화
  7. 네트워킹, HTTP/2, HTTP/3
  8. 테스트 및 모니터링
  9. 빠른 승리
  10. 한 페이지에 모든 것
  11. 체크리스트 다운로드(PDF, Apple Pages, MS Word)
  12. 다음 가이드를 놓치지 않으려면 이메일 뉴스레터를 구독하세요.

배달 최적화

  1. 중요한 JavaScript를 비동기식으로 로드하기 위해 defer 를 사용합니까?
    사용자가 페이지를 요청하면 브라우저는 HTML을 가져와서 DOM을 구성한 다음 CSS를 가져와서 CSSOM을 구성한 다음 DOM과 CSSOM을 일치시켜 렌더링 트리를 생성합니다. JavaScript를 해결해야 하는 경우 브라우저는 해결될 때까지 페이지 렌더링을 시작하지 않으므로 렌더링 이 지연됩니다. 개발자로서 우리는 브라우저에게 기다리지 말고 페이지 렌더링을 시작하라고 명시적으로 알려야 합니다. 스크립트에 대해 이 작업을 수행하는 방법은 HTML의 deferasync 속성을 사용하는 것입니다.

    실제로는 async 대신 defer 를 사용하는 것이 좋습니다. 아, 또 뭐가 달라 ? Steve Souders에 따르면 async 스크립트가 도착하면 스크립트가 준비되는 즉시 즉시 실행됩니다. 예를 들어 스크립트가 캐시에 이미 있는 경우와 같이 매우 빠르게 발생하면 실제로 HTML 파서를 차단할 수 있습니다. defer 를 사용하면 HTML이 구문 분석될 때까지 브라우저가 스크립트를 실행하지 않습니다. 따라서 렌더링을 시작하기 전에 JavaScript를 실행해야 하는 경우가 아니면 defer 를 사용하는 것이 좋습니다. 또한 여러 비동기 파일이 비결정적 순서로 실행됩니다.

    asyncdefer 에 대한 몇 가지 오해가 있다는 점은 주목할 가치가 있습니다. 가장 중요한 것은 async 가 스크립트가 준비될 때마다 코드가 실행된다는 것을 의미하지 않는다는 것입니다. 이는 스크립트가 준비 되고 이전의 모든 동기화 작업이 완료될 때마다 실행됨을 의미합니다. Harry Roberts의 말에 따르면 "동기화 스크립트 뒤에 async 스크립트를 넣으면 async 스크립트는 가장 느린 동기화 스크립트만큼 빠릅니다."

    또한 asyncdefer 를 모두 사용하지 않는 것이 좋습니다. 최신 브라우저는 둘 다 지원하지만 두 속성이 모두 사용될 때마다 async 가 항상 이깁니다.

    더 자세한 내용을 알고 싶다면 Milica Mihajlija가 DOM을 더 빠르게 구축에 대한 매우 상세한 가이드를 작성하여 추측적 구문 분석, 비동기 및 지연에 대한 세부 정보로 이동합니다.

  2. IntersectionObserver 및 우선 순위 힌트를 사용하여 값비싼 구성 요소를 지연 로드합니다.
    일반적으로 무거운 JavaScript, 비디오, iframe, 위젯 및 잠재적인 이미지와 같은 모든 값비싼 구성 요소를 지연 로드하는 것이 좋습니다. 기본 지연 로딩은 이미 loading 속성이 있는 이미지 및 iframe에 사용할 수 있습니다(Chromium만 해당). 내부적으로 이 속성은 뷰포트에서 계산된 거리에 도달할 때까지 리소스 로드를 연기합니다.
    <!-- Lazy loading for images, iframes, scripts. Probably for images outside of the viewport. --> <img loading="lazy" ... /> <iframe loading="lazy" ... /> <!-- Prompt an early download of an asset. For critical images, eg hero images. --> <img loading="eager" ... /> <iframe loading="eager" ... />

    이 임계값은 가져오는 이미지 리소스 유형에서 효과적인 연결 유형에 이르기까지 몇 가지 사항에 따라 다릅니다. 그러나 Android에서 Chrome을 사용하여 수행한 실험에 따르면 4G에서 지연 로드된 스크롤 없이 볼 수 있는 이미지의 97.5%가 표시되고 10ms 이내에 완전히 로드되었으므로 안전해야 합니다.

    <script> , <img> 또는 <link> 요소에 importance 속성( high 또는 low )을 사용할 수도 있습니다(Blink만 해당). 사실, 캐러셀에서 이미지의 우선 순위를 낮추고 스크립트의 우선 순위를 다시 지정하는 좋은 방법입니다. 그러나 때로는 좀 더 세분화된 제어가 필요할 수 있습니다.

    <!-- When the browser assigns "High" priority to an image, but we don't actually want that. --> <img src="less-important-image.svg" importance="low" ... /> <!-- We want to initiate an early fetch for a resource, but also deprioritize it. --> <link rel="preload" importance="low" href="/script.js" as="script" />

    약간 더 정교한 지연 로딩을 수행하는 가장 효과적인 방법은 대상 요소와 상위 요소 또는 최상위 문서의 뷰포트와의 교차점에서 변경 사항을 비동기식으로 관찰 하는 방법을 제공하는 Intersection Observer API를 사용하는 것입니다. 기본적으로 콜백 함수와 옵션 세트를 수신하는 새로운 IntersectionObserver 객체를 생성해야 합니다. 그런 다음 관찰할 대상을 추가합니다.

    콜백 함수는 대상 이 보이 거나 보이지 않을 때 실행되므로 뷰포트를 가로챌 때 요소가 표시되기 전에 몇 가지 작업을 시작할 수 있습니다. 사실, 우리는 rootMargin (루트 주변 여백) 및 threshold (목표 가시성의 백분율을 나타내는 단일 숫자 또는 숫자 배열)을 사용하여 관찰자의 콜백이 호출되어야 하는 시기를 세부적으로 제어할 수 있습니다.

    Alejandro Garcia Anglada는 실제로 구현하는 방법에 대한 편리한 자습서를 게시했으며 Rahul Nanwani는 지연 로딩 전경 및 배경 이미지에 대한 자세한 게시물을 작성했으며 Google Fundamentals는 Intersection Observer를 사용하여 지연 로딩 이미지 및 비디오에 대한 자세한 자습서도 제공합니다.

    움직이는 물체와 끈끈한 물체를 사용한 예술 주도의 스토리텔링을 기억하십니까? Intersection Observer를 사용하여 고성능 스크롤링을 구현할 수도 있습니다.

    지연 로드할 수 있는 다른 항목을 다시 확인하십시오. 지연 로딩 번역 문자열 과 이모티콘도 도움이 될 수 있습니다. 그렇게 함으로써 Mobile Twitter는 새로운 국제화 파이프라인에서 80% 더 빠른 JavaScript 실행을 달성할 수 있었습니다.

    하지만 주의할 점은 지연 로딩이 규칙이 아니라 예외여야 한다는 점입니다. 제품 페이지 이미지, 영웅 이미지 또는 기본 탐색이 대화형이 되는 데 필요한 스크립트와 같이 실제로 사람들이 빨리 보기를 원하는 모든 것을 지연 로드하는 것은 합리적이지 않을 수 있습니다.

3000px의 이전 임계값과 160KB 다운로드(왼쪽)를 보여주는 예와 새로운 임계값의 양이 1250px이고 90KB 다운로드만(오른쪽) img 로딩 지연 데이터 절약의 개선을 보여줍니다.
빠른 연결(예: 4G)에서 Chrome의 표시 영역과의 거리 임계값은 최근 3000px에서 1250px로 감소했으며 느린 연결(예: 3G)에서는 임계값이 4000px에서 2500px로 변경되었습니다. (큰 미리보기)
Twitter UI가 표시된 휴대전화 주변의 텍스트가 있는 그림으로 지연 로드 번역 문자열의 개선된 도구를 설명합니다.
번역 문자열을 지연 로드함으로써 Mobile Twitter는 새로운 국제화 파이프라인에서 80% 더 빠른 JavaScript 실행을 달성했습니다. (이미지 크레디트: Addy Osmani) (큰 미리보기)
  1. 이미지를 점진적으로 로드합니다.
    페이지에 프로그레시브 이미지 로딩을 추가하여 지연 로딩을 한 단계 더 끌어올릴 수도 있습니다. Facebook, Pinterest, Medium 및 Wolt와 유사하게 먼저 낮은 품질 또는 흐릿한 이미지를 로드한 다음 페이지가 계속 로드될 때 BlurHash 기술 또는 LQIP(Low Quality Image Placeholders)를 사용하여 전체 품질 버전으로 교체할 수 있습니다. 기술.

    이러한 기술이 사용자 경험을 개선하는지 여부에 따라 의견이 다르지만, First Contentful Paint에 대한 시간은 확실히 단축됩니다. SVG 플레이스홀더로 이미지의 낮은 품질 버전을 생성하는 SQIP 또는 CSS 선형 그라디언트가 있는 그라디언트 이미지 플레이스홀더를 사용하여 자동화할 수도 있습니다.

    이러한 자리 표시자는 텍스트 압축 방법으로 자연스럽게 압축되므로 HTML 내에 포함될 수 있습니다. Dean Hume은 자신의 기사에서 Intersection Observer를 사용하여 이 기술을 구현하는 방법을 설명했습니다.

    대체? 브라우저가 교차 관찰자를 지원하지 않는 경우에도 폴리필을 지연 로드하거나 이미지를 즉시 로드할 수 있습니다. 그리고 그것을 위한 도서관도 있습니다.

    더 멋지게 가고 싶습니까? 이미지를 추적하고 기본 모양과 가장자리를 사용하여 가벼운 SVG 자리 표시자를 만들고 먼저 로드한 다음 자리 표시자 벡터 이미지에서 (로드된) 비트맵 이미지로 전환할 수 있습니다.

  2. Jose M. Perez의 SVG 지연 로딩 기법을 보여주는 세 가지 다른 버전, 왼쪽은 Cubism art와 유사한 버전, 가운데는 픽셀화된 흐릿한 버전, 오른쪽은 Jose 자신의 적절한 사진
    Jose M. Perez의 SVG 지연 로딩 기술. (큰 미리보기)
  3. content-visibility 렌더링을 연기합니까?
    콘텐츠 블록, 이미지 및 비디오가 많은 복잡한 레이아웃의 경우 데이터 디코딩 및 픽셀 렌더링은 특히 저가형 장치에서 상당히 비용이 많이 드는 작업일 수 있습니다. content-visibility: auto 를 사용하면 컨테이너가 뷰포트 외부에 있는 동안 자식 레이아웃을 건너뛰도록 브라우저에 프롬프트를 표시할 수 있습니다.

    예를 들어, 초기 로드에서 바닥글 및 후기 섹션의 렌더링을 건너뛸 수 있습니다.

    footer { content-visibility: auto; contain-intrinsic-size: 1000px; /* 1000px is an estimated height for sections that are not rendered yet. */ }

    내용 가시성: auto; 오버플로처럼 작동합니다. 숨김; , 하지만 기본 margin-left 대신 padding-leftpadding-right 를 적용하여 수정할 수 있습니다 margin-left: auto; , margin-right: auto; 그리고 선언된 너비. 패딩은 기본적으로 요소가 내용 상자를 오버플로하고 상자 모델을 전체적으로 벗어나지 않고 패딩 상자에 들어갈 수 있도록 합니다.

    또한 새 콘텐츠가 결국 렌더링될 때 일부 CLS를 도입할 수 있으므로 적절한 크기의 자리 표시자와 함께 contain-intrinsic-size 를 사용하는 것이 좋습니다( 감사합니다, Una! ).

    Thijs Terluin은 두 속성 및 브라우저에서 contain-intrinsic-size 를 계산하는 방법에 대해 자세히 설명하고 Malte Ubl은 계산 방법을 보여주고 Jake와 Surma의 간단한 비디오 설명자는 모든 작동 방식을 설명합니다.

    CSS Containment를 사용하여 좀 더 세분화해야 하는 경우 다른 요소에 대해 크기, 정렬 또는 계산된 스타일만 필요한 경우 DOM 노드의 자손에 대한 레이아웃, 스타일 및 페인트 작업을 수동으로 건너뛸 수 있습니다. 캔버스 밖에서.

초기 로드 시 렌더링 성능은 기준선(왼쪽)의 경우 2,288ms이고 content-visibility:auto(오른쪽)가 있는 청크의 경우 13,464ms입니다.
데모에서 content-visibility: auto 을 청크 콘텐츠 영역에 적용하면 초기 로드 시 렌더링 성능이 7배 향상됩니다. (큰 미리보기)
  1. decoding="async" 로 디코딩을 연기합니까?
    때때로 콘텐츠가 화면 밖에 나타나지만 고객이 필요할 때 사용할 수 있도록 하고 싶습니다. 이상적으로는 중요한 경로에서 어떤 것도 차단하지 않고 비동기적으로 디코딩 및 렌더링하는 것입니다. decoding="async" 를 사용하여 브라우저에 기본 스레드에서 이미지를 디코딩할 수 있는 권한을 부여하여 이미지 디코딩에 사용되는 CPU 시간의 사용자 영향을 방지할 수 있습니다(Malte Ubl을 통해).

    <img decoding="async" … />

    또는 오프스크린 이미지의 경우 먼저 자리 표시자를 표시하고 이미지가 뷰포트 내에 있을 때 IntersectionObserver를 사용하여 백그라운드에서 다운로드할 이미지에 대한 네트워크 호출을 트리거할 수 있습니다. 또한 img.decode()로 디코딩할 때까지 렌더링을 연기하거나 Image Decode API를 사용할 수 없는 경우 이미지를 다운로드할 수 있습니다.

    예를 들어 이미지를 렌더링할 때 페이드 인 애니메이션을 사용할 수 있습니다. Katie Hempenius와 Addy Osmani는 Speed ​​at Scale: Web Performance Tips and Tricks from Trenches에서 더 많은 통찰력을 공유합니다.

  2. 중요한 CSS를 생성하고 제공합니까?
    브라우저가 가능한 한 빨리 페이지 렌더링을 시작할 수 있도록 페이지의 첫 번째 표시 부분("중요한 CSS" 또는 "스크롤 없이 볼 수 있는 CSS"라고 함) 렌더링을 시작하는 데 필요한 모든 CSS를 수집하는 것이 일반적입니다. ") 페이지의 <head> 에 인라인으로 포함하여 왕복을 줄입니다. 느린 시작 단계에서 교환되는 패키지의 제한된 크기로 인해 중요한 CSS에 대한 예산은 약 14KB입니다.

    그 이상으로 넘어가면 브라우저는 더 많은 스타일을 가져오기 위해 추가 왕복이 필요합니다. CriticalCSS 및 Critical을 사용하면 사용 중인 모든 템플릿에 대해 중요한 CSS를 출력할 수 있습니다. 하지만 경험상 모든 템플릿에 대해 중요한 CSS를 수동으로 수집하는 것보다 더 나은 자동 시스템은 없었고 실제로 최근에 다시 옮겨온 접근 방식입니다.

    그런 다음 중요한 CSS를 인라인하고 나머지는 critters Webpack 플러그인으로 지연 로드할 수 있습니다. 가능하면 Filament Group에서 사용하는 조건부 인라인 접근 방식을 사용하거나 인라인 코드를 즉시 정적 자산으로 변환하십시오.

    현재 loadCSS와 같은 라이브러리를 사용하여 전체 CSS를 비동기식으로 로드 하는 경우 실제로는 필요하지 않습니다. media="print" 를 사용하면 브라우저가 CSS를 비동기적으로 가져오도록 속일 수 있지만 로드되면 화면 환경에 적용됩니다. ( 고마워, 스콧! )

    <!-- Via Scott Jehl. https://www.filamentgroup.com/lab/load-css-simpler/ --> <!-- Load CSS asynchronously, with low priority --> <link rel="stylesheet" href="full.css" media="print" onload="this.media='all'" />

    각 템플릿에 대한 모든 중요한 CSS를 수집할 때 '스크롤 없이 볼 수 있는 부분' 영역만 탐색하는 것이 일반적입니다. 그러나 복잡한 레이아웃의 경우 레이아웃의 기초를 포함하여 막대한 재계산 및 다시 그리기 비용을 방지 하여 결과적으로 핵심 성능 평가 점수를 손상시키는 것을 방지하는 것이 좋습니다.

    사용자가 페이지 중간에 직접 연결되는 URL을 받았지만 CSS가 아직 다운로드되지 않은 경우에는 어떻게 됩니까? 이 경우 중요하지 않은 콘텐츠를 숨기는 것이 일반적이 되었습니다. 예를 들어 opacity: 0; 인라인 CSS 및 opacity: 1 전체 CSS 파일에 표시하고 CSS를 사용할 수 있을 때 표시합니다. 연결 속도가 느린 사용자는 페이지의 내용을 읽을 수 없기 때문에 큰 단점 이 있습니다. 그렇기 때문에 스타일이 제대로 지정되지 않은 경우에도 콘텐츠를 항상 볼 수 있도록 하는 것이 좋습니다.

    중요한 CSS(및 기타 중요한 자산)를 루트 도메인의 별도 파일에 넣으면 캐싱으로 인해 인라인보다 더 많은 이점이 있습니다. Chrome은 페이지를 요청할 때 루트 도메인에 대한 두 번째 HTTP 연결을 추측적으로 열어 이 CSS를 가져오기 위해 TCP 연결이 필요하지 않습니다. 이는 중요한 CSS 파일 세트(예: critical-homepage.css , critical-product-page.css 등)를 생성하고 인라인할 필요 없이 루트에서 제공할 수 있음을 의미합니다. ( 고마워요, 필립! )

    주의 사항: HTTP/2를 사용하면 중요한 CSS를 별도의 CSS 파일에 저장하고 HTML을 부풀리지 않고 서버 푸시를 통해 전달할 수 있습니다. 문제는 서버 푸시가 브라우저 전반에 걸쳐 많은 문제와 경쟁 조건으로 인해 골칫거리였다는 것입니다. 지속적으로 지원되지 않았고 일부 캐싱 문제가 있었습니다(Hooman Beheshti의 프레젠테이션 슬라이드 114 참조).

    실제로 그 효과는 부정적이고 네트워크 버퍼를 부풀려 문서의 진짜 프레임이 전달되는 것을 방해할 수 있습니다. 따라서 당분간 Chrome이 서버 푸시에 대한 지원을 제거할 계획이라는 것은 그리 놀라운 일이 아닙니다.

  3. CSS 규칙을 다시 그룹화하여 실험합니다.
    우리는 중요한 CSS에 익숙해졌지만 그 이상으로 넘어갈 수 있는 몇 가지 최적화가 있습니다. Harry Roberts는 매우 놀라운 결과로 놀라운 연구를 수행했습니다. 예를 들어 기본 CSS 파일을 개별 미디어 쿼리로 분할 하는 것이 좋습니다. 그렇게 하면 브라우저는 우선 순위가 높은 중요한 CSS를 검색하고 우선 순위가 낮은 다른 모든 항목을 검색하여 중요 경로에서 완전히 벗어납니다.

    또한 async 스니펫 앞에 <link rel="stylesheet" /> 를 배치하지 마십시오. 스크립트가 스타일시트에 의존하지 않는 경우 차단 스타일 위에 차단 스크립트를 배치하는 것을 고려하십시오. 그렇다면 해당 JavaScript를 둘로 나누고 CSS의 양쪽에 로드하십시오.

    Scott Jehl은 인라인 CSS 파일을 서비스 워커와 함께 캐싱하여 또 다른 흥미로운 문제를 해결했습니다. 이 문제는 중요한 CSS를 사용하는 경우 익숙한 일반적인 문제입니다. 기본적으로 JavaScript를 사용하여 쉽게 찾을 수 있도록 style 요소에 ID 속성을 추가하면 작은 JavaScript 조각이 해당 CSS를 찾고 Cache API를 사용하여 로컬 브라우저 캐시에 저장합니다( text/css ) 후속 페이지에서 사용합니다. 후속 페이지에서 인라인을 방지하고 캐시된 자산을 외부에서 참조하기 위해 사이트를 처음 방문할 때 쿠키를 설정합니다. 짜잔!

    동적 스타일 지정도 비용이 많이 들 수 있지만 일반적으로 동시에 렌더링되는 수백 개의 구성 구성 요소에 의존하는 경우에만 해당됩니다. 따라서 CSS-in-JS를 사용하는 경우 CSS가 테마나 소품에 대한 종속성이 없을 때 CSS-in-JS 라이브러리가 실행을 최적화하는지 확인하고 스타일이 지정된 구성 요소를 과도하게 구성하지 마십시오 . Agelos Arvanitakis는 CSS-in-JS의 성능 비용에 대한 더 많은 통찰력을 공유합니다.

  4. 응답을 스트리밍합니까?
    종종 잊혀지고 무시되는 스트림은 비동기 데이터 청크를 읽거나 쓰기 위한 인터페이스를 제공하며, 이 중 일부만 주어진 시간에 메모리에서 사용할 수 있습니다. 기본적으로 데이터의 첫 번째 청크를 사용할 수 있게 되는 즉시 원래 요청을 한 페이지가 응답 작업을 시작하도록 허용하고 스트리밍에 최적화된 파서를 사용하여 콘텐츠를 점진적으로 표시합니다.

    여러 소스에서 하나의 스트림을 만들 수 있습니다. 예를 들어 빈 UI 셸을 제공하고 JavaScript가 이를 채우도록 하는 대신 서비스 워커가 셸은 캐시에서 가져오고 본문은 네트워크에서 오는 스트림을 구성 하도록 할 수 있습니다. Jeff Posnick이 언급했듯이 웹 앱이 부분 템플릿을 함께 연결하여 서버에서 HTML을 렌더링하는 CMS로 구동되는 경우 해당 모델은 서버 대신 서비스 작업자에서 복제된 템플릿 논리와 함께 스트리밍 응답을 사용하는 것으로 직접 변환됩니다. Jake Archibald의 Year of Web Streams 기사는 이를 정확히 구축할 수 있는 방법을 강조합니다. 성능 향상이 상당히 눈에 띕니다.

    전체 HTML 응답을 스트리밍하는 한 가지 중요한 이점은 초기 탐색 요청 중에 렌더링된 HTML이 브라우저의 스트리밍 HTML 파서를 최대한 활용할 수 있다는 것입니다. 페이지가 로드된 후 문서에 삽입되는 HTML 덩어리(JavaScript를 통해 채워진 콘텐츠에서 흔히 볼 수 있는 것처럼)는 이 최적화를 활용할 수 없습니다.

    브라우저 지원? 모든 최신 브라우저에서 지원되는 API 및 서비스 워커를 지원하는 Chrome, Firefox, Safari 및 Edge의 부분 지원으로 여전히 거기에 도달하고 있습니다. 그리고 다시 모험심을 느낀다면 스트리밍 요청의 실험적 구현을 ​​확인할 수 있습니다. 이를 통해 본문을 생성하는 동안 요청 전송을 시작할 수 있습니다. Chrome 85에서 사용할 수 있습니다.

2019년 11월과 2020년 4월에 Cloudinary 연구에서 발견한 Android Chrome의 저장 데이터 사용량과 평균 img 조회수 또는 세션을 요약한 이미지
Cloudinary 조사에 따르면 전 세계 Android Chrome 사용자의 18%가 라이트 모드(Save-Data라고도 함)를 활성화했습니다. (큰 미리보기)
  1. 구성 요소를 연결 인식하도록 만드는 것이 좋습니다.
    데이터는 비싸고 페이로드가 증가함에 따라 사이트나 앱에 액세스하는 동안 데이터 절약을 선택하는 사용자를 존중해야 합니다. Save-Data 클라이언트 힌트 요청 헤더를 사용하면 비용 및 성능이 제한된 사용자에게 애플리케이션과 페이로드를 사용자 지정할 수 있습니다.

    사실, 높은 DPI 이미지에 대한 요청을 낮은 DPI 이미지로 다시 작성하고, 웹 글꼴 제거, 멋진 시차 효과, 미리보기 축소판 및 무한 스크롤, 비디오 자동 재생 끄기, 서버 푸시, 표시된 항목 수 줄이기 및 이미지 품질 저하 또는 마크업을 제공하는 방법을 변경할 수도 있습니다. Tim Vereecke는 데이터 절약을 위한 많은 옵션을 특징으로 하는 데이터 절약 전략에 대한 매우 상세한 기사를 게시했습니다.

    누가 save-data 를 사용하고 있는지 궁금할 것입니다. 전 세계 Android Chrome 사용자의 18%가 라이트 모드를 활성화했으며( Save-Data 켜짐), 그 수치는 더 높을 것입니다. Simon Hearne의 연구에 따르면 옵트인 비율은 저렴한 기기에서 가장 높지만 많은 예외가 있습니다. 예를 들어, 캐나다 사용자의 옵트인 비율은 34% 이상(미국의 ~7%)이고 최신 Samsung 플래그십 사용자의 옵트인 비율은 전 세계적으로 거의 18%입니다.

    Save-Data 모드가 켜져 있으면 Chrome Mobile은 최적화된 환경, 즉 지연된 스크립트, 강제 font-display: swap 및 강제 지연 로드가 있는 프록시 웹 환경을 제공합니다. 브라우저에 의존하여 이러한 최적화를 수행하는 것보다 직접 경험을 구축하는 것이 더 합리적입니다.

    헤더는 현재 Chromium, Android 버전의 Chrome 또는 데스크톱 기기의 Data Saver 확장 프로그램을 통해서만 지원됩니다. 마지막으로 네트워크 정보 API를 사용하여 네트워크 유형에 따라 값비싼 JavaScript 모듈, 고해상도 이미지 및 비디오를 전달할 수도 있습니다. 네트워크 정보 API, 특히 navigator.connection.effectiveTypeRTT , downlink , effectiveType 값(및 기타 몇 가지)을 사용하여 사용자가 처리할 수 있는 연결 및 데이터의 표현을 제공합니다.

    이 맥락에서 Max Bock은 연결 인식 구성 요소에 대해 말하고 Addy Osmani는 적응형 모듈 서비스에 대해 이야기합니다. 예를 들어 React를 사용하여 연결 유형에 따라 다르게 렌더링하는 구성 요소를 작성할 수 있습니다. Max가 제안한 것처럼 뉴스 기사의 <Media /> 구성 요소는 다음을 출력할 수 있습니다.

    • Offline : alt 텍스트가 있는 자리 표시자,
    • 2G / save-data 모드: 저해상도 이미지,
    • 비 Retina 화면의 3G : 중간 해상도 이미지,
    • Retina 화면의 3G : 고해상도 Retina 이미지,
    • 4G : HD 비디오.

    Dean Hume은 서비스 워커를 사용하여 유사한 로직의 실용적인 구현을 제공합니다. 비디오의 경우 기본적으로 비디오 포스터를 표시한 다음 "재생" 아이콘과 비디오 플레이어 쉘, 비디오 메타데이터 등을 더 나은 연결에 표시할 수 있습니다. 지원하지 않는 브라우저에 대한 폴백으로 canplaythrough 이벤트를 수신하고 canplaythrough 이벤트가 2초 이내에 실행되지 않으면 canplaythrough Promise.race() 를 사용하여 소스 로딩 시간을 초과할 수 있습니다.

    좀 더 자세히 알아보려면 다음과 같이 시작할 수 있는 몇 가지 리소스를 참조하세요.

    • Addy Osmani는 React에서 적응형 서빙을 구현하는 방법을 보여줍니다.
    • React Adaptive Loading Hooks & Utilities는 React,
    • Netanel Basel은 Angular의 연결 인식 구성 요소를 탐색합니다.
    • Theodore Vorilas는 Vue에서 네트워크 정보 API를 사용하여 적응형 구성 요소를 제공하는 방법을 공유합니다.
    • Umar Hansa는 고가의 JavaScript를 선택적으로 다운로드/실행하는 방법을 보여줍니다.
  2. 구성 요소 장치의 메모리 인식을 고려하십시오.
    네트워크 연결은 사용자의 컨텍스트에서 단 하나의 관점을 제공합니다. 더 나아가 Device Memory API를 사용하여 사용 가능한 장치 메모리를 기반으로 리소스를 동적으로 조정할 수도 있습니다. navigator.deviceMemory 는 장치에 있는 RAM의 양을 기가바이트 단위로 반환하고 가장 가까운 2의 거듭제곱으로 내림합니다. API에는 동일한 값을 보고하는 클라이언트 힌트 헤더인 Device-Memory 도 있습니다.

    보너스 : Umar Hansa는 장치 메모리, 네트워크 연결 및 하드웨어 동시성을 기반으로 경험을 변경하기 위해 동적 가져오기로 값비싼 스크립트를 연기하는 방법을 보여줍니다.

Chrome 46 이상부터 Blink에서 다양한 리소스의 우선 순위를 보여주는 분석
Chrome 46 이상부터 Blink에서 다양한 리소스의 우선 순위를 보여주는 분석입니다. (이미지 크레디트: Addy Osmani) (큰 미리보기)
  1. 전송 속도를 높이려면 연결을 워밍업하십시오.
    리소스 힌트를 사용하여 dns-prefetch (백그라운드에서 DNS 조회를 수행), preconnect (브라우저에 백그라운드에서 연결 핸드셰이크(DNS, TCP, TLS)를 시작하도록 요청), prefetch (브라우저에 요청 리소스 요청) 및 preload (무엇보다도 리소스를 실행하지 않고 리소스를 미리 가져옴). 최신 브라우저에서 잘 지원되며 곧 Firefox에서도 지원됩니다.

    prerender 기억하십니까? 다음 탐색을 위해 백그라운드에서 전체 페이지를 빌드하도록 브라우저에 프롬프트하는 데 사용되는 리소스 힌트입니다. 구현 문제는 막대한 메모리 공간과 대역폭 사용량에서 등록된 여러 분석 조회수 및 광고 노출에 이르기까지 상당히 문제가 많았습니다.

    당연히 더 이상 사용되지 않지만 Chrome 팀은 이를 NoState Prefetch 메커니즘으로 다시 가져왔습니다. 실제로 Chrome은 prerender 힌트를 대신 NoState Prefetch로 처리하므로 오늘날에도 여전히 사용할 수 있습니다. Katie Hempenius는 해당 기사에서 "사전 렌더링과 마찬가지로 NoState Prefetch는 리소스를 미리 가져오지만 사전 렌더링과 달리 JavaScript를 실행하거나 페이지의 어떤 부분도 미리 렌더링하지 않습니다 ."라고 설명합니다.

    NoState Prefetch는 ~45MiB의 메모리만 사용하며 가져온 하위 리소스는 IDLE Net Priority로 가져옵니다. Chrome 69부터 NoState Prefetch는 일반 탐색과 구별할 수 있도록 모든 요청에 ​​목적: Prefetch 헤더를 추가합니다.

    또한 원활한 탐색을 위해 콘텐츠의 삽입된 preview 를 제공할 개인 정보 보호를 고려한 사전 렌더링을 위한 새로운 노력인 사전 렌더링 대안 및 포털에 주의하십시오.

    리소스 힌트를 사용하는 것이 성능을 높이는 가장 쉬운 방법 일 것이며 실제로 잘 작동합니다. 언제 무엇을 사용합니까? Addy Osmani가 설명했듯이 사용자가 아직 방문하지 않은 페이지에 필요한 Webpack 번들과 같이 현재 페이지와 여러 탐색 경계를 통한 향후 탐색에 사용할 가능성이 매우 높은 리소스를 미리 로드하는 것이 합리적입니다.

    "Chrome에서 우선 순위 로드"에 대한 Addy의 기사는 Chrome이 리소스 힌트를 정확히 해석하는 방법을 보여주므로 렌더링에 중요한 자산을 결정한 후에는 해당 자산에 높은 우선 순위를 지정할 수 있습니다. 요청의 우선 순위를 확인하려면 Chrome DevTools 네트워크 요청 테이블(Safari도 포함)에서 "우선 순위" 열을 활성화할 수 있습니다.

    요즘 대부분의 시간 동안 우리는 최소한 preconnectdns-prefetch 를 사용하고 prefetch , preloadprerender 를 사용할 때 주의할 것입니다. preconnectdns-prefetch 를 사용하더라도 브라우저는 병렬로 조회/연결할 호스트 수에 제한이 있으므로 우선 순위에 따라 주문하는 것이 안전합니다( Philip Tellis에게 감사드립니다! ).

    글꼴 은 일반적으로 페이지의 중요한 자산이므로 때로는 브라우저에 preload 된 중요한 글꼴을 다운로드하도록 요청하는 것이 좋습니다. 그러나 글꼴을 사전 로드할 때 우선 순위의 퍼즐이 있으므로 실제로 성능에 도움이 되는지 다시 확인하십시오. preload 는 매우 중요하므로 중요한 CSS와 같은 훨씬 더 중요한 리소스를 뛰어넘을 수 있습니다. ( 고마워, 배리! )

    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />
    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />

    <link rel="preload">media 속성을 허용하므로 위와 같이 @media 쿼리 규칙을 기반으로 리소스를 선택적으로 다운로드하도록 선택할 수 있습니다.

    또한 imagesrcsetimagesizes 속성을 사용하여 늦게 발견된 영웅 이미지 또는 JavaScript를 통해 로드되는 모든 이미지(예: 영화 포스터)를 미리 로드할 수 있습니다.

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>
    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>

    JSONfetch 로 미리 로드할 수도 있으므로 JavaScript가 요청하기 전에 검색됩니다.

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>

    스크립트의 지연 실행을 위해 효과적으로 JavaScript를 동적으로 로드할 수도 있습니다.

    /* Adding a preload hint to the head */ var preload = document.createElement("link"); link.href = "myscript.js"; link.rel = "preload"; link.as = "script"; document.head.appendChild(link); /* Injecting a script when we want it to execute */ var script = document.createElement("script"); script.src = "myscript.js"; document.body.appendChild(script);

    염두에 두어야 할 몇 가지 문제: preload 는 자산의 다운로드 시작 시간을 초기 요청에 더 가깝게 이동하는 데 적합하지만 사전 로드된 자산은 요청하는 페이지와 연결된 메모리 캐시 에 있습니다. preload 는 HTTP 캐시와 잘 작동합니다. 항목이 이미 HTTP 캐시에 있으면 네트워크 요청이 전송되지 않습니다.

    따라서 늦게 발견된 리소스, background-image 를 통해 로드된 영웅 이미지, 중요한 CSS(또는 JavaScript)를 인라인하고 나머지 CSS(또는 JavaScript)를 미리 로드하는 데 유용합니다.

    Tom Hanks가 주연한 Greyhound 영화의 표지를 사용하여 JavaScript를 검색할 때까지 기다릴 필요가 없기 때문에 미리 로드된 이미지가 더 빨리 로드된다는 것을 보여주는 예
    중요한 이미지를 일찍 미리 로드하십시오. JavaScript를 발견하기 위해 기다릴 필요가 없습니다. (이미지 크레디트: Addy Osmani의 "Preload Late-Discovered Hero Images Faster") (큰 미리보기)

    preload 태그는 브라우저가 서버로부터 HTML을 수신하고 미리보기 파서가 preload 태그를 찾은 후에만 사전 로드를 시작할 수 있습니다. HTTP 헤더를 통한 사전 로드는 브라우저가 요청을 시작하기 위해 HTML을 구문 분석할 때까지 기다리지 않기 때문에 조금 더 빠를 수 있습니다.

    Early Hints는 HTML에 대한 응답 헤더가 전송되기 전에 미리 로드할 수 있도록 하여 훨씬 더 도움이 될 것입니다(Chromium, Firefox의 로드맵에서). 또한 우선 순위 힌트는 스크립트의 로드 우선 순위를 나타내는 데 도움이 됩니다.

    주의 : preload 를 사용하는 경우 정의 해야 하는 as 또는 아무 것도 로드되지 crossorigin 속성이 없는 미리 로드된 글꼴은 이중으로 가져옵니다. prefetch 를 사용하는 경우 Firefox의 Age 헤더 문제에 주의하세요.

지정된 기간(ms) 동안 0에서 150 사이의 카운트가 있는 첫 번째 콘텐츠가 포함된 페인트(서버 작업자 상태별)를 보여주는 그래프
서비스 워커를 사용하면 최소한의 데이터만 요청한 다음 해당 데이터를 전체 HTML 문서로 변환하여 FCP를 개선할 수 있습니다. (필 월튼을 통해) (큰 미리보기)
  1. 캐싱 및 네트워크 대체를 위해 서비스 워커를 사용합니다.
    네트워크를 통한 성능 최적화는 사용자 컴퓨터에 로컬로 저장된 캐시보다 빠를 수 없습니다(예외가 있음). 웹사이트가 HTTPS를 통해 실행되는 경우 서비스 작업자 캐시에 정적 자산을 캐시하고 오프라인 폴백(또는 오프라인 페이지까지)을 저장하고 네트워크로 이동하지 않고 사용자 컴퓨터에서 검색할 수 있습니다.

    Phil Walton이 제안한 대로 서비스 작업자와 함께 프로그래밍 방식으로 응답을 생성하여 더 작은 HTML 페이로드를 보낼 수 있습니다. 서비스 작업자는 서버에서 필요한 최소한의 데이터(예: HTML 콘텐츠 부분, Markdown 파일, JSON 데이터 등)를 요청할 수 있으며, 그런 다음 해당 데이터를 전체 HTML 문서로 프로그래밍 방식으로 변환 할 수 있습니다. 따라서 사용자가 사이트를 방문하고 서비스 워커가 설치되면 사용자는 전체 HTML 페이지를 다시 요청하지 않습니다. 성능에 미치는 영향은 상당히 인상적일 수 있습니다.

    브라우저 지원? 서비스 작업자는 널리 지원되며 대체는 어쨌든 네트워크입니다. 성능 향상에 도움 이 됩니까? 네, 그렇습니다. 예를 들어 Background Fetch를 사용하여 서비스 작업자를 통해 백그라운드 업로드/다운로드를 허용하는 등 점점 더 좋아지고 있습니다.

    서비스 워커에 대한 여러 사용 사례가 있습니다. 예를 들어 "오프라인용으로 저장" 기능을 구현하고, 깨진 이미지를 처리하고, 탭 간에 메시징을 도입하거나, 요청 유형에 따라 다른 캐싱 전략을 제공할 수 있습니다. 일반적으로 신뢰할 수 있는 일반적인 전략은 서비스 워커의 캐시에 앱 셸을 오프라인 페이지, 프론트 페이지 및 귀하의 경우에 중요할 수 있는 기타 모든 중요 페이지와 함께 저장하는 것입니다.

    그러나 염두에 두어야 할 몇 가지 문제가 있습니다. 서비스 워커가 있는 경우 Safari의 범위 요청에 주의해야 합니다(서비스 워커에 대해 Workbox를 사용하는 경우 범위 요청 모듈이 있음). DOMException: Quota exceeded. 브라우저 콘솔에서 오류가 발생하면 Gerardo의 문서 When 7KB equals 7MB를 참조하세요.

    Gerardo는 "프로그레시브 웹 앱을 빌드 중이고 서비스 워커가 CDN에서 제공되는 정적 자산을 캐시할 때 캐시 스토리지가 부풀려지는 경우 원본 간 리소스에 대해 적절한 CORS 응답 헤더가 있는지 확인하고 불투명한 응답을 캐시하지 마십시오. 의도치 않게 서비스 워커와 함께 <img> 태그에 crossorigin 속성을 추가하여 교차 출처 이미지 자산을 CORS 모드로 옵트인하게 됩니다."

    서비스 워커를 시작하는 데 유용한 리소스 가 많이 있습니다.

    • 서비스 워커 마인드셋(Service Worker Mindset): 서비스 워커가 배후에서 일하는 방식과 서비스 워커를 구축할 때 이해해야 할 사항을 이해하는 데 도움이 됩니다.
    • Chris Ferdinandi는 오프라인 애플리케이션을 만드는 방법을 설명하고 최근에 본 페이지를 오프라인으로 저장하는 것부터 서비스 워커 캐시에 있는 항목의 만료 날짜 설정에 이르기까지 다양한 시나리오를 다루는 서비스 워커에 대한 일련의 훌륭한 기사를 제공합니다.

    • 서비스 워커 함정 및 모범 사례, 서비스 워커 등록 지연 및 서비스 워커 캐싱 범위에 대한 몇 가지 팁.
    • Ire Aderinokun의 "Offline First"에서 Service Worker와 함께 앱 셸을 사전 캐싱하는 전략에 대한 훌륭한 시리즈입니다.
    • 서비스 워커: 풍부한 오프라인 경험, 주기적 백그라운드 동기화 및 푸시 알림을 위해 서비스 워커를 사용하는 방법에 대한 실용적인 팁이 포함된 소개입니다.
    • 서비스 워커를 굽는 방법에 대한 다양한 레시피가 포함된 훌륭한 Jake Archibald의 오프라인 요리책을 참조하는 것은 항상 가치가 있습니다.
    • Workbox는 프로그레시브 웹 앱을 빌드하기 위해 특별히 빌드된 서비스 워커 라이브러리 세트입니다.
  2. 예를 들어 A/B 테스트를 위해 CDN/Edge에서 서버 작업자를 실행하고 있습니까?
    이 시점에서 우리는 클라이언트에서 서비스 워커를 실행하는 데 상당히 익숙하지만 CDN을 서버에서 구현하면 이를 사용하여 에지에서도 성능을 조정할 수 있습니다.

    예를 들어 A/B 테스트에서 HTML이 다양한 사용자를 위해 콘텐츠를 변경해야 하는 경우 CDN 서버의 서비스 작업자를 사용하여 논리를 처리할 수 있습니다. 또한 HTML 재작성을 스트리밍하여 Google 글꼴을 사용하는 사이트의 속도를 높일 수 있습니다.

2016년 1월과 2020년 7월 사이의 시간에 따른 페이지 비율과 함께 데스크톱 및 모바일에서 서비스 작업자 설치의 시계열을 보여주는 그래프
서비스 워커 설치 시계열. Web Almanac에 따르면 모든 데스크톱 페이지 중 0.87%만이 서비스 워커를 등록합니다. (큰 미리보기)
  1. 렌더링 성능을 최적화합니다.
    응용 프로그램이 느려질 때마다 즉시 눈에.니다. 따라서 페이지를 스크롤하거나 요소에 애니메이션을 적용할 때 지연이 없고 지속적으로 초당 60프레임을 기록하고 있는지 확인해야 합니다. 이것이 가능하지 않다면 최소한 초당 프레임 수를 일정하게 유지하는 것이 60에서 15 사이의 혼합 범위보다 바람직합니다. CSS의 will-change 를 사용하여 브라우저에 어떤 요소와 속성이 변경되는지 알립니다.

    발생할 때마다 DevTools에서 불필요한 다시 그리기를 디버그 하세요.

    • 런타임 렌더링 성능을 측정합니다. 그것을 이해하는 방법에 대한 몇 가지 유용한 팁을 확인하십시오.
    • 시작하려면 브라우저 렌더링 최적화에 대한 Paul Lewis의 무료 Udacity 과정과 웹 성능에 대한 브라우저 페인팅 및 고려 사항에 대한 Georgy Marchuk의 기사를 확인하십시오.
    • Firefox DevTools의 "추가 도구 → 렌더링 → 페인트 깜박임"에서 페인트 깜박임을 활성화하십시오.
    • React DevTools에서 "업데이트 강조 표시"를 선택하고 "각 구성 요소가 렌더링된 이유 기록"을 활성화합니다.
    • 왜 렌더링을 했는가를 사용할 수도 있으므로 구성 요소가 다시 렌더링되면 플래시에서 변경 사항을 알려줍니다.

    Masonry 레이아웃을 사용하고 있습니까? 곧 CSS 그리드만으로 Masonry 레이아웃을 구축할 수 있다는 점을 염두에 두십시오.

    이 주제에 대해 더 자세히 알고 싶다면 Nolan Lawson이 자신의 기사에서 레이아웃 성능을 정확하게 측정하는 방법을 공유했으며 Jason Miller도 대안 기술을 제안했습니다. GPU 애니메이션을 올바르게 만드는 방법에 대한 Sergey Chikuyonok의 기사도 있습니다.

    위치, 크기 조정, 회전 및 불투명도를 포함한 고성능 애니메이션
    브라우저는 변형 및 불투명도를 저렴하게 애니메이션할 수 있습니다. CSS Triggers는 CSS가 re-layout 또는 reflow를 트리거하는지 확인하는 데 유용합니다. (이미지 크레디트: Addy Osmani)(큰 미리보기)

    참고 : GPU 합성 레이어에 대한 변경 사항은 가장 저렴하므로 opacitytransform 을 통해 합성만 트리거하여 벗어날 수 있다면 올바른 방향으로 가고 있는 것입니다. Anna Migas는 Debugging UI Rendering Performance에 대한 강연에서도 많은 실용적인 조언을 제공했습니다. 그리고 DevTools에서 페인트 성능을 디버그하는 방법을 이해하려면 Umar의 페인트 성능 감사 비디오를 확인하십시오.

  2. 인지된 성능에 최적화했습니까?
    구성 요소가 페이지에 표시되는 순서와 브라우저에 자산을 제공하는 전략이 중요하지만 인지된 성능의 역할도 과소평가해서는 안 됩니다. 이 개념은 기본적으로 다른 일이 일어나는 동안 고객을 바쁘게 하거나 참여하게 하는 기다림의 심리적 측면을 다룹니다. 그것이 바로 지각 관리, 선제적 시작, 조기 완료 및 관용 관리가 작동하는 곳입니다.

    이 모든 것은 무엇을 의미합니까? 자산을 로드하는 동안 우리는 항상 고객 보다 한 발 앞서 려고 노력할 수 있으므로 백그라운드에서 많은 일이 일어나는 동안 경험이 신속하게 느껴집니다. 고객의 참여를 유지하기 위해 표시기를 로드하는 대신 스켈레톤 화면(구현 데모)을 테스트하고, 전환/애니메이션을 추가하고, 더 이상 최적화할 것이 없을 때 기본적으로 UX를 속일 수 있습니다.

    Art of UI Skeletons에 대한 사례 연구에서 Kumar McMillan은 동적 목록, 텍스트 및 최종 화면을 시뮬레이션하는 방법과 React로 뼈대 사고 를 고려하는 방법에 대한 몇 가지 아이디어와 기술을 공유합니다.

    하지만 조심하십시오. 일부 테스트에서는 스켈레톤 스크린이 모든 메트릭에서 최악의 성능을 보일 수 있음을 보여주었으므로 배포하기 전에 스켈레톤 스크린을 테스트해야 합니다.

  3. 레이아웃 변경 및 다시 그리기를 방지합니까?
    인지된 성능의 영역에서 아마도 더 파괴적인 경험 중 하나는 크기 조정된 이미지 및 비디오, 웹 글꼴, 삽입된 광고 또는 구성 요소를 실제 콘텐츠로 채우는 늦게 발견된 스크립트로 인해 발생하는 레이아웃 이동 또는 리플로우 일 것입니다. 결과적으로 고객은 읽기 영역 위의 레이아웃 점프에 의해 중단되기 위해 기사 읽기를 시작할 수 있습니다. 경험은 종종 갑작스럽고 상당히 혼란스럽습니다. 이는 아마도 재고해야 할 우선 순위를 로드하는 경우일 것입니다.

    커뮤니티는 리플로우를 방지하기 위해 몇 가지 기술과 해결 방법을 개발했습니다. 일반적으로 사용자 상호 작용에 대한 응답으로 발생하지 않는 한 기존 콘텐츠 위에 새 콘텐츠를 삽입 하지 않는 것이 좋습니다. 항상 이미지에 너비 및 높이 속성을 설정하므로 최신 브라우저는 기본적으로 상자를 할당하고 공간을 예약합니다(Firefox, Chrome).

    이미지나 비디오 모두에 대해 SVG 자리 표시자를 사용하여 미디어가 표시될 디스플레이 상자를 예약할 수 있습니다. 즉, 가로 세로 비율도 유지해야 할 때 영역이 적절하게 예약됩니다. 또한 자리 표시자 또는 광고 및 동적 콘텐츠에 대한 대체 이미지를 사용할 수 있으며 레이아웃 슬롯을 미리 할당할 수도 있습니다.

    외부 스크립트로 이미지를 지연 로드하는 대신 기본 지연 로딩이 지원되지 않는 경우에만 외부 스크립트를 로드할 때 네이티브 지연 로딩 또는 하이브리드 지연 로딩을 사용하는 것이 좋습니다.

    위에서 언급했듯이 항상 웹 글꼴 다시 그리기를 그룹화하고 모든 대체 글꼴에서 한 번에 모든 웹 글꼴로 전환합니다. font-style-matcher를 사용하여 글꼴 사이의 줄 높이와 간격을 조정하여 전환이 너무 갑작스럽지 않은지 확인하십시오. .

    웹 글꼴을 에뮬레이트하기 위해 대체 글꼴에 대한 글꼴 메트릭을 재정의 하려면 @font-face 설명자를 사용하여 글꼴 메트릭을 재정의할 수 있습니다(데모, Chrome 87에서 활성화됨). (그러나 복잡한 글꼴 스택으로 인해 조정이 복잡합니다.)

    후기 CSS의 경우 레이아웃에 중요한 CSS가 각 템플릿의 헤더에 인라인 되도록 할 수 있습니다. 그보다 훨씬 더: 긴 페이지의 경우 세로 스크롤 막대가 추가되면 기본 콘텐츠가 왼쪽으로 16px 이동합니다. 스크롤바를 일찍 표시하기 위해 overflow-y: scroll on html 을 추가하여 처음 페인트할 때 스크롤바를 적용할 수 있습니다. 후자는 스크롤바가 너비가 변경될 때 스크롤바가 접히지 않는 콘텐츠 리플로우로 인해 사소한 레이아웃 이동을 유발할 수 있기 때문에 도움이 됩니다. Windows와 같은 비 오버레이 스크롤바가 있는 플랫폼에서 대부분 발생해야 합니다. 하지만: break position: sticky 는 해당 요소가 컨테이너 밖으로 스크롤되지 않기 때문입니다.

    스크롤할 때 페이지 상단에 고정되거나 고정되는 헤더를 처리하는 경우 헤더가 파인될 때 헤더를 위한 공간을 확보하십시오(예: 자리 표시자 요소 또는 콘텐츠의 margin-top 사용). 예외는 CLS에 영향을 미치지 않아야 하는 쿠키 동의 배너여야 하지만 때로는 영향을 미치므로 구현에 따라 다릅니다. 이 Twitter 스레드에는 몇 가지 흥미로운 전략과 시사점이 있습니다.

    다양한 양의 텍스트를 포함할 수 있는 탭 구성 요소의 경우 CSS 그리드 스택을 사용하여 레이아웃 이동을 방지할 수 있습니다. 각 탭의 내용을 동일한 그리드 영역에 배치하고 한 번에 하나씩 숨김으로써 컨테이너가 항상 더 큰 요소의 높이를 사용하도록 할 수 있으므로 레이아웃 이동이 발생하지 않습니다.

    아, 물론 목록 아래에 내용(예: 바닥글)이 있는 경우 무한 스크롤 및 "더 로드"로 인해 레이아웃이 변경될 수도 있습니다. CLS를 개선하려면 사용자가 페이지의 해당 부분으로 스크롤 하기 전에 로드될 콘텐츠를 위한 충분한 공간을 예약하고 콘텐츠 로드로 인해 아래로 밀려날 수 있는 페이지 하단의 바닥글 또는 DOM 요소를 제거합니다. 또한, 스크롤 없이 볼 수 있는 콘텐츠에 대한 데이터와 이미지를 미리 가져오므로 사용자가 스크롤할 때 해당 콘텐츠가 이미 존재합니다. react-window와 같은 목록 가상화 라이브러리를 사용하여 긴 목록도 최적화할 수 있습니다( 감사합니다, Addy Osmani! ).

    리플로우의 영향이 포함되도록 하려면 Layout Instability API를 사용하여 레이아웃 안정성을 측정하십시오. 이를 통해 CLS (누적 레이아웃 이동) 점수를 계산하고 테스트에 요구 사항으로 포함할 수 있으므로 회귀가 나타날 때마다 추적하고 수정할 수 있습니다.

    레이아웃 이동 점수를 계산하기 위해 브라우저는 뷰포트 크기와 두 렌더링된 프레임 사이의 뷰포트에서 불안정한 요소의 움직임을 확인합니다. 이상적으로 점수는 0 에 가까울 것입니다. Milica Mihajlija와 Philip Walton이 CLS가 무엇이며 어떻게 측정하는지에 대한 훌륭한 가이드가 있습니다. 특히 비즈니스 크리티컬 작업의 경우 인지된 성능을 측정 및 유지하고 중단을 피하기 위한 좋은 출발점입니다.

    빠른 팁 : DevTools에서 레이아웃 이동을 일으킨 원인을 찾으려면 성능 패널의 "경험" 에서 레이아웃 이동을 탐색할 수 있습니다.

    보너스 : 리플로우 및 다시 그리기를 줄이고 싶다면 Charis Theodoulou의 DOM Reflow/Layout Thrashing 최소화 가이드와 Paul Irish의 What force layout/reflow 목록과 CSSTriggers.com, 레이아웃, 페인트를 트리거하는 CSS 속성에 대한 참조 테이블을 확인하세요. 그리고 합성.

목차

  1. 준비하기: 계획 및 측정항목
  2. 현실적인 목표 설정
  3. 환경 정의
  4. 자산 최적화
  5. 빌드 최적화
  6. 배달 최적화
  7. 네트워킹, HTTP/2, HTTP/3
  8. 테스트 및 모니터링
  9. 빠른 승리
  10. 한 페이지에 모든 것
  11. 체크리스트 다운로드(PDF, Apple Pages, MS Word)
  12. 다음 가이드를 놓치지 않으려면 이메일 뉴스레터를 구독하세요.