2021년 프런트 엔드 성능 체크리스트(PDF, Apple Pages, MS Word)

게시 됨: 2022-03-10
요약 요약 ↬ 2021년을…빨리 만들자! 연간 프론트엔드 성능 체크리스트(PDF, Apple Pages, MS Word로 사용 가능)에는 메트릭에서 도구 및 프론트엔드 기술에 이르기까지 오늘날 웹에서 빠른 경험을 만들기 위해 알아야 할 모든 것이 포함되어 있습니다. 2016년 이후 업데이트되었습니다. 아, 이메일 뉴스레터에서도 유용한 프론트 엔드 팁을 얻을 수 있습니다.

웹 성능은 까다로운 짐승이죠, 그렇죠? 성능 측면에서 우리의 위치와 성능 병목 현상이 정확히 무엇인지 어떻게 알 수 있습니까? 비싼 JavaScript, 느린 웹 글꼴 전달, 무거운 이미지 또는 느린 렌더링입니까? 트리 흔들기, 범위 호이스팅, 코드 분할, 교차 관찰자, 점진적 수화, 클라이언트 힌트, HTTP/3, 서비스 워커, 에지 워커를 사용한 모든 멋진 로딩 패턴으로 충분히 최적화했습니까? 그리고 가장 중요한 것은 어디에서 성과 향상을 시작하고 장기적으로 성과 문화를 구축할 수 있느냐는 것입니다.

그 당시에는 성능이 단순히 사후 고려 사항 에 불과한 경우가 많았습니다. 종종 프로젝트가 끝날 때까지 연기되며 축소, 연결, 자산 최적화 및 잠재적으로 서버의 config 파일에 대한 몇 가지 미세 조정으로 귀결됩니다. 지금 돌이켜보면 상황이 상당히 많이 변한 것 같다.

성능은 단지 기술적인 문제가 아닙니다. 성능은 접근성에서 사용성, 검색 엔진 최적화에 이르기까지 모든 것에 영향을 미치며, 이를 워크플로에 적용할 때 성능에 미치는 영향을 고려하여 설계 결정을 내려야 합니다. 성능을 지속적으로 측정, 모니터링 및 개선해야 하며 , 웹의 복잡성이 증가하면 메트릭을 추적하기 어렵게 만드는 새로운 문제가 발생합니다. 데이터는 장치, 브라우저, 프로토콜, 네트워크 유형 및 대기 시간에 따라 크게 달라지기 때문입니다( CDN, ISP, 캐시, 프록시, 방화벽, 로드 밸런서 및 서버는 모두 성능에 중요한 역할을 합니다.

따라서 프로젝트 시작부터 웹 사이트의 최종 릴리스까지 성능을 개선할 때 염두에 두어야 하는 모든 사항에 대한 개요를 만들면 어떻게 될까요? 아래 에서 2021년에 대한 (편향 없고 객관적인) 프런트 엔드 성능 체크리스트를 찾을 수 있습니다. 응답 시간이 빠르고 사용자 상호 작용이 원활하며 사이트가 사용자의 대역폭을 소모합니다.

목차

  • 모두 별도의 페이지에 있습니다.
  • 준비하기: 계획 및 측정항목
    성능 문화, 핵심 Web Vitals, 성능 프로필, CrUX, Lighthouse, FID, TTI, CLS, 장치.
  • 현실적인 목표 설정
    성능 예산, 성능 목표, RAIL 프레임워크, 170KB/30KB 예산.
  • 환경 정의
    프레임워크 선택, 기본 성능 비용, Webpack, 종속성, CDN, 프런트 엔드 아키텍처, CSR, SSR, CSR + SSR, 정적 렌더링, 사전 렌더링, PRPL 패턴.
  • 자산 최적화
    Brotli, AVIF, WebP, 반응형 이미지, AV1, 적응형 미디어 로딩, 비디오 압축, 웹 글꼴, Google 글꼴.
  • 빌드 최적화
    JavaScript 모듈, 모듈/모듈 패턴, 트리 쉐이킹, 코드 분할, 범위 호이스팅, Webpack, 차등 서비스, 웹 작업자, WebAssembly, JavaScript 번들, React, SPA, 부분 수화, 상호 작용 시 가져오기, 타사, 캐시.
  • 배달 최적화
    지연 로딩, 교차 관찰자, 렌더링 및 디코딩 지연, 중요한 CSS, 스트리밍, 리소스 힌트, 레이아웃 변경, 서비스 작업자.
  • 네트워킹, HTTP/2, HTTP/3
    OCSP 스테이플링, EV/DV 인증서, 패키징, IPv6, QUIC, HTTP/3.
  • 테스트 및 모니터링
    감사 워크플로, 프록시 브라우저, 404 페이지, GDPR 쿠키 동의 프롬프트, 성능 진단 CSS, 접근성.
  • 빠른 승리
  • 체크리스트 다운로드(PDF, Apple Pages, MS Word)
  • 오프 위 고!

(체크리스트 PDF(166KB)를 다운로드하거나 편집 가능한 Apple Pages 파일(275KB) 또는 .docx 파일(151KB)을 다운로드할 수도 있습니다. 모두 즐거운 최적화 작업을 하세요!)

준비하기: 계획 및 측정항목

미세 최적화는 성과를 추적하는 데 유용하지만 프로세스 전반에 걸쳐 내려진 모든 결정에 영향을 미칠 수 있는 측정 가능한 목표를 염두에 두고 명확하게 정의된 목표를 염두에 두는 것이 중요합니다. 몇 가지 다른 모델이 있으며 아래에 논의된 모델은 상당히 독단적입니다. 초기에 우선 순위를 설정해야 합니다.

  1. 공연문화를 정착시킨다.
    많은 조직에서 프론트엔드 개발자는 일반적인 기본 문제가 무엇인지, 이를 해결하기 위해 어떤 전략을 사용해야 하는지 정확히 알고 있습니다. 그러나 성과 문화에 대한 확고한 지지가 없는 한 각 결정은 부서 간의 전쟁터가 되어 조직을 사일로로 분해할 것입니다. 비즈니스 이해 관계자의 동의가 필요하며 이를 얻으려면 속도(특히 나중에 자세히 다룰 핵심 성능 지표)에 대한 사례 연구 또는 개념 증명을 수립해야 메트릭 및 핵심 성과 지표에 이점이 있습니다. ( KPI ) 그들은 관심을 가지고 있습니다.

    예를 들어, 성능을 보다 가시적으로 만들기 위해 전환율과 응용 프로그램 로드 시간 간의 상관 관계와 렌더링 성능을 표시하여 수익 성능에 미치는 영향을 노출할 수 있습니다. 또는 검색 봇 크롤링 속도(PDF, 27–50페이지).

    개발/디자인 팀과 비즈니스/마케팅 팀 간의 긴밀한 연계 없이는 성과가 장기적으로 유지될 수 없습니다. 고객 서비스 및 영업 팀에 들어오는 일반적인 불만 사항을 연구하고 높은 이탈률 및 전환율 하락에 대한 분석을 연구합니다. 성능 향상이 이러한 일반적인 문제 중 일부를 완화하는 데 어떻게 도움이 되는지 알아보십시오. 이야기하고 있는 이해 관계자 그룹에 따라 논쟁을 조정하십시오.

    모바일과 데스크톱(예: Google Analytics 사용) 모두에서 성능 실험을 실행하고 결과를 측정합니다. 실제 데이터를 사용하여 회사 맞춤형 사례 연구를 구축하는 데 도움이 됩니다. 또한 WPO 통계에 게시된 사례 연구 및 실험의 데이터를 사용하면 성능이 중요한 이유와 성능이 사용자 경험 및 비즈니스 메트릭에 미치는 영향에 대한 비즈니스의 민감도를 높이는 데 도움이 됩니다. 하지만 성과가 중요하다고 말하는 것만으로는 충분하지 않습니다. 또한 측정 가능하고 추적 가능한 목표를 설정하고 시간이 지남에 따라 이를 관찰해야 합니다.

    거기에 도착하는 방법? 장기적 성과 구축에 대한 강연에서 Allison McKnight는 Etsy에서 공연 문화를 구축하는 데 그녀가 어떻게 도왔는지에 대한 포괄적인 사례 연구를 공유합니다(슬라이드). 보다 최근에 Tammy Everts는 크고 작은 조직 모두에서 매우 효과적인 성과 팀의 습관에 대해 이야기했습니다.

    조직에서 이러한 대화를 나누는 동안 UX가 경험의 스펙트럼인 것처럼 웹 성능은 분포라는 점을 명심하는 것이 중요합니다. Karolina Szczur가 말했듯이 "하나의 숫자가 열망하는 등급을 제공할 수 있을 것으로 기대하는 것은 잘못된 가정입니다." 따라서 성과 목표는 세분화되고 추적 가능하며 유형적이어야 합니다.

모바일에서 세션당 빠른 로드 시간을 경험한 사용자는 평균보다 17% 더 많은 수익을 얻습니다.
모바일에서 세션당 빠른 로드 시간을 경험한 사용자는 평균보다 17% 더 많은 수익을 가져옵니다. (Addy Osmani를 통한 웹 성능의 영향)
단일 숫자가 열망하는 등급을 제공할 수 있을 것으로 기대하는 것은 잘못된 가정입니다.
단일 숫자가 열망하는 등급을 제공할 수 있을 것으로 기대하는 것은 잘못된 가정입니다. (이미지 크레디트: 성능은 Karolina Czczur를 통해 배포됨)
  1. 목표: 가장 빠른 경쟁자보다 최소 20% 더 빠릅니다.
    심리학 연구에 따르면 사용자가 귀하의 웹사이트가 경쟁업체의 웹사이트보다 빠르다고 느끼도록 하려면 최소 20% 빨라야 합니다. 주요 경쟁업체를 연구하고 모바일 및 데스크톱에서 수행하는 방법에 대한 메트릭을 수집하고 경쟁업체를 능가하는 데 도움이 되는 임계값을 설정합니다. 하지만 정확한 결과와 목표를 얻으려면 먼저 분석을 연구하여 사용자 경험을 철저히 파악해야 합니다. 그런 다음 테스트를 위해 90번째 백분위수의 경험을 모방할 수 있습니다.

    경쟁업체의 성과에 대한 좋은 첫인상을 얻으려면 Chrome UX 보고서( CrUX , 기성품 RUM 데이터 세트, Ilya Grigorik의 비디오 소개 및 Rick Viscomi의 세부 가이드) 또는 RUM 모니터링 도구인 Treo를 사용할 수 있습니다. Chrome UX 보고서에서 제공합니다. 데이터는 Chrome 브라우저 사용자로부터 수집되므로 보고서는 Chrome 전용이지만 광범위한 방문자에 대해 성능, 가장 중요한 핵심 성능 평가 점수를 상당히 철저하게 분포시킵니다. 새로운 CrUX 데이터 세트는 매월 두 번째 화요일에 발표됩니다.

    또는 다음을 사용할 수도 있습니다.

    • Addy Osmani의 Chrome UX 보고서 비교 도구,
    • Speed ​​Scorecard(수익 영향 추정기 제공),
    • 실제 사용자 경험 테스트 비교 또는
    • SiteSpeed ​​CI(합성 테스트 기반).

    참고 : Page Speed ​​Insights 또는 Page Speed ​​Insights API(아니요, 더 이상 사용되지 않습니다!)를 사용하는 경우 집계가 아닌 특정 페이지에 대한 CrUX 성능 데이터를 얻을 수 있습니다. 이 데이터는 "랜딩 페이지" 또는 "제품 목록"과 같은 자산의 실적 목표를 설정하는 데 훨씬 더 유용할 수 있습니다. 그리고 CI를 사용하여 예산을 테스트하는 경우 대상 설정에 CrUX를 사용한 경우 테스트된 환경이 CrUX와 일치하는지 확인해야 합니다( Patrick Meenan에게 감사드립니다! ).

    속도의 우선 순위를 정하는 이유를 보여주기 위해 도움이 필요하거나, 느린 성능과 함께 전환율 감소 또는 이탈률 증가를 시각화하고 싶거나, 조직에서 RUM 솔루션을 옹호해야 하는 경우, Sergey Chernyshev는 데이터를 시뮬레이션하고 시각화하여 요점을 파악하는 데 도움이 되는 오픈 소스 도구인 UX 속도 계산기를 구축했습니다.

    CrUX는 Google Chrome 사용자로부터 수집된 트래픽과 함께 시간 경과에 따른 성능 분포에 대한 개요를 생성합니다.
    CrUX는 Google Chrome 사용자로부터 수집된 트래픽과 함께 시간 경과에 따른 성능 분포에 대한 개요를 생성합니다. Chrome UX 대시보드에서 직접 만들 수 있습니다. (큰 미리보기)
    성능에 대한 근거를 제시해야 할 때: UX 속도 계산기는 실제 데이터를 기반으로 이탈률, 전환 및 총 수익에 대한 성능의 영향을 시각화합니다.
    성능에 대한 근거를 제시해야 할 때: UX 속도 계산기는 실제 데이터를 기반으로 이탈률, 전환 및 총 수익에 대한 성능의 영향을 시각화합니다. (큰 미리보기)

    때로는 CrUX에서 가져온 데이터를 다른 데이터와 결합하여 속도 저하, 사각 지대 및 비효율이 있는 곳(경쟁업체 또는 프로젝트)을 빠르게 해결해야 하는 경우가 있습니다. Harry Roberts는 작업에서 주요 페이지 유형별로 성능을 분류하고 주요 메트릭이 어떻게 다른지 추적하는 데 사용하는 Site-Speed ​​Topography Spreadsheet를 사용하고 있습니다. 스프레드시트를 Google 스프레드시트, Excel, OpenOffice 문서 또는 CSV로 다운로드할 수 있습니다.

    사이트의 주요 페이지에 대해 표시되는 주요 메트릭이 있는 사이트 속도 지형
    사이트의 주요 페이지에 대해 표시되는 주요 메트릭이 있는 사이트 속도 지형. (큰 미리보기)

    그리고 끝까지 진행하고 싶다면 사이트의 모든 페이지에서 Lighthouse 성능 감사를 실행할 수 있습니다(Lightouse Parade를 통해). CSV로 저장한 출력과 함께. 이렇게 하면 경쟁업체의 특정 페이지(또는 페이지 유형)가 더 나쁘거나 더 나은 성과를 거두고 무엇에 집중해야 하는지 식별하는 데 도움이 됩니다. (자신의 사이트의 경우 데이터를 분석 엔드포인트로 보내는 것이 더 나을 수 있습니다!).

    Lighthouse Parade를 사용하면 사이트의 모든 페이지에서 Lighthouse 성능 감사를 실행할 수 있으며 출력은 CSV로 저장됩니다.
    Lighthouse Parade를 사용하면 CSV로 저장된 출력을 사용하여 사이트의 모든 페이지에서 Lighthouse 성능 감사를 실행할 수 있습니다. (큰 미리보기)

    이러한 방식으로 데이터를 수집하고, 스프레드시트를 설정하고, 20%를 줄이고, 목표( 성과 예산 )를 설정합니다. 이제 테스트할 측정 가능한 항목이 있습니다. 예산을 염두에 두고 대화형 시간을 단축하기 위해 최소한의 페이로드만 제공하려는 경우 합리적인 경로에 있는 것입니다.

    시작하는 데 리소스가 필요하십니까?

    • Addy Osmani는 성능 예산 책정을 시작하는 방법, 새로운 기능의 영향을 수량화하는 방법, 예산이 초과되었을 때 시작하는 방법에 대한 매우 상세한 글을 작성했습니다.
    • 성능 예산으로 설계에 접근하는 방법에 대한 Lara Hogan의 가이드는 설계자에게 유용한 지침을 제공할 수 있습니다.
    • Harry Roberts는 Request Map,
    • Jonathan Fielding의 Performance Budget Calculator, Katie Hempenius의 perf-budget-calculator 및 Browser Calories는 예산을 만드는 데 도움이 될 수 있습니다.
    • 많은 회사에서 성과 예산은 열망이 아니라 오히려 실용적이어야 하며, 특정 지점을 지나치지 않도록 유지 신호 역할을 합니다. 이 경우 지난 2주 동안 최악의 데이터 포인트를 임계값으로 선택하고 거기에서 가져올 수 있습니다. Performance Budgets는 이를 달성하기 위한 전략을 실용적으로 보여줍니다.
    • 또한 빌드 크기를 보고하는 그래프로 대시보드를 설정하여 성능 예산과 현재 성능을 모두 볼 수 있습니다 . 이를 가능하게 하는 많은 도구가 있습니다. SiteSpeed.io 대시보드(오픈 소스), SpeedCurve 및 Calibre는 그 중 일부에 불과하며 perf.rocks에서 더 많은 도구를 찾을 수 있습니다.
    브라우저 칼로리는 성능 예산을 설정하고 페이지가 이 수치를 초과하는지 여부를 측정하는 데 도움이 됩니다.
    브라우저 칼로리는 성능 예산을 설정하고 페이지가 이 수치를 초과하는지 여부를 측정하는 데 도움이 됩니다. (큰 미리보기)

    예산이 확보되면 Webpack Performance Hints 및 Bundlesize, Lighthouse CI, PWMetrics 또는 Sitespeed CI를 사용하여 빌드 프로세스에 통합하여 pull 요청에 예산을 적용하고 PR 주석에 점수 기록을 제공하십시오.

    전체 팀에 성능 예산을 공개하려면 Lightwallet을 통해 Lighthouse에 성능 예산을 통합하거나 빠른 Github Actions 통합을 위해 LHCI Action을 사용하십시오. 그리고 사용자 정의가 필요한 경우 엔드포인트 API인 webpagetest-charts-api를 사용하여 WebPagetest 결과에서 차트를 작성할 수 있습니다.

    그러나 성과 인식은 성과 예산만으로 이루어지면 안 됩니다. Pinterest와 마찬가지로 종속성이 많고 번들을 부풀릴 수 있는 파일 및 디렉터리에서 가져오기를 허용하지 않는 사용자 지정 eslint 규칙을 만들 수 있습니다. 전체 팀에서 공유할 수 있는 "안전한" 패키지 목록을 설정합니다.

    또한 귀하의 비즈니스에 가장 유익한 중요한 고객 작업에 대해 생각해 보십시오. 중요한 작업에 대한 허용 가능한 시간 임계값을 연구, 논의 및 정의하고 전체 조직이 승인한 "UX 준비" 사용자 타이밍 표시를 설정합니다. 대부분의 경우 사용자 여정은 여러 부서의 작업과 관련이 있으므로 허용 가능한 시간에 맞춰 조정하면 향후 성능 논의를 지원하거나 방지하는 데 도움이 됩니다. 추가된 리소스 및 기능에 대한 추가 비용이 표시되고 이해되는지 확인합니다.

    구축 중인 제품의 새로운 기능에서 리팩토링, 새로운 글로벌 청중에게 다가가기까지 다양한 기술 이니셔티브와 성과 노력을 조정합니다. 따라서 추가 개발에 대한 대화가 발생할 때마다 성능도 대화의 일부입니다. 코드 기반이 최신이거나 리팩토링되는 중일 때 성능 목표에 훨씬 더 쉽게 도달할 수 있습니다.

    또한 Patrick Meenan이 제안한 것처럼 설계 과정 에서 로딩 순서와 절충안을 계획하는 것이 좋습니다. 어떤 부분이 더 중요한지 조기에 우선 순위를 지정하고 표시 순서를 정의하면 지연될 수 있는 부분도 알게 됩니다. 이상적으로는 해당 순서가 CSS 및 JavaScript 가져오기의 순서도 반영하므로 빌드 프로세스 중에 처리하기가 더 쉬울 것입니다. 또한 페이지가 로드되는 동안(예: 웹 글꼴이 아직 로드되지 않은 경우) "중간" 상태에 있어야 하는 시각적 경험을 고려하십시오.

    조직에 강력한 성과 문화를 구축했으면 시간이 흘러도 우선 순위를 그대로 유지하기 위해 이전 자신보다 20% 더 빠른 것을 목표로 삼으십시오( Guy Podjarny에게 감사드립니다! ). 그러나 봇 트래픽 및 계절성 효과와 함께 고객의 다양한 유형 및 사용 행동(Tobias Baldauf가 케이던스 및 집단이라고 부름)을 고려하십시오.

    기획, 기획, 기획. 초기에 빠른 "낮은 성과" 최적화에 들어가고 싶은 마음이 들 수도 있고 빠른 승리를 위한 좋은 전략일 수도 있습니다. - 맞춤형 성능 목표.

Treo Sites는 실제 데이터를 기반으로 경쟁 분석을 제공합니다.
Treo는 실제 데이터를 기반으로 경쟁 분석을 제공합니다. (큰 미리보기)
2020년 초에 Lighthouse v6에 새로운 메트릭이 추가되었습니다.
2020년 초에 Lighthouse v6에 새로운 측정항목이 추가되었습니다. (큰 미리보기)
  1. 올바른 측정항목을 선택하세요.
    모든 지표가 똑같이 중요한 것은 아닙니다. 어떤 메트릭이 애플리케이션에 가장 중요한지 연구하십시오. 일반적으로 인터페이스의 가장 중요한 픽셀 을 렌더링하기 시작할 수 있는 속도와 렌더링된 픽셀에 대한 입력 응답 성을 얼마나 빨리 제공할 수 있는지에 따라 정의됩니다. 이 지식은 지속적인 노력을 위한 최상의 최적화 목표를 제공할 것입니다. 결국 경험을 정의하는 것은 로드 이벤트나 서버 응답 시간이 아니라 인터페이스가 얼마나 빠른지 인지하는 입니다.

    무슨 뜻이에요? 전체 페이지 로드 시간(예: onLoadDOMContentLoaded 타이밍 사용)에 초점을 맞추는 대신 고객이 인식하는 페이지 로드의 우선 순위를 지정하십시오. 이는 약간 다른 측정항목 집합에 초점을 맞추는 것을 의미합니다. 사실, 올바른 메트릭을 선택하는 것은 명백한 승자가 없는 과정입니다.

    Tim Kadlec의 연구와 그의 강연에서 Marcos Iglesias의 메모를 기반으로 하면 기존 측정항목 을 몇 개의 집합으로 그룹화할 수 있습니다. 일반적으로 성능에 대한 완전한 그림을 얻으려면 이들 모두가 필요하며 특정 경우에는 그 중 일부가 다른 것보다 더 중요합니다.

    • 수량 기반 메트릭 은 요청 수, 가중치 및 성능 점수를 측정합니다. 경보를 발생시키고 시간이 지남에 따라 변경 사항을 모니터링하는 데는 좋지만 사용자 경험을 이해하는 데는 좋지 않습니다.
    • 마일스톤 메트릭 은 로드 프로세스의 수명 동안 상태를 사용합니다(예: Time To First ByteTime To Interactive ). 사용자 경험 및 모니터링을 설명하는 데 적합하지만 이정표 사이에 어떤 일이 발생하는지 알기에는 적합하지 않습니다.
    • 렌더링 메트릭 은 콘텐츠가 얼마나 빨리 렌더링되는지에 대한 추정치를 제공합니다(예: 시작 렌더링 시간, 속도 인덱스 ). 렌더링 성능을 측정하고 조정하는 데는 좋지만 중요한 콘텐츠가 표시되고 상호 작용할 수 있는 시점을 측정하는 데에는 적합하지 않습니다.
    • 사용자 지정 메트릭 은 사용자에 대한 특정 사용자 지정 이벤트(예: Twitter의 첫 트윗 시간 및 Pinterest의 PinnerWaitTime)를 측정합니다. 사용자 경험을 정확하게 설명하는 데는 좋지만 메트릭을 확장하고 경쟁자와 비교하는 데는 좋지 않습니다.

    그림을 완성하기 위해 일반적으로 이러한 모든 그룹에서 유용한 메트릭을 찾습니다. 일반적으로 가장 구체적이고 관련성이 높은 항목은 다음과 같습니다.

    • 인터랙티브 시간 (TTI)
      레이아웃이 안정화 되고 주요 웹 글꼴이 표시되고 기본 스레드가 사용자 입력을 처리할 수 있을 만큼 충분히 사용 가능한 지점(기본적으로 사용자가 UI와 상호 작용할 수 있는 시간 표시)입니다. 사용자가 지연 없이 사이트를 사용하기 위해 경험해야 하는 대기 시간을 이해하기 위한 주요 측정항목입니다. Boris Schapira는 TTI를 안정적으로 측정하는 방법에 대한 자세한 게시물을 작성했습니다.
    • 첫 번째 입력 지연 (FID) 또는 입력 응답
      사용자가 귀하의 사이트와 처음 상호작용할 때부터 브라우저가 실제로 해당 상호작용 에 응답할 수 있을 때까지의 시간입니다. 사용자가 실제로 사이트와 상호 작용할 때 발생하는 그림의 누락된 부분을 설명하므로 TTI를 매우 잘 보완합니다. RUM 지표로만 사용됩니다. 브라우저에서 FID를 측정하기 위한 JavaScript 라이브러리가 있습니다.
    • 최대 함량 페인트 (LCP)
      페이지의 중요한 콘텐츠 가 로드되었을 가능성이 있는 페이지 로드 타임라인의 지점을 표시합니다. 페이지의 가장 중요한 요소는 사용자의 뷰포트에서 볼 수 있는 가장 큰 요소라고 가정합니다. 요소가 접히는 부분 위와 아래 모두에 렌더링되면 보이는 부분만 관련성이 있는 것으로 간주됩니다.
    • 총 차단 시간( 미정 )
      페이지가 안정적으로 상호작용하기 전에 페이지가 얼마나 비대화식인지의 심각도를 수량화하는 데 도움이 되는 측정항목입니다(즉, 기본 스레드에 최소 5초 동안 50ms( 긴 작업 ) 이상 실행되는 작업이 없음). 이 메트릭은 입력 응답을 방지할 만큼 충분히 오랫동안 메인 스레드가 차단된 첫 번째 페인트와 TTI(Time to Interactive) 사이의 총 시간을 측정합니다. 따라서 낮은 TBT가 좋은 성과를 나타내는 좋은 지표라는 것은 놀라운 일이 아닙니다. (고마워, Artem, Phil)
    • 누적 레이아웃 이동( CLS )
      이 측정항목은 사용자가 사이트에 액세스할 때 예상치 못한 레이아웃 변경 ( 리플로우 )을 얼마나 자주 경험하는지 강조합니다. 불안정한 요소와 전반적인 경험에 미치는 영향을 조사합니다. 점수가 낮을수록 좋습니다.
    • 속도 지수
      페이지 콘텐츠가 시각적으로 채워지는 속도를 측정합니다. 점수가 낮을수록 좋습니다. 속도 지수 점수는 시각적 진행 속도를 기반으로 계산되지만 계산된 값일 뿐입니다. 또한 뷰포트 크기에 민감하므로 대상 고객과 일치하는 테스트 구성 범위를 정의해야 합니다. LCP가 더 관련성 있는 메트릭이 되면서 중요성이 줄어들고 있다는 점에 유의하십시오( Boris, Artem에게 감사드립니다! ).
    • CPU 소요 시간
      페인팅, 렌더링, 스크립팅 및 로드 작업에서 메인 스레드가 차단 되는 빈도기간 을 보여주는 메트릭입니다. 높은 CPU 시간은 버벅 거림 경험의 분명한 지표입니다. 즉, 사용자가 작업과 응답 사이에 눈에 띄는 지연을 경험할 때입니다. WebPageTest를 사용하면 "Chrome" 탭에서 "개발 도구 타임라인 캡처"를 선택하여 WebPageTest를 사용하는 모든 장치에서 실행되는 기본 스레드의 분석을 노출할 수 있습니다.
    • 구성 요소 수준 CPU 비용
      CPU 소요 시간 과 마찬가지로 Stoyan Stefanov가 제안한 이 지표 는 JavaScript가 CPU에 미치는 영향을 조사합니다. 아이디어는 개별적으로 전체 경험에 미치는 영향을 이해하기 위해 구성 요소당 CPU 명령 수를 사용하는 것입니다. Puppeteer 및 Chrome을 사용하여 구현할 수 있습니다.
    • 좌절 지수
      위에 나온 많은 메트릭이 특정 이벤트가 발생하는 시기를 설명하지만 Tim Vereecke의 FrustrationIndex는 메트릭을 개별적으로 보는 대신 메트릭 사이의 간격 을 봅니다. 제목이 표시됨, 첫 번째 콘텐츠가 표시됨, 시각적으로 준비됨 및 페이지가 준비된 모양과 같이 최종 사용자가 인식하는 주요 이정표를 보고 페이지를 로드하는 동안 좌절감을 나타내는 수준을 나타내는 점수를 계산합니다. 격차가 클수록 사용자가 불만을 가질 가능성이 커집니다. 사용자 경험을 위한 잠재적으로 좋은 KPI입니다. Tim은 FrustrationIndex와 작동 방식에 대한 자세한 게시물을 게시했습니다.
    • 광고 가중치 영향
      사이트가 광고에 의해 생성된 수익에 의존하는 경우 광고 관련 코드의 가중치를 추적하는 것이 유용합니다. Paddy Ganti의 스크립트는 두 개의 URL(하나는 일반, 다른 하나는 광고 차단)을 구성하고 WebPageTest를 통해 비디오 비교 생성을 요청하고 델타를 보고합니다.
    • 편차 측정항목
      Wikipedia 엔지니어가 언급한 바와 같이 결과에 얼마나 많은 편차 가 존재하는지에 대한 데이터는 도구가 얼마나 신뢰할 수 있는지, 편차 및 이상값에 얼마나 주의를 기울여야 하는지 알려줄 수 있습니다. 큰 편차는 설정에 필요한 조정의 지표입니다. 또한 특정 페이지를 안정적으로 측정하기가 더 어려운지(예: 상당한 변동을 일으키는 타사 스크립트로 인해)를 이해하는 데 도움이 됩니다. 새 브라우저 버전이 출시될 때 성능의 충돌을 이해하기 위해 브라우저 버전을 추적하는 것도 좋은 생각일 수 있습니다.
    • 맞춤 측정항목
      사용자 지정 메트릭은 비즈니스 요구 사항과 고객 경험에 따라 정의됩니다. 중요한 픽셀, 중요한 스크립트, 필요한 CSS 및 관련 자산을 식별하고 사용자에게 얼마나 빨리 전달되는지 측정해야 합니다. 이를 위해 Hero Rendering Times를 모니터링하거나 Performance API를 사용하여 비즈니스에 중요한 이벤트의 특정 타임스탬프를 표시할 수 있습니다. 또한 테스트가 끝날 때 임의의 JavaScript를 실행하여 WebPagetest로 사용자 정의 메트릭을 수집할 수 있습니다.

    첫 번째 의미 있는 페인트 (FMP) 는 위의 개요에 나타나지 않습니다. 서버 데이터를 얼마나 빨리 출력하는지에 대한 통찰력을 제공하는 데 사용되었습니다. 긴 FMP는 일반적으로 메인 스레드를 차단하는 JavaScript를 나타내지만 백엔드/서버 문제와도 관련될 수 있습니다. 그러나 이 측정항목은 케이스의 약 20%에서 정확하지 않은 것으로 나타나 최근에 더 이상 사용되지 않습니다. 보다 안정적이고 추론하기 쉬운 LCP로 효과적으로 대체되었습니다. Lighthouse에서는 더 이상 지원되지 않습니다. 안전한 페이지에 있는지 확인하기 위해 최신 사용자 중심 성능 메트릭 및 권장 사항을 다시 확인하십시오( 감사합니다, Patrick Meenan ).

    Steve Souders는 이러한 많은 지표에 대해 자세히 설명합니다. Time-To-Interactive는 소위 랩 환경 에서 자동화된 감사를 실행하여 측정되지만 First Input Delay는 실제 사용자 경험을 나타내며 실제 사용자는 눈에 띄게 지연됩니다. 일반적으로 항상 두 가지를 모두 측정하고 추적하는 것이 좋습니다.

    애플리케이션의 컨텍스트에 따라 선호하는 메트릭이 다를 수 있습니다. 예를 들어 Netflix TV UI의 경우 키 입력 응답성, 메모리 사용량 및 TTI가 더 중요하고 Wikipedia의 경우 처음/마지막 시각적 변경 및 CPU 소요 시간 메트릭이 더 중요합니다.

    참고 : FID와 TTI는 모두 스크롤 동작을 고려하지 않습니다. 스크롤링은 오프 메인 스레드이기 때문에 독립적으로 발생할 수 있으므로 많은 콘텐츠 소비 사이트에서 이러한 메트릭은 훨씬 덜 중요할 수 있습니다( 감사합니다, Patrick! ).

사용자 중심의 성능 메트릭은 실제 사용자 경험에 대한 더 나은 통찰력을 제공합니다.
사용자 중심의 성능 메트릭은 실제 사용자 경험에 대한 더 나은 통찰력을 제공합니다. FID(First Input Delay)는 이를 달성하기 위한 새로운 지표입니다. (큰 미리보기)
개요의 새로운 핵심 Web Vitals, LCP < 2.5s, FID <100ms, CLS < 0.1
개요의 새로운 핵심 Web Vitals, LCP < 2.5s, FID <100ms, CLS < 0.1. (Core Web Vitals, Addy Osmani를 통해)
  1. 핵심 Web Vitals를 측정하고 최적화합니다 .
    오랫동안 성능 메트릭은 서버가 응답하는 속도와 브라우저가 로드되는 속도에 대한 엔지니어링 관점에 초점을 맞춘 상당히 기술적인 것이었습니다. 메트릭은 서버 타이밍보다 실제 사용자 경험을 캡처하는 방법을 찾으려고 시도하면서 수년에 걸쳐 변경되었습니다. 2020년 5월, Google은 각각 사용자 경험의 고유한 측면을 나타내는 새로운 사용자 중심 성능 측정항목인 핵심 성능 지표를 발표했습니다.

    각각에 대해 Google은 허용 가능한 속도 목표 범위를 권장합니다. 이 평가를 통과하려면 전체 페이지 조회수의 75% 이상이 좋음 범위 를 초과해야 합니다. 이러한 측정항목은 빠르게 주목을 받았으며 2021년 5월에 핵심 성능 평가가 Google 검색의 순위 신호가 되면서( 페이지 경험 순위 알고리즘 업데이트 ) 많은 회사에서 성과 점수에 관심을 돌렸습니다.

    이러한 지표를 염두에 두고 경험을 최적화하기 위한 유용한 기술 및 도구 와 함께 각각의 핵심 핵심 성능을 하나씩 분석해 보겠습니다. (이 기사의 일반적인 조언을 따르면 더 나은 Core Web Vitals 점수를 얻을 수 있습니다.)

    • 가장 큰 내용이 포함된 페인트 ( LCP ) < 2.5초
      페이지 로드 를 측정하고 뷰포트 내에서 볼 수 있는 가장 큰 이미지 또는 텍스트 블록 의 렌더링 시간을 보고합니다. 따라서 LCP는 중요한 정보의 렌더링을 지연시키는 모든 것의 영향을 받습니다. 느린 서버 응답 시간, CSS 차단, 인플라이트 JavaScript(자사 또는 타사), 웹 글꼴 로드, 값비싼 렌더링 또는 페인팅 작업, 게으름 -로드된 이미지, 스켈레톤 화면 또는 클라이언트 측 렌더링.

      좋은 경험을 위해 LCP는 페이지가 처음 로드되기 시작한 후 2.5초 이내에 발생해야 합니다. 즉, 페이지의 첫 번째 보이는 부분을 가능한 한 빨리 렌더링해야 합니다. 이를 위해서는 각 템플릿에 대해 맞춤형 중요 CSS가 필요하고 <head> 주문을 조정하고 중요한 자산을 미리 가져옵니다(나중에 다룰 것입니다).

      낮은 LCP 점수의 주요 원인은 일반적으로 이미지입니다. 잘 최적화된 서버에서 호스팅되는 Fast 3G에서 2.5초 미만으로 LCP를 제공하려면 클라이언트 측 렌더링이 없고 전용 이미지 CDN에서 가져온 이미지가 모두 정적이며 이론상 최대 이미지 크기는 약 144KB에 불과합니다 . 이것이 반응형 이미지가 중요한 이유이며 중요한 이미지를 조기에 미리 로드하는 것( preload 포함)입니다.

      빠른 팁 : 페이지에서 LCP로 간주되는 항목을 찾으려면 DevTools에서 성능 패널의 "타이밍" 아래에 있는 LCP 배지 위로 마우스를 가져갈 수 있습니다( 감사합니다, Tim Kadlec !).

    • 첫 번째 입력 지연 ( FID ) < 100ms.
      UI의 응답 성을 측정합니다. 즉, 탭이나 클릭과 같은 개별 사용자 입력 이벤트에 반응할 수 있기 전에 브라우저가 다른 작업으로 얼마나 시간 을 많이 썼는지 측정합니다. 특히 페이지 로드 중에 메인 스레드가 사용 중이어서 발생하는 지연을 캡처하도록 설계되었습니다.

      목표는 모든 상호 작용에 대해 50–100ms 이내로 유지하는 것입니다. 거기에 도달하려면 긴 작업을 식별하고(>50ms 동안 기본 스레드 차단) 이를 분할하고 번들을 여러 청크로 코드 분할하고 JavaScript 실행 시간을 줄이고 데이터 가져오기를 최적화하고 타사의 스크립트 실행을 연기해야 ​​합니다. , JavaScript를 웹 작업자와 함께 백그라운드 스레드로 이동하고 점진적 수화를 사용하여 SPA에서 재수화 비용을 줄입니다.

      빠른 팁 : 일반적으로 더 나은 FID 점수를 얻기 위한 신뢰할 수 있는 전략은 더 큰 번들을 더 작은 번들로 나누고 사용자가 필요할 때 필요로 하는 것을 제공 하여 기본 스레드에서 작업을 최소화하여 사용자 상호 작용이 지연되지 않도록 하는 것입니다. . 이에 대해서는 아래에서 자세히 다루겠습니다.

    • 누적 레이아웃 이동 ( CLS ) < 0.1.
      부드럽고 자연스러운 상호 작용을 보장하기 위해 UI의 시각적 안정성 을 측정합니다. 즉, 페이지 수명 동안 발생하는 모든 예상치 못한 레이아웃 이동에 대한 모든 개별 레이아웃 이동 점수의 합계입니다. 개별 레이아웃 이동은 이미 표시되었던 요소가 페이지에서 위치를 변경할 때마다 발생합니다. 콘텐츠의 크기와 이동 거리에 따라 점수가 매겨집니다.

      따라서 시프트가 나타날 때마다 - 예를 들어 대체 글꼴과 웹 글꼴이 서로 다른 글꼴 메트릭을 사용하거나 광고, 포함 또는 iframe이 늦게 제공되거나 이미지/비디오 크기가 예약되지 않거나 늦은 CSS가 강제로 다시 칠하거나 변경 사항이 주입되는 경우 늦은 JavaScript — CLS 점수에 영향을 미칩니다. 좋은 경험을 위한 권장 값은 CLS < 0.1입니다.

    Core Web Vitals는 예측 가능한 연간 주기로 시간이 지남에 따라 진화해야 합니다. 첫 해 업데이트의 경우 First Contentful Paint가 Core Web Vitals로 승격되어 FID 임계값이 감소하고 단일 페이지 애플리케이션에 대한 지원이 향상될 것으로 예상할 수 있습니다. 보안, 개인 정보 보호 및 접근성(!) 고려 사항과 함께 더 많은 가중치를 얻은 로드 후 사용자 입력에 대한 응답을 볼 수도 있습니다.

    Core Web Vitals와 관련하여 살펴볼 가치가 있는 유용한 리소스와 기사가 많이 있습니다.

    • Web Vitals 리더보드를 사용하면 모바일, 태블릿, 데스크톱, 3G 및 4G에서 경쟁자들과 점수를 비교할 수 있습니다.
    • Core SERP Vitals, Google 검색 결과에 CrUX의 핵심 Web Vitals를 표시하는 Chrome 확장 프로그램입니다.
    • 간단한 GIF로 CLS를 시각화하는 레이아웃 시프트 GIF 생성기(명령줄에서도 사용 가능).
    • web-vitals 라이브러리는 Core Web Vitals를 수집하여 Google Analytics, Google 태그 관리자 또는 기타 분석 엔드포인트로 보낼 수 있습니다.
    • Patrick Meenan이 WebPageTest가 핵심 Web Vital에 대한 데이터를 노출하는 방법을 탐구하는 WebPageTest로 Web Vital을 분석합니다.
    • Addy Osmani와 함께하는 50분짜리 비디오인 Optimizing with Core Web Vitals에서는 전자 상거래 사례 연구에서 Core Web Vitals를 개선하는 방법을 강조합니다.
    • 실제의 누적 레이아웃 이동 및 실제 세계의 누적 레이아웃 이동은 CLS에 대한 거의 모든 것을 다루고 이탈률, 세션 시간 또는 Rage Clicks와 같은 주요 메트릭과 상관 관계가 있는 Nic Jansma의 포괄적인 기사입니다.
    • JavaScript에서 요청/호출될 때 속성 또는 메서드에 대한 개요와 함께 강제 리플로우는 브라우저가 스타일과 레이아웃을 동기적으로 계산하도록 트리거합니다.
    • CSS 트리거는 레이아웃, 페인트 및 합성을 트리거하는 CSS 속성을 보여줍니다.
    • 레이아웃 불안정성 수정은 WebPageTest를 사용하여 레이아웃 불안정성 문제를 식별하고 수정하는 방법입니다.
    • CLS에 대한 Boris Schapira의 또 다른 매우 상세한 가이드인 Cumulative Layout Shift, The Layout Instability Metric, 계산 방법, 측정 방법 및 최적화 방법.
    • 핵심 성능 향상 방법, 각 메트릭(FCP, TTI, TBT와 같은 다른 웹 바이탈 포함), 발생 시기 및 측정 방법에 대한 Simon Hearne의 자세한 가이드입니다.

    그렇다면 Core Web Vitals는 따라야 할 궁극적인 지표 입니까? 좀 빠지는. Cloudflare, Treo, SpeedCurve, Calibre, WebPageTest(이미 영사 슬라이드 보기에서), Newrelic, Shopify, Next.js, 모든 Google 도구(PageSpeed ​​Insights, Lighthouse + CI, Search 포함)를 포함한 대부분의 RUM 솔루션 및 플랫폼에 이미 노출되어 있습니다. 콘솔 등) 및 기타 여러 가지가 있습니다.

    그러나 Katie Sylor-Miller가 설명하는 것처럼 Core Web Vitals의 주요 문제 중 일부는 브라우저 간 지원이 부족하고 사용자 경험의 전체 수명 주기를 실제로 측정하지 않으며 FID 및 비즈니스 성과가 있는 CLS.

    Core Web Vital이 발전할 것으로 예상해야 하므로 성능 측면에서 현재 위치를 더 잘 이해하기 위해 Web Vital을 사용자 정의 측정 지표와 항상 결합 하는 것이 합리적으로 보입니다.

  2. 청중을 대표하는 장치에서 데이터를 수집하십시오.
    정확한 데이터를 수집하려면 테스트할 장치를 철저히 선택해야 합니다. 대부분의 회사에서 이는 분석을 조사하고 가장 일반적인 장치 유형을 기반으로 사용자 프로필을 생성하는 것을 의미합니다. 그러나 종종 분석만으로는 완전한 그림을 제공하지 못합니다. 타겟 고객의 상당 부분은 경험이 너무 느리고 해당 기기가 분석에서 가장 인기 있는 기기로 표시되지 않을 가능성이 있다는 이유로 사이트를 포기하고 다시 돌아오지 않을 수 있습니다. 따라서 대상 그룹의 공통 장치에 대한 연구를 추가로 수행하는 것이 좋습니다.

    IDC에 따르면 2020년 전 세계적으로 출하되는 모든 휴대전화의 84.8%가 Android 기기입니다. 평균 소비자는 2년마다 휴대폰을 업그레이드하며 미국 휴대폰 교체 주기는 33개월입니다. 전 세계적으로 가장 많이 팔리는 휴대폰의 평균 가격은 200달러 미만입니다.

    그렇다면 대표적인 기기는 최소 24개월 된 Android 기기로 가격은 200달러 이하이며 느린 3G, 400ms RTT 및 400kbps 전송에서 실행되지만 조금 더 비관적입니다. 물론 이것은 회사에 따라 매우 다를 수 있지만 대부분의 고객과 거의 비슷합니다. 실제로 대상 시장에 대한 현재 Amazon 베스트 셀러를 살펴보는 것이 좋습니다. ( 조언을 해주신 Tim Kadlec, Henri Helvetica 및 Alex Russell에게 감사드립니다! ).

    새로운 사이트나 앱을 구축할 때는 항상 타겟 시장의 현재 아마존 베스트 셀러를 먼저 확인하십시오.
    새 사이트나 앱을 구축할 때 항상 먼저 대상 시장에 대한 현재 Amazon 베스트 셀러를 확인하십시오. (큰 미리보기)

    그러면 어떤 테스트 장치를 선택해야 할까요? 위에 요약된 프로필과 잘 맞는 것들. 약간 오래된 Moto G4/G5 Plus, 중급 Samsung 장치(Galaxy A50, S8), Nexus 5X, Xiaomi Mi A3 또는 Xiaomi Redmi Note와 같은 중급 장치를 선택하는 것이 좋습니다. 7 및 Alcatel 1X 또는 Cubot X19와 같은 느린 장치(아마도 개방형 장치 연구실에서). 더 느린 열 조절 장치에서 테스트하려면 약 100달러에 달하는 Nexus 4를 구입할 수도 있습니다.

    또한 각 기기에 사용되는 칩셋을 확인하고 하나의 칩셋을 과대 대표하지 마십시오 . 몇 세대의 Snapdragon과 Apple은 물론 저가형 Rockchip, Mediatek으로 충분할 것입니다 (고마워 Patrick!) .

    장치가 없는 경우 조절된 CPU(5배 속도 저하)로 조절된 3G 네트워크 (예: 300ms RTT, 1.6Mbps 감소, 0.8Mbps 증가)에서 테스트하여 데스크톱에서 모바일 경험을 에뮬레이트합니다. 결국 일반 3G, 느린 4G(예: 170ms RTT, 9Mbps 다운, 9Mbps 업) 및 Wi-Fi로 전환합니다. 성능에 미치는 영향을 보다 명확하게 하기 위해 화요일에 2G를 도입하거나 사무실에 스로틀링된 3G/4G 네트워크를 설정하여 더 빠른 테스트를 수행할 수도 있습니다.

    모바일 장치에서는 데스크톱 컴퓨터에 비해 4~5배 느려질 것으로 예상해야 합니다. 모바일 장치는 GPU, CPU, 메모리 및 배터리 특성이 다릅니다. 그렇기 때문에 평균적인 장치에 대한 좋은 프로필을 갖고 항상 그러한 장치에서 테스트하는 것이 중요합니다.

  3. 일주일 중 가장 느린 요일 소개
    일주일 중 가장 느린 요일을 소개합니다. Facebook은 느린 연결의 가시성과 감도를 높이기 위해 2G 화요일을 도입했습니다. (이미지 출처)

    운 좋게도 데이터 수집을 자동화하고 이러한 지표에 따라 시간 경과에 따른 웹사이트 성능을 측정하는 데 도움이 되는 많은 훌륭한 옵션이 있습니다. 좋은 성능 그림은 성능 메트릭, 실험실 데이터 및 필드 데이터 세트를 포함한다는 점을 명심하십시오.

    • 합성 테스트 도구 는 사전 정의된 장치 및 네트워크 설정(예: Lighthouse , Calibre , WebPageTest )을 사용하여 재현 가능한 환경에서 실험실 데이터 를 수집하고
    • RUM ( 실제 사용자 모니터링 ) 도구는 사용자 상호 작용을 지속적으로 평가하고 현장 데이터 를 수집합니다(예: SpeedCurve , New Relic — 도구도 종합 테스트 제공).

    전자는 제품 작업 중에 성능 문제를 식별, 격리 및 수정하는 데 도움이 되므로 개발 중에 특히 유용합니다. 후자는 사용자가 실제로 사이트에 액세스할 때 실시간으로 발생하는 성능 병목 현상을 이해하는 데 도움이 되므로 장기 유지 관리 에 유용합니다.

    탐색 타이밍, 리소스 타이밍, 페인트 타이밍, 긴 작업 등과 같은 기본 제공 RUM API를 활용하여 합성 테스트 도구와 RUM이 함께 응용 프로그램의 성능에 대한 완전한 그림을 제공합니다. 성능 모니터링을 위한 훌륭한 옵션인 Calibre, Treo, SpeedCurve, mPulse 및 Boomerang, Sitespeed.io를 사용할 수 있습니다. 또한 Server Timing 헤더를 사용하면 백엔드 및 프론트엔드 성능을 모두 한 곳에서 모니터링할 수도 있습니다.

    참고 : 예를 들어 DevTools는 구현 방식으로 인해 HTTP/2 푸시와 상호 작용하는 데 문제가 있으므로 브라우저 외부의 네트워크 수준 조절기를 선택하는 것이 항상 더 안전한 방법입니다( Yoav, Patrick 감사 합니다!). Mac OS의 경우 Network Link Conditioner, Windows Windows Traffic Shaper, Linux netem 및 FreeBSD dummynet에 사용할 수 있습니다.

    Lighthouse에서 테스트할 가능성이 높으므로 다음을 수행할 수 있습니다.

    • Lighthouse CI를 사용하여 시간 경과에 따른 Lighthouse 점수 추적(매우 인상적임)
    • GitHub Actions에서 Lighthouse를 실행하여 모든 PR과 함께 Lighthouse 보고서를 가져옵니다.
    • 사이트의 모든 페이지에서 Lighthouse 성능 감사를 실행하고(Lightouse Parade를 통해) 출력을 CSV로 저장합니다.
    • 더 자세히 알아보려면 Lighthouse Scores Calculator 및 Lighthouse 메트릭 가중치를 사용하십시오.
    • Lighthouse는 Firefox에서도 사용할 수 있지만 내부적으로 PageSpeed ​​Insights API를 사용하고 헤드리스 Chrome 79 User-Agent를 기반으로 보고서를 생성합니다.
Lighthouse CI는 매우 놀랍습니다. Lighthouse 결과에 대해 지속적으로 실행, 저장, 검색 및 주장하는 도구 모음
Lighthouse CI는 매우 놀랍습니다. Lighthouse 결과에 대해 지속적으로 실행, 저장, 검색 및 주장하는 도구 모음입니다. (큰 미리보기)
  1. 테스트를 위해 "깨끗한" 및 "고객" 프로필을 설정합니다.
    수동 모니터링 도구에서 테스트를 실행하는 동안 바이러스 백신 및 백그라운드 CPU 작업을 끄고 백그라운드 대역폭 전송을 제거하고 왜곡된 결과를 피하기 위해 브라우저 확장 없이 깨끗한 사용자 프로필로 테스트하는 것이 일반적인 전략입니다(Firefox 및 Chrome에서).
    DebugBear의 보고서는 암호 관리자, 광고 차단기 및 Evernote 및 Grammarly와 같은 인기 애플리케이션을 포함하여 가장 느린 20개의 확장 프로그램을 강조합니다.
    DebugBear의 보고서는 암호 관리자, 광고 차단기, Evernote 및 Grammarly와 같은 인기 애플리케이션을 포함하여 가장 느린 20개의 확장 프로그램을 강조합니다. (큰 미리보기)

    그러나 고객이 자주 사용하는 브라우저 확장 을 연구하고 전용 "고객" 프로필 로도 테스트하는 것도 좋은 생각입니다. 실제로 일부 확장 프로그램은 애플리케이션의 성능에 중대한 영향을 미칠 수 있으며(2020 Chrome 확장 프로그램 성능 보고서) 사용자가 많이 사용하는 경우 이를 미리 고려하는 것이 좋습니다. 따라서 "깨끗한" 프로필 결과만으로는 지나치게 낙관적이며 실제 시나리오에서 무너질 수 있습니다.

  2. 동료들과 성과 목표를 공유하십시오.
    성과 목표가 팀의 모든 구성원에게 친숙한지 확인하여 선에서 오해를 피하십시오. 디자인, 마케팅 또는 그 사이의 모든 결정은 성능에 영향 을 미치며 전체 팀에 책임과 소유권을 분산하면 나중에 성능 중심 의사 결정이 간소화됩니다. 성능 예산 및 초기에 정의된 우선 순위에 따라 설계 결정을 매핑합니다.

현실적인 목표 설정

  1. 100밀리초 응답 시간, 60fps.
    상호 작용이 원활하게 느껴지도록 인터페이스는 사용자 입력에 응답하는 데 100ms가 있습니다. 그보다 길면 사용자는 앱을 랙으로 인식합니다. 사용자 중심의 성능 모델인 RAIL은 건강한 목표 를 제공합니다. <100밀리초 응답을 허용하려면 페이지는 늦어도 매 <50밀리초 후에 기본 스레드에 제어를 되돌려야 합니다. 예상 입력 대기 시간은 임계값에 도달했는지 알려주며 이상적으로는 50ms 미만이어야 합니다. 애니메이션과 같은 고압 포인트의 경우 할 수 있는 곳에서는 다른 작업을 하지 않는 것이 가장 좋고, 할 수 없는 곳에서는 최소한의 작업을 수행하는 것이 가장 좋습니다.

    사용자 중심의 성능 모델인 RAIL.
    사용자 중심의 성능 모델인 RAIL.

    또한 애니메이션의 각 프레임은 16밀리초 미만으로 완료되어야 하므로 초당 60프레임(1초 ÷ 60 = 16.6밀리초), 바람직하게는 10밀리초 미만을 달성해야 합니다. 브라우저가 새 프레임을 화면에 칠하는 데 시간이 필요하기 때문에 코드 실행이 16.6밀리초 표시에 도달하기 전에 완료되어야 합니다. 우리는 120fps(예: iPad Pro의 화면은 120Hz에서 실행됨)에 대한 대화를 시작했으며 Surma는 120fps에 대한 몇 가지 렌더링 성능 솔루션을 다루었지만 아직 우리가 보고 있는 목표는 아닙니다.

    성능 기대치는 비관적이지만 인터페이스 디자인은 낙관적이며 유휴 시간을 현명하게 사용하십시오(idlize, idle-until-urgent 및 react-idle 확인). 분명히 이러한 목표는 로드 성능이 아니라 런타임 성능에 적용됩니다.

  2. FID < 100ms, LCP < 2.5s, TTI < 5s on 3G, 중요 파일 크기 예산 < 170KB(gzipped).
    달성하기가 매우 어려울 수 있지만 좋은 궁극적인 목표는 5초 미만의 상호 작용 시간이고 반복 방문의 경우 2초 미만을 목표로 하는 것입니다(서비스 작업자만 가능). 2.5초 미만의 가장 큰 콘텐츠가 포함된 페인트 를 목표로 하고 총 차단 시간누적 레이아웃 이동 을 최소화합니다. 허용 가능한 첫 번째 입력 지연 은 100ms–70ms 미만입니다. 위에서 언급했듯이 우리는 400ms RTT 및 400kbps 전송 속도로 에뮬레이트된 느린 3G 네트워크의 200달러 Android 전화(예: Moto G4)를 기준으로 고려하고 있습니다.

    웹에서 콘텐츠를 신속하게 전달하기 위한 합리적인 목표를 효과적으로 형성하는 두 가지 주요 제약 조건이 있습니다. 한편으로는 TCP 느린 시작으로 인한 네트워크 전달 제약 이 있습니다. HTML의 처음 14KB(각 1460바이트, 약 14.25KB를 만드는 TCP 패킷 10개)는 문자 그대로 받아들여지지는 않지만 가장 중요한 페이로드 청크이며 첫 번째 왕복에서 전달할 수 있는 예산의 유일한 부분입니다( 모바일 깨우기 시간으로 인해 400ms RTT에서 1초 안에 얻을 수 있는 모든 것입니다.

    Ilya Grigorik의 고성능 브라우저 네트워킹
    TCP 연결을 사용하면 작은 혼잡 창으로 시작하여 모든 왕복에 대해 두 배로 늘립니다. 첫 번째 왕복에서는 14KB를 맞출 수 있습니다. 보낸 사람: Ilya Grigorik의 고성능 브라우저 네트워킹. (큰 미리보기)

    ( 참고 : TCP는 일반적으로 네트워크 연결을 상당히 활용하지 못하기 때문에 Google은 TCP 지연 제어 TCP 흐름 제어 알고리즘인 TCP Bottleneck Bandwidth 및 RRT( BBR )를 개발했습니다. 최신 웹용으로 설계되어 실제 혼잡에 응답합니다. TCP와 같은 패킷 손실 대신 처리량이 더 높고 대기 시간이 짧고 훨씬 빠르며 알고리즘은 다르게 작동합니다.( 감사합니다, Victor, Barry! )

    반면에 JavaScript 구문 분석 및 실행 시간으로 인해 메모리와 CPU에 대한 하드웨어 제약 이 있습니다(나중에 자세히 설명하겠습니다). 첫 번째 단락에서 설명한 목표를 달성하려면 JavaScript의 중요한 파일 크기 예산을 고려해야 합니다. 예산이 얼마인지에 대한 의견은 다양하지만(프로젝트의 특성에 따라 크게 다릅니다), 170KB JavaScript gzip으로 압축된 예산은 이미 중급 전화기에서 구문 분석하고 컴파일하는 데 최대 1초가 소요됩니다. 170KB가 압축 해제 시 해당 크기의 3배로 확장된다고 가정하면(0.7MB), 이는 이미 Moto G4/G5 Plus에서 "적절한" 사용자 경험의 죽음의 신호일 수 있습니다.

    Wikipedia 웹사이트의 경우 2020년에 전 세계적으로 Wikipedia 사용자의 코드 실행이 19% 빨라졌습니다. 따라서 연간 웹 성능 지표가 안정적으로 유지된다면 환경이 계속 개선됨에 따라 실제로 퇴행 하고 있다는 경고 신호입니다(자세한 내용은 Gilles Dubuc의 블로그 게시물 참조).

    동남아시아, 아프리카 또는 인도와 같이 성장하는 시장을 목표로 하려면 매우 다른 제약 조건을 살펴봐야 합니다. Addy Osmani는 소수의 저가, 고품질 장치, 고품질 네트워크 사용 불가, 고가의 모바일 데이터와 같은 주요 피처폰 제약 조건을 이러한 환경에 대한 PRPL-30 예산 및 개발 지침과 함께 다룹니다.

    Addy Osmani에 따르면 지연 로드 경로의 권장 크기도 35KB 미만입니다.
    Addy Osmani에 따르면 지연 로드 경로의 권장 크기도 35KB 미만입니다. (큰 미리보기)
    Addy Osmani는 피처폰을 대상으로 하는 경우 PRPL-30 성능 예산(30KB 압축 + 초기 번들 축소)을 제안합니다.
    Addy Osmani는 피처폰을 대상으로 하는 경우 PRPL-30 성능 예산(30KB 압축 + 초기 번들 축소)을 제안합니다. (큰 미리보기)

    실제로 Google의 Alex Russell은 합리적인 상한선으로 gzip으로 압축된 130~170KB를 목표로 할 것을 권장합니다. 실제 시나리오에서 대부분의 제품은 가깝지 않습니다. 오늘날 중간 번들 크기는 약 452KB 로, 이는 2015년 초에 비해 53.6% 증가한 것입니다. -대화형 .

    2019년 전 세계적으로 가장 많이 팔린 스마트폰에 대한 Geekbench CPU 성능 벤치마크. JavaScript는 단일 코어 성능을 강조하며 CPU에 종속됩니다.
    2019년 전 세계적으로 가장 많이 팔린 스마트폰에 대한 Geekbench CPU 성능 벤치마크. JavaScript는 단일 코어 성능을 강조하며(다른 웹 플랫폼보다 본질적으로 단일 스레드임을 기억하십시오) CPU 바운드입니다. Addy의 기사 "20달러 피처폰에서 웹 페이지 빠르게 로드"에서. (큰 미리보기)

    그러나 번들 크기 예산을 초과할 수도 있습니다. 예를 들어, 우리는 브라우저의 메인 쓰레드의 활동을 기반으로 성능 예산을 설정할 수 있습니다. Calibre, SpeedCurve 및 Bundlesize와 같은 도구를 사용하면 예산을 확인하고 빌드 프로세스에 통합할 수 있습니다.

    마지막으로 성능 예산 은 고정된 값이 되어서는 안 됩니다. 네트워크 연결에 따라 성능 예산이 조정되어야 하지만 느린 연결의 페이로드는 사용 방식에 관계없이 훨씬 더 "비쌉니다".

    참고 : HTTP/2가 널리 보급되고 5G 및 HTTP/3가 출시되고 휴대폰이 빠르게 발전하고 SPA가 번창하는 시대에 이처럼 경직된 예산을 설정하는 것이 이상하게 들릴 수 있습니다. 그러나 혼잡한 네트워크에서 천천히 발전하는 인프라, 데이터 한도, 프록시 브라우저, 데이터 저장 모드 및 교활한 로밍 요금에 이르기까지 모든 것을 포함하여 네트워크 및 하드웨어의 예측할 수 없는 특성을 처리할 때 합리적으로 들립니다.

Addy Osmani의 'Fast By Default: Modern Loading Best Practices'에서
Fast By Default: Addy Osmani의 최신 로딩 모범 사례(슬라이드 19)
성능 예산은 평균적인 모바일 장치의 네트워크 조건에 따라 조정되어야 합니다.
성능 예산은 평균적인 모바일 장치의 네트워크 조건에 따라 조정되어야 합니다. (이미지 출처: Katie Hempenius) (큰 미리보기)

환경 정의

  1. 빌드 도구를 선택하고 설정합니다.
    요즘 멋지다고 생각하는 것에 너무 많은 관심을 기울이지 마십시오. Grunt, Gulp, Webpack, Parcel 또는 도구 조합 등 빌드 환경에 따라 달라집니다. 필요한 결과를 얻고 빌드 프로세스를 유지 관리하는 데 문제가 없다면 잘 하고 있는 것입니다.

    빌드 도구 중에서 Rollup이 계속 인기를 얻고 있고 Snowpack도 마찬가지지만 Webpack은 말 그대로 수백 개의 플러그인을 사용하여 빌드 크기를 최적화할 수 있는 가장 확실한 도구인 것 같습니다. Webpack 로드맵 2021을 주목하십시오.

    최근 등장한 가장 주목할만한 전략 중 하나는 중복 코드를 최소화하기 위해 Next.js와 Gatsby에서 Webpack을 사용한 Granular 청킹입니다. 기본적으로 모든 진입점에서 공유되지 않는 모듈은 이를 사용하지 않는 경로에 대해 요청할 수 있습니다. 필요한 것보다 더 많은 코드가 다운로드되므로 결국 오버헤드가 됩니다. Next.js의 세분화된 청크를 사용하면 서버 측 빌드 매니페스트 파일 을 사용하여 다른 진입점에서 사용되는 출력 청크를 결정할 수 있습니다.

    Webpack 프로젝트에서 중복 코드를 줄이기 위해 기본적으로 Next.js 및 Gatsby에서 활성화된 세분화된 청킹을 사용할 수 있습니다.
    Webpack 프로젝트에서 중복 코드를 줄이기 위해 기본적으로 Next.js 및 Gatsby에서 활성화된 세분화된 청크를 사용할 수 있습니다. 이미지 크레디트: Addy Osmani. (큰 미리보기)

    SplitChunksPlugin을 사용하면 여러 경로에서 중복 코드를 가져오는 것을 방지하기 위해 여러 조건에 따라 여러 분할 청크가 생성됩니다. 이렇게 하면 탐색 중 페이지 로드 시간과 캐싱이 향상됩니다. Next.js 9.2 및 Gatsby v2.20.7에서 제공됩니다.

    Webpack을 시작하는 것은 어려울 수 있습니다. 따라서 Webpack에 대해 자세히 알아보려면 다음과 같은 훌륭한 리소스가 있습니다.

    • Webpack 문서는 — 분명히 — 좋은 출발점이며 Webpack — Raja Rao의 The Confusing Bits 및 Andrew Welch의 An Annotated Webpack Config도 마찬가지입니다.
    • Sean Larkin은 Webpack: The Core Concepts에 대한 무료 과정을 제공하고 Jeffrey Way는 모두를 위한 Webpack에 대한 환상적인 무료 과정을 공개했습니다. 둘 다 Webpack에 뛰어들기 위한 훌륭한 입문서입니다.
    • Webpack Fundamentals는 FrontendMasters에서 출시한 Sean Larkin과 함께 하는 매우 포괄적인 4시간 과정입니다.
    • Webpack 예제에는 주제 및 목적별로 분류된 수백 가지의 바로 사용할 수 있는 Webpack 구성이 있습니다. 보너스: 기본 구성 파일을 생성하는 Webpack 구성 구성자도 있습니다.
    • Awesome-webpack은 Angular, React 및 프레임워크에 구애받지 않는 프로젝트에 대한 기사, 비디오, 코스, 책 및 예제를 포함하여 유용한 Webpack 리소스, 라이브러리 및 도구의 선별된 목록입니다.
    • Webpack을 사용한 빠른 프로덕션 자산 빌드로의 여정은 팀이 RequireJS 기반 JavaScript 빌드 시스템 사용에서 Webpack 사용으로 전환한 방법과 평균 4분 만에 13,200개 이상의 자산을 관리하여 빌드를 최적화한 방법에 대한 Etsy의 사례 연구입니다.
    • Webpack 성능 팁은 Ivan Akulov의 금광 스레드로, Webpack에 특별히 초점을 맞춘 팁을 포함하여 많은 성능 중심 팁을 제공합니다.
    • Awesome-webpack-perf는 성능을 위한 유용한 Webpack 도구 및 플러그인이 포함된 금광 GitHub 리포지토리입니다. Ivan Akulov도 관리합니다.
Webpack을 사용한 빠른 프로덕션 빌드를 위한 Etsy의 여정 시각화
Webpack을 통한 빠른 프로덕션 빌드를 위한 Etsy의 여정(Addy Osmani를 통해)(큰 미리보기)
  1. 점진적 향상을 기본값으로 사용합니다.
    하지만 세월이 흘러도 프론트 엔드 아키텍처 및 배포의 기본 원칙으로 점진적인 향상을 유지하는 것이 안전한 방법입니다. 먼저 핵심 경험을 설계 및 구축한 다음, 지원 가능한 브라우저를 위한 고급 기능으로 경험을 향상시켜 탄력적인 경험을 만드십시오. 웹사이트가 최적이 아닌 네트워크의 열악한 브라우저에서 열악한 화면을 가진 느린 컴퓨터에서 빠르게 실행되는 경우 적절한 네트워크에서 좋은 브라우저가 있는 빠른 컴퓨터에서만 더 빠르게 실행됩니다.

    사실, 적응형 모듈 서비스를 통해 우리는 다른 수준으로 점진적인 향상을 가져오고, 저가형 장치에 "라이트" 핵심 경험을 제공하고 고급형 장치에 대한 보다 정교한 기능으로 향상시키는 것 같습니다. 점진적인 향상은 곧 사라지지 않을 것입니다.

  2. 강력한 성능 기준을 선택하십시오.
    네트워크, 열 제한, 캐시 제거, 타사 스크립트, 파서 차단 패턴, 디스크 I/O, IPC 대기 시간, 설치된 확장, 바이러스 백신 소프트웨어 및 방화벽, 백그라운드 CPU 작업, 하드웨어 및 메모리 제약 등 로드에 영향을 미치는 많은 알려지지 않은 사항이 있습니다. L2/L3 캐싱의 차이점, RTTS — JavaScript는 기본적으로 렌더링을 차단하는 웹 글꼴과 너무 많은 메모리를 사용하는 이미지 다음으로 경험 비용이 가장 높습니다. 성능 병목 현상이 서버에서 클라이언트로 이동함에 따라 개발자로서 우리는 이러한 알려지지 않은 모든 사항을 훨씬 더 자세히 고려해야 합니다.

    이미 임계 경로 HTML/CSS/JavaScript, 라우터, 상태 관리, 유틸리티, 프레임워크 및 애플리케이션 로직이 포함된 170KB 예산으로 네트워크 전송 비용, 구문 분석/컴파일 시간 및 런타임 비용을 철저히 조사해야 합니다. 우리가 선택한 프레임워크. 운 좋게도 지난 몇 년 동안 브라우저가 스크립트를 구문 분석하고 컴파일하는 속도가 크게 향상되었습니다. 그러나 JavaScript 실행은 여전히 ​​주요 병목 현상이므로 스크립트 실행 시간과 네트워크에 세심한 주의를 기울이는 것이 영향을 미칠 수 있습니다.

    Tim Kadlec은 최신 프레임워크의 성능에 대한 환상적인 연구를 수행했으며 "JavaScript 프레임워크에는 비용이 있습니다"라는 기사에 요약했습니다. 우리는 종종 독립 실행형 프레임워크의 영향에 대해 이야기하지만 Tim이 언급한 것처럼 실제로 여러 프레임워크를 사용하는 것은 드문 일이 아닙니다. 아마도 Angular의 이전 버전을 사용하는 몇 가지 레거시 애플리케이션과 함께 최신 프레임워크로 천천히 마이그레이션되는 이전 버전의 jQuery일 수 있습니다. 따라서 고급 장치에서도 사용자 경험을 거의 사용할 수 없게 만들 수 있는 JavaScript 바이트 및 CPU 실행 시간의 누적 비용 을 탐색하는 것이 더 합리적입니다.

    일반적으로 최신 프레임워크 는 덜 강력한 장치에 우선순위를 두지 않으므로 휴대전화와 데스크톱에서의 경험은 성능 면에서 극적으로 다른 경우가 많습니다. 연구에 따르면 React 또는 Angular를 사용하는 사이트는 다른 사이트보다 CPU에서 더 많은 시간을 소비합니다(물론 React가 Vue.js보다 CPU에서 더 비싸다고 말하는 것은 아닙니다).

    Tim에 따르면 한 가지 분명한 사실은 "사이트를 구축하기 위해 프레임워크를 사용하는 경우 최상의 시나리오에서도 초기 성능 측면에서 절충안을 만들고 있는 것입니다."

프레임워크 비용, JavaScript CPU 시간: SPA 사이트 성능이 좋지 않음
프레임워크의 비용, JavaScript의 단점: SPA 사이트(여전히) 성능이 저조합니다.
모바일 장치에 대한 스크립팅 관련 CPU 시간 및 desktopv 장치에 대한 JavaScript 바이트. 일반적으로 React 또는 Angular를 사용하는 사이트는 다른 사이트보다 CPU에서 더 많은 시간을 보냅니다. 그러나 사이트를 구축하는 방법에 따라 다릅니다. 팀 Kadlec의 연구. (큰 미리보기)
  1. 프레임워크 및 종속성을 평가합니다.
    이제 모든 프로젝트에 프레임워크가 필요한 것은 아니며 단일 페이지 애플리케이션의 모든 페이지에서 프레임워크를 로드해야 하는 것도 아닙니다. Netflix의 경우 "클라이언트 측에서 React, 여러 라이브러리 및 해당 앱 코드를 제거하면 JavaScript의 총량이 200KB 이상 감소하여 로그아웃한 홈페이지에 대한 Netflix의 상호 작용 시간이 50% 이상 감소했습니다. ." 그런 다음 팀은 사용자가 방문 페이지에서 보낸 시간을 활용하여 사용자가 방문할 가능성이 높은 후속 페이지에 대해 React를 미리 가져왔습니다(자세한 내용은 참조).

    중요한 페이지에서 기존 프레임워크를 모두 제거하면 어떻게 될까요? Gatsby를 사용하면 정적 HTML 파일에서 Gatsby가 생성한 모든 JavaScript 파일을 제거하는 gatsby-plugin-no-javascript를 확인할 수 있습니다. Vercel에서는 특정 페이지에 대해 프로덕션에서 런타임 JavaScript 비활성화를 허용할 수도 있습니다(실험적).

    일단 프레임워크가 선택되면 우리는 최소 몇 년 동안 그 프레임워크를 유지하게 되므로, 프레임워크를 사용해야 하는 경우 선택 사항이 정보에 입각하여 잘 고려되었는지 확인해야 합니다. 신경써.

    데이터에 따르면 기본적으로 프레임워크는 상당히 비쌉니다. React 페이지의 58.6%는 1MB 이상의 JavaScript를 제공하고 Vue.js 페이지 로드의 36%는 1.5초 미만의 First Contentful Paint를 사용합니다. Ankur Sethi의 연구에 따르면 "당신의 React 애플리케이션 은 아무리 최적화하더라도 인도의 평균 전화에서 약 1.1초보다 빠르게 로드 되지 않습니다. Angular 앱은 부팅하는 데 항상 최소 2.7초가 걸립니다. Vue 앱 사용자는 사용을 시작하기 전에 최소 1초를 기다려야 합니다." 어쨌든 인도를 주요 시장으로 타겟팅하지 않을 수 있지만 최적이 아닌 네트워크 조건으로 사이트에 액세스하는 사용자는 비슷한 경험을 할 것입니다.

    물론 SPA를 빠르게 만드는 것은 가능하지만 즉시 사용 가능한 것은 아니므로 빠르게 만들고 유지 하는 데 필요한 시간과 노력을 고려해야 합니다. 초기에 가벼운 기본 성능 비용을 선택하면 더 쉬울 것입니다.

    그렇다면 프레임워크를 선택하는 방법은 무엇입니까? 옵션을 선택하기 전에 크기 대한 총 비용 + 초기 실행 시간을 고려하는 것이 좋습니다. Preact, Inferno, Vue, Svelte, Alpine 또는 Polymer와 같은 경량 옵션은 작업을 잘 수행할 수 있습니다. 기준선의 크기는 애플리케이션 코드의 제약 조건을 정의합니다.

    Seb Markbage가 언급한 것처럼 프레임워크의 시작 비용을 측정하는 좋은 방법은 먼저 뷰를 렌더링한 다음 뷰를 삭제한 다음 프레임워크가 확장되는 방식을 알려줄 수 있으므로 다시 렌더링 하는 것입니다. 첫 번째 렌더는 지연 컴파일된 코드를 워밍업하는 경향이 있으며, 이는 더 큰 트리가 확장될 때 이점을 얻을 수 있습니다. 두 번째 렌더링은 기본적으로 페이지의 코드 재사용이 페이지의 복잡성이 증가함에 따라 성능 특성에 영향을 미치는 방식에 대한 에뮬레이션입니다.

    기능, 접근성, 안정성, 성능, 패키지 생태계 , 커뮤니티, 학습 곡선, 문서, 도구, 추적 기록을 탐색하여 Sacha Greif의 12점 척도 점수 시스템에서 후보자(또는 일반적으로 모든 JavaScript 라이브러리)를 평가할 수 있습니다. , 팀, 호환성, 보안 등.

    Perf Track은 대규모로 프레임워크 성능을 추적합니다.
    Perf Track은 대규모로 프레임워크 성능을 추적합니다. (큰 미리보기)

    또한 더 오랜 기간 동안 웹에서 수집된 데이터에 의존할 수 있습니다. 예를 들어, Perf Track은 프레임워크 성능을 대규모로 추적하여 Angular, React, Vue, Polymer, Preact, Ember, Svelte 및 AMP로 구축된 웹사이트에 대한 오리진 집계 Core Web Vitals 점수 를 보여줍니다. Gatsby, Next.js 또는 Create React App으로 구축된 웹사이트와 Nuxt.js(Vue) 또는 Sapper(Svelte)로 구축된 웹사이트를 지정하고 비교할 수도 있습니다.

    좋은 출발점은 애플리케이션에 적합한 기본 스택 을 선택하는 것입니다. Gatsby(React), Next.js(React), Vuepress(Vue), Preact CLI 및 PWA 스타터 키트는 평균적인 모바일 하드웨어에서 즉시 로드할 수 있는 합리적인 기본값을 제공합니다. 또한, React 및 Angular에 대한 web.dev 프레임워크별 성능 지침을 살펴보세요( 감사합니다, Phillip! ).

    그리고 아마도 단일 페이지 애플리케이션을 모두 구축하는 데 약간 더 신선한 접근 방식을 취할 수 있습니다. Turbolinks는 JSON 대신 HTML을 사용하여 뷰를 렌더링하는 15KB JavaScript 라이브러리입니다. 따라서 링크를 따라갈 때 Turbolinks는 전체 페이지 로드 비용을 발생시키지 않고 자동으로 페이지를 가져오고 <body> 를 바꾸고 <head> 를 병합합니다. 스택(Hotwire)에 대한 빠른 설명과 전체 문서를 확인할 수 있습니다.

가장 많이 팔린 휴대폰의 컴퓨팅 성능을 보여주는 히스토그램과 같은 그래프
가장 많이 팔린 휴대폰의 CPU 및 컴퓨팅 성능(이미지 제공: Addy Osmani)(큰 미리보기)
  1. 클라이언트 측 렌더링 또는 서버 측 렌더링? 둘 다!
    꽤 열띤 대화입니다. 궁극적인 접근 방식은 일종의 프로그레시브 부팅을 설정하는 것입니다. 서버 측 렌더링을 사용하여 빠른 First Contentful Paint를 얻되, First Contentful Paint에 가깝게 대화식 시간을 유지하는 데 필요한 최소한의 JavaScript도 포함합니다. JavaScript가 FCP 이후에 너무 늦게 오는 경우 브라우저는 늦게 발견된 JavaScript를 구문 분석, 컴파일 및 실행하는 동안 기본 스레드를 잠그므로 사이트 또는 응용 프로그램의 상호 작용을 방해합니다.

    이를 방지하려면 항상 함수 실행 을 별도의 비동기 작업으로 나누고 가능한 경우 requestIdleCallback 을 사용하십시오. WebPack의 동적 import() 지원을 사용하여 UI의 지연 로드 부분을 고려하여 사용자가 실제로 필요할 때까지 로드, 구문 분석 및 컴파일 비용을 피하십시오( Addy에게 감사드립니다! ).

    위에서 언급했듯이 TTI(Time to Interactive)는 탐색과 상호 작용 사이의 시간을 알려줍니다. 구체적으로, 메트릭은 초기 콘텐츠가 렌더링된 후 첫 5초 창을 보고 정의되며, JavaScript 작업은 50ms ( 긴 작업 )보다 오래 걸리지 않습니다. 50ms를 초과하는 작업이 발생하면 5초 창 검색이 다시 시작됩니다. 결과적으로 브라우저는 먼저 Interactive 에 도달했다고 가정하고 Frozen 으로 전환하고 결국에는 Interactive 로 다시 전환합니다.

    Interactive 에 도달하면 필요에 따라 또는 시간이 허락하는 한 앱의 중요하지 않은 부분을 부팅할 수 있습니다. 불행히도 Paul Lewis가 지적했듯이 프레임워크에는 일반적으로 개발자에게 표시될 수 있는 우선 순위에 대한 간단한 개념이 없으므로 점진적 부팅은 대부분의 라이브러리 및 프레임워크에서 구현하기가 쉽지 않습니다.

    그래도 우리는 거기에 도달하고 있습니다. 요즘에는 우리가 탐색할 수 있는 몇 가지 선택 사항이 있으며 Houssein Djirdeh와 Jason Miller는 Rendering on the Web과 Jason과 Addy의 Modern Front-End Architectures에 대한 글에서 이러한 옵션에 대한 훌륭한 개요를 제공합니다. 아래의 개요는 그들의 뛰어난 작업을 기반으로 합니다.

    • 전체 서버 측 렌더링 (SSR)
      WordPress와 같은 클래식 SSR에서는 모든 요청이 전적으로 서버에서 처리됩니다. 요청된 콘텐츠는 완성된 HTML 페이지로 반환되며 브라우저는 즉시 이를 렌더링할 수 있습니다. 따라서 예를 들어 SSR 앱은 실제로 DOM API를 사용할 수 없습니다. First Contentful Paint와 Time to Interactive 사이의 간격은 일반적으로 작으며 HTML이 브라우저로 스트리밍되는 즉시 페이지를 렌더링할 수 있습니다.

      이것은 브라우저가 응답을 받기 전에 처리되기 때문에 클라이언트에서 데이터 가져오기 및 템플릿을 위한 추가 왕복을 방지합니다. 그러나 우리는 더 긴 서버 생각 시간 과 결과적으로 Time To First Byte로 끝나고 최신 응용 프로그램의 반응형 및 풍부한 기능을 사용하지 않습니다.

    • 정적 렌더링
      제품을 단일 페이지 애플리케이션으로 구축하지만 모든 페이지는 구축 단계로 최소한의 JavaScript를 사용하여 정적 HTML로 미리 렌더링됩니다. 이는 정적 렌더링을 사용하여 가능한 모든 URL에 대해 개별 HTML 파일을 미리 생성한다는 것을 의미합니다. 이는 많은 응용 프로그램에서 감당할 수 없는 것입니다. 그러나 페이지의 HTML을 즉석에서 생성할 필요가 없기 때문에 일관되게 빠른 첫 번째 바이트까지의 시간을 달성할 수 있습니다. 따라서 랜딩 페이지를 빠르게 표시한 다음 후속 페이지에 대한 SPA 프레임워크를 미리 가져올 수 있습니다. Netflix는 이 접근 방식을 채택하여 로딩 및 상호 작용 시간을 50%까지 줄였습니다.

    • (Re)Hydration을 사용한 서버 측 렌더링 (범용 렌더링, SSR + CSR)
      우리는 SSR과 CSR 접근 방식의 두 가지 장점을 모두 사용하려고 노력할 수 있습니다. 혼합된 수화와 함께 서버에서 반환된 HTML 페이지에는 완전한 클라이언트 측 애플리케이션을 로드하는 스크립트도 포함됩니다. 이상적으로는 (SSR과 같은) 빠른 First Contentful Paint를 달성한 다음 (재)수화로 렌더링을 계속합니다. 불행히도 그런 경우는 드뭅니다. 더 자주 페이지는 준비된 것처럼 보이지만 사용자의 입력에 응답할 수 없어 분노의 클릭과 이탈이 발생합니다.

      React를 사용하면 Express와 같은 노드 서버에서 ReactDOMServer 모듈을 사용한 다음 renderToString 메서드를 호출하여 최상위 구성 요소를 정적 HTML 문자열로 렌더링할 수 있습니다.

      Vue.js에서는 vue-server-renderer를 사용하여 renderToString 을 사용하여 Vue 인스턴스를 HTML로 렌더링할 수 있습니다. Angular에서는 @nguniversal 을 사용하여 클라이언트 요청을 완전히 서버에서 렌더링된 HTML 페이지로 전환할 수 있습니다. 완전히 서버에서 렌더링된 경험은 Next.js(React) 또는 Nuxt.js(Vue)를 사용하여 즉시 달성할 수도 있습니다.

      접근 방식에는 단점이 있습니다. 결과적으로 더 빠른 서버 측 렌더링을 제공하면서 클라이언트 측 앱의 완전한 유연성을 얻을 수 있지만 First Contentful Paint와 Time To Interactive 사이의 간격이 더 길어 지고 First Input Delay가 증가하게 됩니다. 재수화는 비용이 많이 들고 일반적으로 이 전략만으로는 Time To Interactive를 크게 지연시키기 때문에 충분하지 않습니다.

    • 점진적 수화(SSR + CSR)를 사용한 스트리밍 서버 측 렌더링
      Time To Interactive와 First Contentful Paint 사이의 간격을 최소화하기 위해 한 번에 여러 요청을 렌더링하고 생성되는 대로 콘텐츠를 청크로 보냅니다 . 따라서 콘텐츠를 브라우저로 보내기 전에 전체 HTML 문자열을 기다릴 필요가 없으므로 Time To First Byte가 향상됩니다.

      React에서는 renderToString() 을 사용하여 응답을 파이프하고 HTML을 청크로 보낼 수 있습니다. Vue에서는 파이프 및 스트리밍이 가능한 renderToStream()을 사용할 수 있습니다. React Suspense를 사용하면 그 목적으로도 비동기식 렌더링을 사용할 수 있습니다.

      클라이언트 측에서는 전체 응용 프로그램을 한 번에 부팅하는 대신 구성 요소를 점진적으로 부팅합니다 . 애플리케이션의 섹션은 먼저 코드 분할을 통해 독립 실행형 스크립트로 분할된 다음 점진적으로 수화됩니다(우선 순위에 따라). 사실, 우리는 중요한 구성 요소를 먼저 수화할 수 있고 나머지는 나중에 수화할 수 있습니다. 그런 다음 클라이언트 측 및 서버 측 렌더링의 역할을 구성 요소별로 다르게 정의할 수 있습니다. 그런 다음 일부 구성 요소가 표시되거나 사용자 상호 작용에 필요하거나 브라우저가 유휴 상태일 때까지 일부 구성 요소의 수화를 연기할 수도 있습니다.

      Vue의 경우 Markus Oberlehner는 가시성 또는 특정 사용자 상호 작용 시 구성 요소 수화를 가능하게 하는 초기 단계 플러그인인 vue-lazy-hydration뿐만 아니라 사용자 상호 작용 시 수화를 사용하여 SSR 앱의 대화형 시간을 줄이는 방법에 대한 가이드를 게시했습니다. Angular 팀은 Ivy Universal과 함께 점진적인 수분 공급을 위해 노력합니다. Preact 및 Next.js를 사용하여 부분 수화를 구현할 수도 있습니다.

    • 삼형제 렌더링
      서비스 워커가 있으면 초기/비JS 탐색에 스트리밍 서버 렌더링 을 사용할 수 있으며, 그런 다음 서비스 워커가 설치된 후 탐색을 위해 HTML 렌더링을 수행하도록 할 수 있습니다. 이 경우 서비스 작업자는 콘텐츠를 미리 렌더링하고 동일한 세션에서 새 보기를 렌더링하기 위해 SPA 스타일 탐색을 활성화합니다. 서버, 클라이언트 페이지 및 서비스 작업자 간에 동일한 템플릿 및 라우팅 코드를 공유할 수 있을 때 잘 작동합니다.

    DOM 렌더링, 서비스 작업자 사전 렌더링 및 서버 측 렌더링과 같은 3가지 위치에서 삼중형 렌더링이 작동하는 방식을 보여주는 그림
    서버, DOM 또는 서비스 작업자의 세 위치에서 동일한 코드 렌더링을 사용하는 삼중형 렌더링. (이미지 출처: Google Developers) (큰 미리보기)
    • 사전 렌더링이 포함된 CSR
      사전 렌더링은 서버 측 렌더링과 유사하지만 서버에서 페이지를 동적으로 렌더링하는 대신 빌드 시 애플리케이션을 정적 HTML로 렌더링합니다. 정적 페이지는 클라이언트 측 JavaScript가 많이 없어도 완전히 대화식이지만 사전 렌더링은 다르게 작동합니다 . 기본적으로 클라이언트 측 애플리케이션의 초기 상태를 빌드 시 정적 HTML로 캡처하는 반면 사전 렌더링에서는 페이지가 대화형이 되도록 클라이언트에서 애플리케이션을 부팅해야 합니다.

      Next.js를 사용하면 앱을 정적 HTML로 미리 렌더링하여 정적 HTML 내보내기를 사용할 수 있습니다. React를 사용하는 오픈 소스 정적 사이트 생성기인 Gatsby에서는 기본 JS 청크가 미리 로드되고 향후 경로가 미리 가져오는 빌드 중에 renderToStaticMarkup 메서드 대신 renderToString 메서드를 사용합니다. 간단한 정적 페이지에는 필요하지 않은 DOM 속성이 없습니다.

      Vue의 경우 Vuepress를 사용하여 동일한 목표를 달성할 수 있습니다. Webpack과 함께 prerender-loader를 사용할 수도 있습니다. Navi는 정적 렌더링도 제공합니다.

      결과적으로 Time To First Byte 및 First Contentful Paint가 향상되었으며 Time To Interactive와 First Contentful Paint 사이의 간격이 줄어듭니다. 내용이 많이 변경될 것으로 예상되는 경우 접근 방식을 사용할 수 없습니다. 또한 모든 페이지를 생성하려면 모든 URL을 미리 알아야 합니다. 따라서 일부 구성 요소는 사전 렌더링을 사용하여 렌더링될 수 있지만 동적인 것이 필요한 경우 콘텐츠를 가져오기 위해 앱에 의존해야 합니다.

    • 전체 클라이언트 측 렌더링 (CSR)
      모든 로직, 렌더링 및 부팅은 클라이언트에서 수행됩니다. 결과는 일반적으로 Time To Interactive와 First Contentful Paint 사이에 차이가 있습니다. 결과적으로 모든 것을 렌더링하려면 전체 앱을 클라이언트에서 부팅해야 하므로 애플리케이션 이 느려지는 경우가 많습니다 .

      JavaScript에는 성능 비용이 있으므로 응용 프로그램과 함께 JavaScript의 양이 증가함에 따라 JavaScript의 영향을 길들이기 위해서는 JavaScript의 공격적인 코드 분할 및 지연이 절대적으로 필요합니다. 이러한 경우에는 상호 작용이 많이 필요하지 않은 경우 일반적으로 서버 측 렌더링 이 더 나은 접근 방식입니다. 옵션이 아닌 경우 앱 셸 모델을 사용하는 것이 좋습니다.

      일반적으로 SSR은 CSR보다 빠릅니다. 그러나 여전히 많은 앱에서 매우 자주 구현됩니다.

    그래서, 클라이언트 측 또는 서버 측? 일반적으로 완전한 클라이언트 측 프레임워크의 사용을 절대적으로 필요한 페이지로 제한 하는 것이 좋습니다. 고급 응용 프로그램의 경우 서버 측 렌더링에만 의존하는 것도 좋은 생각이 아닙니다. 서버 렌더링과 클라이언트 렌더링 모두 제대로 수행되지 않으면 재앙이 됩니다.

    CSR이든 SSR이든 상관없이 중요한 픽셀을 가능한 한 빨리 렌더링하고 해당 렌더링과 Time To Interactive 사이의 간격을 최소화해야 합니다. 페이지가 많이 변경되지 않으면 사전 렌더링을 고려하고 가능한 경우 프레임워크 부팅을 연기합니다. 서버 측 렌더링을 사용하여 HTML을 청크로 스트리밍 하고 클라이언트 측 렌더링을 위해 점진적인 수화 를 구현하고 가시성, 상호 작용 또는 유휴 시간에 수화하여 두 가지 장점을 모두 얻을 수 있습니다.

클라이언트 측과 서버 측 렌더링 옵션을 비교하는 표
클라이언트 측과 서버 측 렌더링에 대한 옵션의 스펙트럼. 또한 Google I/O에서 애플리케이션 아키텍처의 성능 영향에 대한 Jason과 Houssein의 대화를 확인하십시오. (이미지 출처: Jason Miller) (큰 미리보기)
AirBnB 웹사이트의 왼쪽은 점진적인 수분 공급이 없고 오른쪽은 점진적 수분 공급이 있는 예
AirBnB는 점진적인 수분 공급을 실험하고 있습니다. 불필요한 구성 요소를 연기하고 사용자 상호 작용(스크롤) 또는 유휴 시간 동안 로드를 수행하고 테스트를 통해 TTI를 개선할 수 있음을 보여줍니다. (큰 미리보기)
  1. 우리는 얼마나 정적으로 봉사할 수 있습니까?
    큰 응용 프로그램에서 작업하든 작은 사이트에서 작업하든 간에, 즉석에서 동적으로 생성되는 것보다 CDN(예: JAM 스택)에서 정적으로 제공 할 수 있는 콘텐츠를 고려하는 것이 좋습니다. 개인화 옵션이 많은 수천 개의 제품과 수백 개의 필터가 있더라도 여전히 중요한 방문 페이지를 정적으로 제공하고 선택한 프레임워크에서 이러한 페이지를 분리하고 싶을 수 있습니다.

    많은 정적 사이트 생성기가 있으며 생성되는 페이지는 종종 매우 빠릅니다. 요청 시 서버나 클라이언트에서 페이지 보기를 생성하는 대신 미리 미리 구축할 수 있는 콘텐츠가 많을수록 더 나은 성능을 달성할 수 있습니다.

    부분적으로 수화되고 점진적으로 향상되는 정적 웹 사이트 구축에서 Markus Oberlehner는 정적 사이트 생성기와 SPA를 사용하여 웹 사이트를 구축하는 동시에 점진적 향상과 최소 JavaScript 번들 크기를 달성하는 방법을 보여줍니다. Markus는 Eleventy와 Preact 를 자신의 도구로 사용하고 도구 설정, 부분 수화, 지연 수화, 클라이언트 항목 파일 추가, Preact용 Babel 구성 및 Preact와 롤업 번들을 처음부터 끝까지 보여줍니다.

    요즘 대규모 사이트에서 JAMStack을 사용하면서 새로운 성능 고려 사항인 빌드 시간 이 나타났습니다. 사실, 새로 배포할 때마다 수천 페이지라도 빌드하는 데 몇 분이 걸릴 수 있으므로 WordPress, Contentful, Drupal, Netlify CMS와 같은 인기 있는 CMS 솔루션에 통합하여 빌드 시간을 60배 까지 개선하는 Gatsby의 증분 빌드를 볼 수 있을 것으로 기대됩니다. 다른 사람.

    증분 상태 재생성 프로세스를 보여주는 왼쪽 상단의 사용자 1과 왼쪽 하단의 사용자 2를 보여주는 순서도
    Next.js를 사용한 증분 정적 재생성. (이미지 크레디트: Prisma.io) (큰 미리보기)

    또한 Next.js는 사전 및 증분 정적 생성을 발표했습니다. 이를 통해 런타임 시 새로운 정적 페이지를 추가하고 트래픽이 들어올 때 백그라운드에서 다시 렌더링하여 이미 구축된 기존 페이지를 업데이트할 수 있습니다. .

    더 가벼운 접근 방식이 필요하십니까? Eleventy, Alpine 및 Tailwind: 가벼운 Jamstack을 향한 그의 강연에서 Nicola Goutay는 CSR, SSR 및 모든 것의 차이점을 설명하고 접근 방식을 보여주는 GitHub 리포지토리와 함께 더 가벼운 접근 방식을 사용하는 방법을 보여줍니다. 실제로.

  2. PRPL 패턴 및 앱 셸 아키텍처 사용을 고려하십시오.
    프레임워크에 따라 성능에 미치는 영향이 다르고 최적화 전략도 달라져야 하므로 의존하게 될 프레임워크의 모든 핵심 사항을 명확하게 이해해야 합니다. 웹 앱을 구축할 때 PRPL 패턴과 애플리케이션 셸 아키텍처를 살펴보세요. 아이디어는 매우 간단합니다. 초기 경로가 빠르게 렌더링되도록 대화식으로 전환하는 데 필요한 최소한의 코드를 푸시한 다음 리소스 캐싱 및 사전 캐싱에 서비스 작업자를 사용하고 필요한 경로를 비동기식으로 지연 로드합니다.
애플리케이션 셸 아키텍처의 PRPL 패턴
PRPL은 중요 리소스 푸시, 초기 경로 렌더링, 나머지 경로 사전 캐싱 및 요청 시 나머지 경로 지연 로드를 나타냅니다.
애플리케이션 셸 아키텍처
애플리케이션 셸은 사용자 인터페이스를 지원하는 최소한의 HTML, CSS 및 JavaScript입니다.
  1. API의 성능을 최적화했습니까?
    API는 애플리케이션이 엔드포인트 를 통해 내부 및 타사 애플리케이션에 데이터를 노출하는 통신 채널입니다. API를 설계하고 구축할 때 서버와 타사 요청 간의 통신을 가능하게 하는 합리적인 프로토콜이 필요합니다. REST (Representational State Transfer)는 잘 정립된 논리적 선택입니다. 이는 개발자가 콘텐츠에 성능이 좋고 안정적이며 확장 가능한 방식으로 액세스할 수 있도록 하기 위해 따라야 하는 일련의 제약 조건을 정의합니다. REST 제약 조건을 준수하는 웹 서비스를 RESTful 웹 서비스 라고 합니다.

    좋은 HTTP 요청과 마찬가지로 API에서 데이터를 검색할 때 서버 응답의 지연이 최종 사용자에게 전파되어 렌더링이 지연 됩니다. 리소스가 API에서 일부 데이터를 검색하려면 해당 엔드포인트에서 데이터를 요청해야 합니다. 주석이 있는 기사 및 각 주석에 작성자 사진과 같은 여러 리소스의 데이터를 렌더링하는 구성 요소는 렌더링되기 전에 모든 데이터를 가져오기 위해 서버로 여러 번 왕복해야 할 수 있습니다. 또한 REST를 통해 반환되는 데이터의 양은 해당 구성 요소를 렌더링하는 데 필요한 것보다 많은 경우가 많습니다.

    많은 리소스에 API의 데이터가 필요한 경우 API가 성능 병목 현상이 될 수 있습니다. GraphQL은 이러한 문제에 대한 고성능 솔루션을 제공합니다. 그 자체로 GraphQL은 API용 쿼리 언어이며 데이터에 대해 정의한 유형 시스템을 사용하여 쿼리를 실행하기 위한 서버 측 런타임입니다. REST와 달리 GraphQL은 단일 요청에서 모든 데이터를 검색할 수 있으며 일반적으로 REST에서 발생하는 데이터를 과도하게 또는 과소 하게 가져오지 않고 응답이 정확히 필요한 것입니다.

    또한 GraphQL은 스키마 (데이터가 구조화되는 방식을 알려주는 메타데이터)를 사용하기 때문에 이미 데이터를 원하는 구조로 구성할 수 있으므로 예를 들어 GraphQL을 사용하면 상태 관리를 처리하는 데 사용되는 JavaScript 코드를 제거할 수 있습니다. 클라이언트에서 더 빠르게 실행되는 더 깨끗한 애플리케이션 코드.

    GraphQL을 시작하거나 성능 문제가 발생하는 경우 다음 문서가 매우 유용할 수 있습니다.

    • GraphQL 입문서: 새로운 종류의 API가 필요한 이유 Eric Baer,
    • GraphQL 입문서: API 디자인의 진화 Eric Baer,
    • Leonardo Losoviz의 최적의 성능을 위한 GraphQL 서버 설계,
    • Wojciech Trocki가 설명하는 GraphQL 성능.
Redux/REST(왼쪽) 및 Apollo/GraphQL(오른쪽)을 사용하는 동안 메시지를 위한 모바일 인터페이스의 두 가지 예
왼쪽의 Redux + REST, 오른쪽의 Apollo + GraphQL 간의 대화를 통해 설명되는 REST와 GraphQL의 차이점. (이미지 출처: Hacker Noon) (큰 미리보기)
  1. AMP 또는 인스턴트 아티클을 사용하시겠습니까?
    조직의 우선 순위와 전략에 따라 Google의 AMP나 Facebook의 Instant Articles 또는 Apple의 Apple News 사용을 고려할 수 있습니다. 그것들 없이도 좋은 성능을 얻을 수 있지만 AMP 무료 CDN(콘텐츠 전달 네트워크)을 통해 견고한 성능 프레임워크를 제공하는 반면 인스턴트 아티클은 Facebook에서 가시성과 성능을 향상시킵니다.

    사용자를 위한 이러한 기술의 겉보기에 명백한 이점은 보장된 성능 이므로 때때로 사용자는 "일반" 및 잠재적으로 부풀려진 페이지보다 AMP-/Apple News/Instant Pages-링크를 선호할 수도 있습니다. 많은 타사 콘텐츠를 처리하는 콘텐츠가 많은 웹 사이트의 경우 이러한 옵션은 잠재적으로 렌더링 시간을 크게 단축하는 데 도움이 될 수 있습니다.

    그들이하지 않는 한. 예를 들어 Tim Kadlec에 따르면 "AMP 문서는 문서보다 빠른 경향이 있지만 반드시 페이지의 성능을 의미하지는 않습니다. AMP가 성능 관점에서 가장 큰 차이를 만드는 것은 아닙니다."

    웹사이트 소유자의 이점은 분명합니다. 해당 플랫폼에서 이러한 형식을 검색할 수 있고 검색 엔진에서 가시성을 높일 수 있다는 것입니다.

    글쎄, 적어도 예전에는 그랬다. AMP는 더 이상 Top Stories 의 요구 사항이 아니므로 게시자는 대신 AMP에서 기존 스택으로 이동할 수 있습니다( 감사합니다, Barry! ).

    그래도 AMP를 PWA의 데이터 소스로 재사용하여 프로그레시브 웹 AMP를 구축할 수도 있습니다. 단점? 분명히 벽으로 둘러싸인 정원에 존재하면 개발자가 콘텐츠의 별도 버전을 생성하고 유지 관리할 수 있는 위치에 놓이게 되며, Instant Articles 및 Apple News의 경우 실제 URL이 없는 경우 (Addy, Jeremy에게 감사드립니다!) .

  2. CDN을 현명하게 선택하십시오.
    위에서 언급했듯이 얼마나 많은 동적 데이터가 있는지에 따라 콘텐츠의 일부를 정적 사이트 생성기로 "아웃소싱"하여 CDN으로 푸시하고 CDN에서 정적 버전을 제공하여 섬기는 사람. 사실, 이러한 생성기 중 일부는 기본적으로 제공되는 많은 자동화된 최적화 기능을 갖춘 실제로 웹사이트 컴파일러입니다. 컴파일러가 시간이 지남에 따라 최적화를 추가함에 따라 컴파일된 출력은 시간이 지남에 따라 더 작아지고 빨라집니다.

    CDN은 동적 콘텐츠도 제공(및 오프로드)할 수 있습니다. 따라서 CDN을 정적 자산으로 제한할 필요가 없습니다. CDN이 압축 및 변환(예: 에지에서 이미지 최적화 및 크기 조정)을 수행하는지 여부, 페이지의 정적 및 동적 부분을 조합하는 에지 측 포함뿐만 아니라 서버 작업자, A/B 테스트에 대한 지원을 제공하는지 여부를 다시 확인하십시오. CDN 에지(즉, 사용자에게 가장 가까운 서버) 및 기타 작업. 또한 CDN이 QUIC(HTTP/3)를 통한 HTTP를 지원하는지 확인하십시오.

    Katie Hempenius는 좋은 CDN을 선택하는 방법 , 미세 조정하는 방법 및 평가할 때 염두에 두어야 할 모든 작은 사항에 대한 통찰력을 제공하는 환상적인 CDN 가이드를 작성했습니다. 일반적으로 콘텐츠를 최대한 적극적으로 캐시하고 Brotli, TLS 1.3, HTTP/2 및 HTTP/3과 같은 CDN 성능 기능을 활성화하는 것이 좋습니다.

    참고 : Patrick Meenan과 Andy Davies의 연구에 따르면 HTTP/2 우선 순위 지정은 많은 CDN에서 효과적으로 손상되었으므로 CDN을 선택할 때 주의하십시오. Patrick은 HTTP/2 Prioritization에 대한 자신의 강연에서 더 자세한 정보를 제공합니다( 감사합니다, Barry! ).

    ms 단위의 CDN 이름 및 쿼리 속도의 CDNPerf 미리 보기
    CDNPerf는 매일 3억 건의 테스트를 수집하고 분석하여 CDN에 대한 쿼리 속도를 측정합니다. (큰 미리보기)

    CDN을 선택할 때 기능에 대한 자세한 개요와 함께 다음 비교 사이트 를 사용할 수 있습니다.

    • Cloudfront, Aazure, KeyCDN, Fastly, Verizon, Stackpach, Akamai 및 기타 여러 업체에 대한 CDN 비교 매트릭스인 CDN 비교.
    • CDN Perf는 매일 3억 건의 테스트를 수집 및 분석하여 CDN에 대한 쿼리 속도를 측정하며 모든 결과는 전 세계 사용자의 RUM 데이터를 기반으로 합니다. 또한 DNS 성능 비교 및 ​​클라우드 성능 비교를 확인하십시오.
    • CDN Planet Guides는 Serve Stale, Purge, Origin Shield, Prefetch 및 Compression과 같은 특정 주제에 대한 CDN 개요를 제공합니다.
    • Web Almanac: CDN 채택 및 사용은 최고의 CDN 제공업체, RTT 및 TLS 관리, TLS 협상 시간, HTTP/2 채택 등에 대한 통찰력을 제공합니다. (안타깝게도 데이터는 2019년의 것입니다.)

자산 최적화

  1. 일반 텍스트 압축에는 Brotli를 사용하십시오.
    2015년에 Google은 모든 최신 브라우저에서 지원되는 새로운 오픈 소스 무손실 데이터 형식인 Brotli를 도입했습니다. Brotli용 인코더와 디코더를 구현하는 오픈 소스 Brotli 라이브러리에는 인코더에 대해 미리 정의된 11가지 품질 수준이 있으며 품질 수준이 높을수록 더 나은 압축률을 위해 더 많은 CPU가 필요합니다. 느린 압축은 궁극적으로 더 높은 압축률로 이어지지만 여전히 Brotli는 빠르게 압축을 풉니다. 압축 수준이 4인 Brotli는 Gzip보다 작고 압축 속도가 빠릅니다.

    실제로 Brotli는 Gzip보다 훨씬 더 효과적인 것으로 보입니다. 의견과 경험은 다르지만 사이트가 이미 Gzip으로 최적화되어 있는 경우 크기 축소 및 FCP 타이밍에서 최소 한 자릿수 개선과 기껏해야 두 자릿수 개선을 기대할 수 있습니다. 사이트에 대한 Brotli 압축 절감 효과를 추정할 수도 있습니다.

    브라우저는 사용자가 HTTPS를 통해 웹사이트를 방문하는 경우에만 Brotli를 허용합니다. Brotli는 광범위하게 지원되며 많은 CDN(Akamai, Netlify Edge, AWS, KeyCDN, Fastly(현재는 패스스루), Cloudflare, CDN77)에서 지원하며 아직 지원하지 않는 CDN에서도 Brotli를 활성화할 수 있습니다. (서비스 워커와 함께).

    문제는 높은 압축 수준에서 Brotli를 사용하여 모든 자산을 압축하는 데 비용이 많이 들기 때문에 많은 호스팅 제공자가 생성하는 막대한 비용 오버헤드 때문에 전체 자산을 사용할 수 없다는 것입니다. 사실, 가장 높은 압축 수준에서 Brotli는 너무 느려서 서버가 자산을 동적으로 압축할 때까지 응답을 보내기 시작하는 데 걸리는 시간으로 인해 파일 크기의 잠재적인 이득이 무효화될 수 있습니다. (그러나 정적 압축으로 빌드 시간에 시간이 있다면 물론 더 높은 압축 설정이 선호됩니다.)

    최소, 평균 및 90번째 백분위수의 세 가지 다른 백엔드 시간에 대한 다양한 압축 방법을 보여주는 수염 차트로 표시된 비교
    다양한 압축 방법의 백엔드 시간 비교. 당연히 Brotli는 gzip보다 느립니다(현재로서는). (큰 미리보기)

    그러나 이것은 바뀔 수 있습니다. Brotli 파일 형식에는 내장된 정적 사전 이 포함되어 있으며 여러 언어로 된 다양한 문자열을 포함할 뿐만 아니라 해당 단어에 여러 변환을 적용하는 옵션도 지원하여 다양성을 높입니다. 그의 연구에서 Content-Type Hanau는 "기본값보다 사전의 더 전문화된 하위 집합"을 사용하고 압축기에 HTML, JavaScript 또는 CSS용 사전. 결과는 "제한된 사전 사용 접근 방식을 사용하여 높은 압축 수준에서 웹 콘텐츠를 압축할 때 무시할 수 있는 성능 영향(일반적으로 12%에 비해 1%에서 3% 더 많은 CPU)"이었습니다.

    레벨 5에서 ​​Brotli 축소 사전을 사용한 압축 이득을 보여주는 막대 차트
    개선된 사전 접근 방식을 사용하면 더 높은 압축 수준에서 자산을 더 빠르게 압축할 수 있으며 CPU는 1~3%만 더 사용합니다. 일반적으로 압축 수준이 6 이상 5이면 CPU 사용량이 최대 12% 증가합니다. (큰 미리보기)

    게다가 Elena Kirilenko의 연구를 통해 이전 압축 아티팩트를 사용하여 빠르고 효율적인 Brotli 재압축 을 달성할 수 있습니다. Elena에 따르면 " 일단 Brotli를 통해 압축된 자산이 있고 콘텐츠가 미리 사용 가능한 콘텐츠와 유사한 동적 콘텐츠를 즉석에서 압축하려고 하면 압축 시간을 크게 개선할 수 있습니다. "

    얼마나 자주 경우입니까? 예를 들어 JavaScript 번들 하위 집합 을 전달하는 경우(예: 코드의 일부가 이미 클라이언트에 캐시되어 있거나 WebBundles와 함께 제공되는 동적 번들이 있는 경우). 또는 미리 알려진 템플릿을 기반으로 하는 동적 HTML 또는 동적으로 부분집합된 WOFF2 글꼴 을 사용합니다. Elena에 따르면 콘텐츠의 10%를 제거하면 압축률이 5.3%, 압축 속도가 39% 향상되며, 콘텐츠의 50%를 제거하면 압축률이 3.2%, 압축률이 26% 빨라집니다.

    Brotli 압축이 점점 더 좋아지고 있으므로 정적 자산을 동적으로 압축하는 비용을 우회할 수 있다면 노력할 가치가 있습니다. Brotli는 HTML, CSS, SVG, JavaScript, JSON 등 모든 일반 텍스트 페이로드에 사용할 수 있습니다.

    참고 : 2021년 초 현재 HTTP 응답의 약 60%가 텍스트 기반 압축 없이 전달되며, 30.82%는 Gzip으로, 9.1%는 Brotli로 압축합니다(모바일 및 데스크톱 모두). 예를 들어, Angular 페이지의 23.4%는 압축되지 않습니다(gzip 또는 Brotli를 통해). 그러나 종종 압축을 켜는 것은 스위치를 살짝 눌러 성능을 향상시키는 가장 쉬운 방법 중 하나입니다.

    전략? 최고 수준에서 Brotli+Gzip을 사용하여 정적 자산을 사전 압축하고 수준 4-6에서 Brotli를 사용하여 즉석에서 (동적) HTML을 압축합니다. 서버가 Brotli 또는 Gzip에 대한 콘텐츠 협상을 올바르게 처리하는지 확인하십시오.

Web Almanax 2020 보고서에 따른 HTTP 요청에 대한 압축 알고리즘을 보여주는 막대 차트
2020년에 압축되어 제공되는 리소스 중 22.59%가 Brotli로 압축됩니다. 약 77.39%가 gzip으로 압축됩니다. (이미지 출처: Web Almanac: 압축) (큰 미리보기)
  1. 적응형 미디어 로딩과 클라이언트 힌트를 사용합니까?
    그것은 오래된 뉴스의 땅에서 srcset , sizes<picture> 요소와 함께 반응형 이미지를 사용하는 것은 항상 좋은 일입니다. 특히 미디어 풋프린트가 많은 사이트의 경우 적응형 미디어 로딩(이 예에서는 React + Next.js)을 사용하여 한 단계 더 나아가 느린 네트워크 및 저메모리 장치에 가벼운 경험을 제공하고 빠른 네트워크 및 높은 - 기억 장치. React의 맥락에서 우리는 서버의 클라이언트 힌트와 클라이언트의 react-adaptive-hooks를 사용하여 이를 달성할 수 있습니다.

    반응형 이미지의 미래는 클라이언트 힌트의 광범위한 채택으로 극적으로 바뀔 수 있습니다. 클라이언트 힌트는 DPR , Viewport-Width , Width , Save-Data , Accept (이미지 형식 기본 설정 지정용) 등의 HTTP 요청 헤더 필드입니다. 그들은 사용자의 브라우저, 화면, 연결 등의 세부 사항에 대해 서버에 알려야 합니다.

    결과적으로 서버는 적절한 크기의 이미지 로 레이아웃을 채우는 방법을 결정할 수 있으며 이러한 이미지만 원하는 형식으로 제공할 수 있습니다. 클라이언트 힌트를 사용하여 리소스 선택을 HTML 마크업에서 클라이언트와 서버 간의 요청-응답 협상으로 이동합니다.

    네트워크 기능에 따라 사용자에게 다른 해상도를 전송하여 적응형 미디어 서비스를 사용하는 방법을 보여주는 그림
    적응형 미디어가 사용 중입니다. 오프라인 사용자에게는 텍스트, 2G 사용자에게는 저해상도 이미지, 3G 사용자에게는 고해상도 이미지, 4G 사용자에게는 HD 비디오가 있는 자리 표시자를 보냅니다. 20달러 피처폰에서 웹 페이지를 빠르게 로드합니다. (큰 미리보기)

    Ilya Grigorik이 얼마 전에 언급했듯이 클라이언트 힌트는 그림을 완성합니다. 반응형 이미지의 대안이 아닙니다. " <picture> 요소는 HTML 마크업에서 필요한 아트 방향 제어를 제공합니다. 클라이언트 힌트는 리소스 선택 자동화를 가능하게 하는 결과 이미지 요청에 대한 주석을 제공합니다. Service Worker는 클라이언트에서 전체 요청 및 응답 관리 기능을 제공합니다."

    서비스 작업자는 예를 들어 요청에 새 클라이언트 힌트 헤더 값을 추가 하고, URL을 다시 작성하고 이미지 요청을 CDN으로 가리키고, 연결 및 사용자 기본 설정 등에 따라 응답을 조정할 수 있습니다. 이는 이미지 자산뿐만 아니라 거의 모든 다른 요청에 대해서도 마찬가지입니다.

    클라이언트 힌트를 지원하는 클라이언트의 경우 이미지에서 42% 바이트 절약을 측정할 수 있고 70번째 백분위수 이상에 대해 1MB 이상 더 적은 바이트를 측정할 수 있습니다. Smashing Magazine에서도 19-32% 개선을 측정할 수 있습니다. 클라이언트 힌트는 Chromium 기반 브라우저에서 지원되지만 Firefox에서는 아직 고려 중입니다.

    그러나 일반 반응형 이미지 마크업과 클라이언트 힌트에 대한 <meta> 태그를 모두 제공하는 경우 지원 브라우저는 반응형 이미지 마크업을 평가하고 클라이언트 힌트 HTTP 헤더를 사용하여 적절한 이미지 소스를 요청합니다.

  2. 배경 이미지에 반응형 이미지를 사용합니까?
    우리는 반드시 해야 합니다! 이제 Safari 14와 Firefox를 제외한 대부분의 최신 브라우저에서 지원되는 image-set 을 사용하여 반응형 배경 이미지도 제공할 수 있습니다.

    background-image: url("fallback.jpg"); background-image: image-set( "photo-small.jpg" 1x, "photo-large.jpg" 2x, "photo-print.jpg" 600dpi);

    기본적으로 우리는 조건부로 1x 설명자가 있는 저해상도 배경 이미지, 2x 설명자가 있는 고해상도 이미지, 600dpi 설명자가 있는 인쇄 품질 이미지를 제공할 수 있습니다. 그러나 브라우저는 보조 기술에 배경 이미지에 대한 특별한 정보를 제공하지 않으므로 이상적으로는 이러한 사진이 단지 장식일 것입니다.

  3. WebP를 사용합니까?
    이미지 압축은 종종 빠른 승리로 간주되지만 실제로는 여전히 많이 활용되지 않습니다. 물론 이미지는 렌더링을 차단하지 않지만 낮은 LCP 점수에 크게 기여하며 매우 자주 사용되는 장치에 비해 너무 무겁고 너무 큽니다.

    따라서 최소한 이미지에 WebP 형식을 사용하여 탐색할 수 있습니다. 사실, WebP 사가는 작년에 Apple이 Safari 14에서 WebP에 대한 지원을 추가하면서 거의 끝나가고 있습니다. 따라서 수년간의 토론과 토론 끝에 오늘 현재 WebP는 모든 최신 브라우저에서 지원됩니다. 따라서 필요한 경우(Andreas Bovens의 코드 스니펫 참조) 또는 콘텐츠 협상( Accept 헤더 사용)을 사용하여 <picture> 요소와 JPEG 폴백을 사용하여 WebP 이미지를 제공할 수 있습니다.

    WebP에도 단점 이 없는 것은 아닙니다. WebP 이미지 파일 크기는 동등한 Guetzli 및 Zopfli와 비교되지만 형식은 JPEG와 같은 프로그레시브 렌더링을 지원하지 않습니다. 따라서 WebP 이미지는 네트워크를 통해 더 빨라질 수 있지만 사용자는 좋은 ol' JPEG로 완성된 이미지를 더 빨리 볼 수 있습니다. JPEG를 사용하면 WebP의 경우와 같이 절반이 비어 있는 이미지가 아니라 데이터의 절반 또는 4분의 1로 "적절한" 사용자 경험을 제공하고 나머지는 나중에 로드할 수 있습니다.

    결정은 목표에 따라 달라집니다. WebP를 사용하면 페이로드를 줄이고 JPEG를 사용하면 인지된 성능을 개선할 수 있습니다. WebP에 대한 자세한 내용은 Google Pascal Massimino의 WebP Rewind 토크에서 확인할 수 있습니다.

    WebP로 변환하려면 WebP Converter, cwebp 또는 libwebp를 사용할 수 있습니다. Ire Aderinokun은 이미지를 WebP로 변환하는 방법에 대한 매우 자세한 자습서도 제공합니다. Josh Comeau도 현대 이미지 형식 수용에 대한 그의 글에서 그렇습니다.

    Image ready: webp rewind라는 Pascal Massimino의 강연에 사용된 슬라이드
    WebP에 대한 철저한 이야기: Pascal Massimino의 WebP 되감기. (큰 미리보기)

    Sketch는 기본적으로 WebP를 지원하며 Photoshop용 WebP 플러그인을 사용하여 Photoshop에서 WebP 이미지를 내보낼 수 있습니다. 그러나 다른 옵션도 사용할 수 있습니다.

    WordPress 또는 Joomla를 사용하는 경우 WordPress용 Optimus 및 Cache Enabler 및 Joomla의 자체 지원 확장(Cody Arsenault를 통해)과 같이 WebP 지원을 쉽게 구현하는 데 도움이 되는 확장이 있습니다. React, 스타일이 지정된 구성 요소 또는 gatsby-image를 사용하여 <picture> 요소를 추상화할 수도 있습니다.

    아 - 뻔뻔한 플러그! — Jeremy Wagner는 WebP에 관한 모든 것에 관심이 있는지 확인하고 싶을 수도 있는 WebP에 대한 Smashing 책을 출판했습니다.

  4. AVIF를 사용합니까?
    큰 소식을 들었을 수도 있습니다. AVIF가 출시되었습니다. AV1 비디오의 키프레임에서 파생된 새로운 이미지 형식입니다. 손실 및 무손실 압축, 애니메이션, 손실 알파 채널을 지원하고 선명한 선과 단색(JPEG의 문제)을 처리할 수 있는 동시에 더 나은 결과를 제공하는 개방형 로열티 프리 형식입니다.

    사실, WebP 및 JPEG와 비교하여 AVIF는 훨씬 더 나은 성능 을 보여 동일한 DSSIM에서 최대 50%까지 파일 크기를 중앙값으로 절약합니다(인간의 시각을 근사하는 알고리즘을 사용하는 두 개 이상의 이미지 간의 유사성). 실제로 Malte Ubl은 이미지 로딩 최적화에 대한 철저한 게시물에서 AVIF가 "매우 중요한 방식으로 JPEG보다 일관되게 성능이 뛰어납니다. 이것은 JPEG보다 항상 더 작은 이미지를 생성하지 않으며 실제로는 실제 네트워크일 수 있는 WebP와 다릅니다. 점진적 로딩에 대한 지원 부족으로 인한 손실"

    AVIF를 점진적 향상으로 보여주는 코드 스니펫
    AVIF를 점진적 향상으로 사용하여 WebP, JPEG 또는 PNG를 구형 브라우저에 전달할 수 있습니다. (큰 미리보기). 아래의 일반 텍스트 보기를 참조하세요.

    아이러니하게도 AVIF는 대형 SVG보다 훨씬 더 나은 성능을 발휘할 수 있지만 물론 SVG를 대체하는 것으로 보여서는 안 됩니다. 또한 HDR 색상 지원을 지원하는 최초의 이미지 형식 중 하나입니다. 더 높은 밝기, 색 비트 깊이 및 색 영역을 제공합니다. 유일한 단점은 현재 AVIF가 프로그레시브 이미지 디코딩(아직?)을 지원하지 않고 Brotli와 유사하게 높은 압축률 인코딩이 디코딩은 빠르지만 현재 상당히 느리다는 것입니다.

    AVIF는 현재 Chrome, Firefox 및 Opera에서 지원되며 Safari에서도 곧 지원될 예정입니다(Apple이 AV1을 만든 그룹의 구성원이기 때문에).

    그렇다면 요즘 이미지를 제공하는 가장 좋은 방법 은 무엇입니까? 일러스트레이션 및 벡터 이미지의 경우 (압축) SVG가 의심할 여지 없이 최고의 선택입니다. 사진의 경우 picture 요소와 콘텐츠 협상 방법을 사용합니다. AVIF가 지원되는 경우 AVIF 이미지를 보냅니다. 그렇지 않은 경우 먼저 WebP로 폴백하고 WebP가 지원되지 않는 경우 폴백으로 JPEG 또는 PNG로 전환합니다(필요한 경우 @media 조건 적용).

    <picture> <source type="image/avif"> <source type="image/webp"> <img src="image.jpg" alt="Photo" width="450" height="350"> </picture>

    솔직히 말해서 picture 요소 내에서 몇 가지 조건을 사용할 가능성이 더 큽니다.

    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>

    애니메이션 이미지를 정적 이미지로 교체하여 보다 적은 움직임을 prefers-reduced-motion 고객을 위해 더 나아갈 수 있습니다.

    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>

    몇 달 동안 AVIF는 상당한 주목을 받았습니다.

    • DevTools의 렌더링 패널에서 WebP/AVIF 폴백을 테스트할 수 있습니다.
    • Squoosh, AVIF.io 및 libavif를 사용하여 AVIF 파일을 인코딩, 디코딩, 압축 및 변환할 수 있습니다.
    • 작업자의 AVIF 파일을 디코딩하고 캔버스에 결과를 표시하는 Jake Archibald의 AVIF Preact 구성 요소를 사용할 수 있습니다.
    • 지원하는 브라우저에만 AVIF를 제공하기 위해 PostCSS 플러그인을 315B 스크립트와 함께 사용하여 CSS 선언에서 AVIF를 사용할 수 있습니다.
    • CSS 및 Cloudlare 작업자를 통해 새로운 이미지 형식을 점진적으로 제공하여 반환된 HTML 문서를 동적으로 변경하고 accept 헤더에서 정보를 추론한 다음 적절하게 webp/avif 등의 클래스를 추가할 수 있습니다.
    • AVIF는 이미 Cloudinary에서 사용할 수 있으며(사용 제한 있음) Cloudflare는 이미지 크기 조정에서 AVIF를 지원하며 Netlify에서 사용자 지정 AVIF 헤더로 AVIF를 활성화할 수 있습니다.
    • 애니메이션과 관련하여 AVIF는 Safari의 <img src=mp4> 만큼 성능이 뛰어나 GIF 및 WebP보다 성능이 우수하지만 MP4는 여전히 더 나은 성능을 제공합니다.
    • 일반적으로 애니메이션의 경우 Chromium 기반 브라우저가 <img src=mp4> 를 지원할 것이라고 가정하고 AVC1(h264) > HVC1 > WebP > AVIF > GIF입니다.
    • AVIF에 대한 자세한 내용은 Netflix의 Aditya Mavlankar의 차세대 이미지 코딩을 위한 AVIF 강연과 Cloudflare의 Kornel Lesinski의 The AVIF Image Format 강연에서 확인할 수 있습니다.
    • 모든 AVIF에 대한 훌륭한 참조: AVIF에 대한 Jake Archibald의 포괄적인 게시물이 도착했습니다.

    그렇다면 미래의 AVIF는 ? Jon Sneyers는 동의하지 않습니다. AVIF는 Google과 Cloudinary에서 개발한 또 다른 무료 공개 형식인 JPEG XL보다 성능이 60% 더 낮습니다. 사실, JPEG XL은 전반적으로 훨씬 더 나은 성능을 보이는 것 같습니다. 그러나 JPEG XL은 아직 표준화의 마지막 단계에 불과하며 아직 어떤 브라우저에서도 작동하지 않습니다. (좋은 ol' Internet Explorer 9에서 나오는 Microsoft의 JPEG-XR과 혼동하지 마십시오).

반응형 이미지 중단점 생성기
반응형 이미지 중단점 생성기는 이미지 및 마크업 생성을 자동화합니다.
  1. JPEG/PNG/SVG가 제대로 최적화되어 있습니까?
    영웅 이미지가 엄청나게 빠르게 로드되는 것이 중요한 랜딩 페이지에서 작업할 때 JPEG가 프로그레시브이고 mozJPEG(스캔 수준을 조작하여 시작 렌더링 시간을 개선함) 또는 Google의 오픈 소스인 Guetzli로 압축되었는지 확인하십시오. 지각 성능에 중점을 두고 Zopfli 및 WebP의 학습을 활용하는 인코더입니다. 유일한 단점: 느린 처리 ​​시간(메가픽셀당 1분의 CPU).

    PNG의 경우 Pingo를 사용할 수 있고 SVG의 경우 SVGO 또는 SVGOMG를 사용할 수 있습니다. 웹 사이트에서 모든 SVG 자산을 빠르게 미리 보고 복사하거나 다운로드해야 하는 경우 svg-grabber도 이를 수행할 수 있습니다.

    모든 단일 이미지 최적화 기사에 명시되어 있지만 벡터 자산을 깨끗하고 긴밀하게 유지하는 것은 항상 언급할 가치가 있습니다. 사용하지 않는 자산을 정리하고 불필요한 메타데이터를 제거하고 아트웍(및 SVG 코드)의 경로 포인트 수를 줄이십시오. ( 고마워, 제레미! )

    다음과 같은 유용한 온라인 도구도 있습니다.

    • Squoosh를 사용하여 최적의 압축 수준(손실 또는 무손실)에서 이미지를 압축, 크기 조정 및 조작합니다.
    • Guetzli.it을 사용하여 Guetzli로 JPEG 이미지를 압축하고 최적화하십시오. 이는 가장자리가 선명하고 색상이 단색인 이미지에 적합합니다(그러나 약간 느릴 수 있음).
    • 반응형 이미지 중단점 생성기 또는 Cloudinary 또는 Imgix와 같은 서비스를 사용하여 이미지 최적화를 자동화합니다. 또한 많은 경우에 srcsetsizes 만 사용하면 상당한 이점을 얻을 수 있습니다.
    • 반응형 마크업의 효율성을 확인하려면 뷰포트 크기 및 장치 픽셀 비율에 대한 효율성을 측정하는 명령줄 도구인 이미징 힙을 사용할 수 있습니다.
    • GitHub 워크플로에 자동 이미지 압축을 추가할 수 있으므로 압축되지 않은 이미지가 프로덕션에 도달할 수 없습니다. 이 작업은 PNG 및 JPG와 함께 작동하는 mozjpeg 및 libvips를 사용합니다.
    • 저장 공간을 내부적으로 최적화하기 위해 Dropbox의 새로운 Lepton 형식을 사용하여 JPEG를 평균 22%까지 손실 없이 압축할 수 있습니다.
    • 자리 표시자 이미지를 일찍 표시하려면 BlurHash를 사용하세요. BlurHash는 이미지를 가져오고 이 이미지의 자리 표시자를 나타내는 짧은 문자열(20-30자만!)을 제공합니다. 문자열은 JSON 객체의 필드로 쉽게 추가할 수 있을 만큼 충분히 짧습니다.
    왼쪽에 이미지 자리 표시자가 없는 인터페이스와 오른쪽에 표시된 자리 표시자가 있는 인터페이스 비교
    BlurHash는 이미지에 대한 자리 표시자의 작고 간결한 표현입니다. (큰 미리보기)

    이미지 최적화만으로는 효과가 없는 경우가 있습니다. 중요한 이미지의 렌더링을 시작하는 데 필요한 시간을 개선하려면 덜 중요한 이미지를 지연 로드 하고 중요한 이미지가 이미 렌더링된 후에 로드할 스크립트를 연기합니다. 가장 확실한 방법은 하이브리드 지연 로딩입니다. 네이티브 지연 로딩과 지연 로드를 사용할 때 사용자 상호 작용을 통해 트리거된 가시성 변경을 감지하는 라이브러리(나중에 살펴볼 IntersectionObserver 사용)입니다. 추가로:

    • 중요한 이미지를 미리 로드하여 브라우저가 너무 늦게 발견하지 않도록 하십시오. 배경 이미지의 경우 그보다 더 공격적으로 이미지를 추가하려면 <img src> 를 사용하여 이미지를 일반 이미지로 추가한 다음 화면에서 숨길 수 있습니다.
    • 예를 들어 돋보기 구성 요소에서 소스를 교환하기 위해 sizes 를 조작하기 위해 미디어 쿼리에 따라 다른 이미지 표시 치수를 지정하여 Sizes 속성으로 이미지 교환을 고려하십시오.
    • 전경 및 배경 이미지에 대한 예기치 않은 다운로드를 방지하기 위해 이미지 다운로드 불일치를 검토합니다. 기본적으로 로드되지만 표시되지 않을 수 있는 이미지(예: 회전 목마, 아코디언 및 이미지 갤러리)에 주의하십시오.
    • 이미지의 widthheight 를 항상 설정해야 합니다. CSS의 aspect-ratio 속성과 이미지의 가로 세로 비율과 크기를 설정할 수 있는 intrinsicsize 크기 속성에 주의하십시오. 따라서 브라우저는 페이지 로드 중 레이아웃 점프를 피하기 위해 미리 정의된 레이아웃 슬롯을 조기에 예약할 수 있습니다.
    편집기에서 사용 중인 padding-top 및 aspect-ratio 요소를 보여주는 코드 스크린샷
    이제 몇 주 또는 몇 달이면 브라우저에 가로 세로 비율이 표시됩니다. Safari Technical Preview 118에서 이미. 현재 Firefox 및 Chrome의 플래그 뒤에 있습니다. (큰 미리보기)

    모험심을 느낀다면 기본적으로 CDN에 있는 실시간 필터인 Edge 작업자를 사용하여 HTTP/2 스트림을 자르고 재정렬하여 네트워크를 통해 이미지를 더 빠르게 보낼 수 있습니다. 에지 작업자는 사용자가 제어할 수 있는 청크를 사용하는 JavaScript 스트림을 사용하므로(기본적으로 스트리밍 응답을 수정할 수 있는 CDN 에지에서 실행되는 JavaScript임) 이미지 전달을 제어할 수 있습니다.

    서비스 워커를 사용하면 유선상의 항목을 제어할 수 없으므로 너무 늦었지만 Edge 워커에서는 작동합니다. 따라서 특정 방문 페이지에 대해 점진적으로 저장된 정적 JPEG 위에 이를 사용할 수 있습니다.

    다양한 뷰포트 크기 및 장치 픽셀 비율이 포함된 테이블을 보여주는 이미징 힙 명령줄 도구의 스크린샷
    뷰포트 크기 및 장치 픽셀 비율 전반에 걸쳐 효율성을 측정하는 명령줄 도구인 이미징 힙의 샘플 출력입니다. (이미지 출처) (큰 미리보기)

    충분하지? 음, 다중 배경 이미지 기술을 사용하여 이미지에 대한 인식 성능을 향상시킬 수도 있습니다. 대비를 사용하여 재생하고 불필요한 세부 사항을 흐리게 처리(또는 색상 제거)하면 파일 크기도 줄일 수 있습니다. 아, 화질을 잃지 않고 작은 사진을 확대 해야합니까? Letsenhance.io 사용을 고려하십시오.

    지금까지 이러한 최적화는 기본 사항만 다룹니다. Addy Osmani는 이미지 압축 및 색상 관리의 세부 사항에 대해 매우 자세히 설명하는 Essential Image Optimization에 대한 매우 상세한 가이드를 게시했습니다. 예를 들어, 이미지의 불필요한 부분을 흐리게 처리 하여(가우스 흐림 효과 필터를 적용하여) 파일 크기를 줄일 수 있으며, 결국에는 색상을 제거하거나 사진을 흑백으로 변환하여 크기를 더욱 줄일 수도 있습니다. . 배경 이미지의 경우 Photoshop에서 0~10% 품질로 사진을 내보내는 것도 절대적으로 허용될 수 있습니다.

    Smashing Magazine에서는 이미지 이름에 접미사 -opt 를 사용합니다(예: brotli-compression-opt.png ; 이미지에 해당 접미어가 포함될 때마다 팀의 모든 사람들은 이미지가 이미 최적화되었음을 압니다.

    아, 그리고 웹에서 JPEG-XR을 사용하지 마십시오. "CPU에서 JPEG-XR의 소프트웨어 측 디코딩 처리는 특히 SPA의 맥락에서 바이트 크기 절약의 잠재적인 긍정적 영향을 무효화하고 심지어 더 큽니다." 그러나 Cloudinary/Google의 JPEG XL과 혼합).

애니메이션 GIF를 비디오 요소로 교체하여 80% 이상 절약
Addy Osmani는 애니메이션 GIF를 반복 인라인 비디오로 교체할 것을 권장합니다. 파일 크기 차이가 눈에 띕니다(80% 절약). (큰 미리보기)
  1. 동영상이 제대로 최적화되어 있습니까?
    지금까지 이미지를 다루었지만 좋은 GIF에 대한 대화는 피했습니다. GIF에 대한 우리의 사랑에도 불구하고 이제는 영원히 (적어도 우리 웹사이트와 앱에서) GIF를 버려야 할 때입니다. 렌더링 성능과 대역폭 모두에 영향을 미치는 무거운 애니메이션 GIF를 로드하는 대신 애니메이션 WebP(GIF가 대체)로 전환하거나 반복되는 HTML5 비디오로 완전히 교체하는 것이 좋습니다.

    이미지와 달리 브라우저는 <video> 콘텐츠를 미리 로드하지 않지만 HTML5 비디오는 GIF보다 훨씬 가볍고 작은 경향이 있습니다. 옵션이 아닌가요? 글쎄, 우리는 적어도 Lossy GIF, gifsicle 또는 giflossy를 사용하여 GIF에 손실 압축을 추가할 수 있습니다.

    Colin Bendell의 테스트에 따르면 Safari Technology Preview의 img 태그 내의 인라인 비디오는 파일 크기가 매우 작을 뿐만 아니라 GIF에 상응하는 것보다 최소 20배 더 빠르게 표시하고 7배 더 빠르게 디코딩합니다. 단, 다른 브라우저에서는 지원하지 않습니다.

    좋은 소식의 나라에서 비디오 형식은 수년에 걸쳐 크게 발전 했습니다. 오랫동안 우리는 WebM이 모든 것을 지배하는 형식이 되기를 바랐고 WebP(기본적으로 WebM 비디오 컨테이너 내부에 있는 하나의 정지 이미지)가 오래된 이미지 형식을 대체할 것입니다. 실제로 Safari는 현재 WebP를 지원하고 있지만, 요즘 WebP와 WebM이 지원을 받고 있음에도 불구하고 획기적인 발전은 일어나지 않았습니다.

    그래도 우리는 대부분의 최신 브라우저에 WebM을 사용할 수 있습니다.

    <!-- By Houssein Djirdeh. https://web.dev/replace-gifs-with-videos/ --> <!-- A common scenartio: MP4 with a WEBM fallback. --> <video autoplay loop muted playsinline> <source src="my-animation.webm" type="video/webm"> <source src="my-animation.mp4" type="video/mp4"> </video>

    그러나 아마도 우리는 그것을 완전히 다시 방문할 수 있을 것입니다. 2018년, Alliance of Open Media는 AV1 이라는 새로운 유망한 비디오 형식을 출시했습니다. AV1은 H.265 코덱(H.264의 발전)과 유사한 압축을 갖지만 후자와 달리 AV1은 무료입니다. H.265 라이선스 가격 책정으로 인해 브라우저 공급업체는 성능이 비슷한 AV1을 대신 채택하게 되었습니다. AV1(H.265와 마찬가지로)은 WebM보다 두 배 더 압축 합니다.

    AV1 로고 2018
    AV1은 웹상의 비디오에 대한 궁극적인 표준이 될 가능성이 높습니다. (이미지 크레디트: Wikimedia.org) (큰 미리보기)

    실제로 Apple은 현재 HEIF 형식과 HEVC(H.265)를 사용하고 있으며 최신 iOS의 모든 사진과 동영상은 JPEG가 아닌 이러한 형식으로 저장됩니다. HEIF 및 HEVC(H.265)가 웹에 제대로 노출되지 않은 반면(아직?), AV1은 — 그리고 브라우저 지원을 얻고 있습니다. 따라서 <video> 태그에 AV1 소스를 추가하는 것이 합리적입니다. 모든 브라우저 공급업체가 참여하는 것처럼 보이기 때문입니다.

    현재 가장 널리 사용 및 지원되는 인코딩은 MP4 파일에서 제공하는 H.264이므로 파일을 제공하기 전에 MP4가 다중 패스 인코딩으로 처리되고 frei0r iirblur 효과(해당되는 경우)로 흐려지고 moov 원자 메타데이터는 파일의 헤드로 이동되는 반면 서버는 바이트 제공을 허용합니다. Boris Schapira는 FFmpeg가 비디오를 최대로 최적화하기 위한 정확한 지침을 제공합니다. 물론 대안으로 WebM 형식을 제공하는 것도 도움이 될 것입니다.

    비디오 렌더링을 더 빠르게 시작해야 하지만 비디오 파일이 여전히 너무 큽 니까? 예를 들어 방문 페이지에 큰 배경 비디오가 있을 때마다? 사용하는 일반적인 기술은 가장 첫 번째 프레임을 먼저 정지 이미지로 표시하거나 비디오의 일부로 해석될 수 있는 크게 최적화된 짧은 반복 세그먼트를 표시한 다음 비디오가 충분히 버퍼링될 때마다 재생을 시작하는 것입니다. 실제 영상. Doug Sillars는 이 경우에 도움이 될 수 있는 배경 비디오 성능에 대한 자세한 가이드를 작성했습니다. ( 고마워, Guy Podjarny! ).

    위 시나리오의 경우 반응형 포스터 이미지 를 제공할 수 있습니다. 기본적으로 video 요소는 하나의 이미지만 포스터로 허용하며 이것이 반드시 최적일 필요는 없습니다. 반응형 비디오 포스터(Responsive Video Poster)를 사용할 수 있습니다. JavaScript 라이브러리를 사용하면 다른 화면에 다른 포스터 이미지를 사용할 수 있으며 전환 오버레이와 비디오 자리 표시자의 전체 스타일 제어를 추가할 수 있습니다.

    연구에 따르면 비디오 스트림 품질은 시청자 행동에 영향을 미칩니다. 실제로 시청자는 시작 지연이 약 2초를 초과하면 비디오를 포기하기 시작합니다. 그 지점을 넘어서면 지연이 1초 증가하면 포기율이 약 5.8% 증가합니다. 따라서 중간 비디오 시작 시간이 12.8초인 것은 놀라운 일이 아닙니다. 비디오의 40%는 최소 1번의 지연이 있고 20%는 최소 2초의 지연된 비디오 재생이 있습니다. 사실 3G에서는 네트워크가 콘텐츠를 제공할 수 있는 것보다 더 빠르게 비디오가 재생되기 때문에 비디오 스톨은 피할 수 없습니다.

    그래서, 해결책은 무엇입니까? 일반적으로 작은 화면 장치는 데스크탑을 제공하는 720p 및 1080p를 처리할 수 없습니다. Doug Sillars에 따르면 비디오의 더 작은 버전을 만들고 Javascript를 사용하여 더 작은 화면의 소스를 감지하여 이러한 장치에서 빠르고 부드러운 재생 을 보장할 수 있습니다. 또는 스트리밍 비디오를 사용할 수 있습니다. HLS 비디오 스트림은 적절한 크기의 비디오를 장치에 전달하여 다양한 화면에 대해 다른 비디오를 생성할 필요성을 추상화합니다. 또한 네트워크 속도를 협상하고 사용 중인 네트워크 속도에 맞게 비디오 비트 전송률을 조정합니다.

    대역폭 낭비를 피하기 위해 실제로 비디오를 잘 재생할 수 있는 장치에 대해서만 비디오 소스를 추가할 수 있었습니다. 또는 video 태그에서 autoplay 속성을 완전히 제거하고 JavaScript를 사용하여 더 큰 화면에 대한 autoplay 을 삽입할 수 있습니다. 또한 videopreload="none" 을 추가하여 실제로 파일이 필요할 때까지 비디오 파일을 다운로드 하지 않도록 브라우저에 지시해야 합니다.

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    그런 다음 실제로 AV1을 지원하는 브라우저를 구체적으로 타겟팅할 수 있습니다.

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.av1.mp4" type="video/mp4; codecs=av01.0.05M.08"> <source src="video.hevc.mp4" type="video/mp4; codecs=hevc"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    그런 다음 특정 임계값(예: 1000px)에 autoplay 을 다시 추가할 수 있습니다.

    /* By Doug Sillars. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ */ <script> window.onload = addAutoplay(); var videoLocation = document.getElementById("hero-video"); function addAutoplay() { if(window.innerWidth > 1000){ videoLocation.setAttribute("autoplay",""); }; } </script>
    Alcatel 1X, Moto G, Moto G4, MotoE, Nexus 5 및 OnePlus 5에서 3G, 케이블, LTE 및 Native를 포함한 장치 및 네트워크 속도별로 작은 tme(ms)를 보여주는 막대 차트
    장치 및 네트워크 속도별 스톨 수. 더 빠른 네트워크의 더 빠른 장치는 사실상 중단이 없습니다. Doug Sillars의 연구에 따르면 (큰 미리보기)

    비디오 재생 성능은 그 자체로 하나의 이야기이며, 이에 대해 자세히 알아보려면 비디오 전송 메트릭에 대한 세부 정보가 포함된 현재 상태의 비디오 및 비디오 전송 모범 사례에 대한 다른 Doug Sillars 시리즈를 살펴보십시오. , 비디오 사전 로드, 압축 및 스트리밍. 마지막으로 스트리밍 여부를 사용하여 비디오 스트리밍이 얼마나 느리거나 빠른지 확인할 수 있습니다.

마인드 맵 그래프로 표시되는 Zach Leatherman의 글꼴 로딩 전략에 대한 종합 가이드
Zach Leatherman의 글꼴 로딩 전략에 대한 종합 가이드는 더 나은 웹 글꼴 전달을 위한 12가지 옵션을 제공합니다.
  1. 웹 글꼴 전달이 최적화되어 있습니까?
    물어볼 가치가 있는 첫 번째 질문은 처음부터 UI 시스템 글꼴을 사용할 수 있는지 여부입니다. 다양한 플랫폼에서 올바르게 표시되는지 다시 확인하기만 하면 됩니다. 그렇지 않은 경우, 우리가 제공하는 웹 글꼴에 사용되지 않는 글리프와 추가 기능 및 가중치가 포함될 가능성이 높습니다. 웹 글꼴을 하위 집합 으로 지정하도록 유형 주조소에 요청할 수 있습니다. 또는 오픈 소스 글꼴을 사용하는 경우 Glyphhanger 또는 Fontsquirrel을 사용하여 자체적으로 하위 집합을 만들 수 있습니다. 가장 최적의 웹 글꼴 하위 집합을 생성한 다음 페이지에 삽입하기 위해 페이지를 정적으로 분석하는 명령줄 도구인 Peter Muller의 하위 글꼴을 사용하여 전체 워크플로를 자동화할 수도 있습니다.

    WOFF2 지원은 훌륭하며 WOFF를 지원하지 않는 브라우저에 대한 폴백으로 사용할 수 있습니다. 또는 레거시 브라우저에 시스템 글꼴이 제공될 수 있습니다. 웹 글꼴 로딩을 위한 많은 옵션이 있으며 Zach Leatherman의 "글꼴 로딩 전략에 대한 종합 가이드"에서 전략 중 하나를 선택할 수 있습니다(코드 조각은 웹 글꼴 로딩 레시피로도 사용 가능).

    아마도 오늘날 고려해야 할 더 나은 옵션은 preload 이 있는 Critical FOFT와 "The Compromise" 방법일 것입니다. 둘 다 단계적으로 웹 글꼴을 제공하기 위해 2단계 렌더링 을 사용합니다. 먼저 웹 글꼴로 페이지를 빠르고 정확하게 렌더링하는 데 필요한 작은 상위 하위 집합이 필요한 다음 나머지 패밀리를 비동기식으로 로드합니다. 차이점은 "The Compromise" 기술은 글꼴 로드 이벤트가 지원되지 않는 경우에만 폴리필을 비동기적으로 로드하므로 기본적으로 폴리필을 로드할 필요가 없다는 것입니다. 빠른 승리가 필요하십니까? Zach Leatherman은 글꼴을 정리하기 위한 23분 분량의 빠른 튜토리얼과 사례 연구를 제공합니다.

    일반적으로 preload 리소스 힌트를 사용하여 글꼴을 사전 로드하는 것이 좋지만 마크업에서 중요한 CSS 및 JavaScript에 대한 링크 뒤에 힌트를 포함합니다. preload 에는 우선순위의 퍼즐이 있으므로 외부 차단 스크립트 직전에 DOM에 rel="preload" 요소를 삽입하는 것을 고려하십시오. Andy Davies에 따르면 "스크립트를 사용하여 주입된 리소스는 스크립트가 실행될 때까지 브라우저에서 숨겨지며 우리는 이 동작을 사용하여 브라우저가 preload 힌트를 발견할 때를 지연할 수 있습니다." 그렇지 않으면 첫 번째 렌더링 시 글꼴 로드 비용이 발생합니다.

    '메트릭 우선 순위 지정: 각 제품군 중 하나 미리 로드'라는 제목 옆에 두 개의 이미지 예를 보여주는 슬라이드 93의 스크린샷
    모든 것이 중요할 때 중요한 것은 없습니다. 각 패밀리에 대해 하나 또는 최대 두 개의 글꼴만 미리 로드합니다. (이미지 제공: Zach Leatherman – 슬라이드 93) (큰 미리보기)

    가장 중요한 파일을 선택하고 선택하는 것이 좋습니다. 예를 들어 렌더링에 중요하거나 눈에 띄고 방해가 되는 텍스트 리플로우를 방지하는 데 도움이 되는 파일을 선택하는 것이 좋습니다. 일반적으로 Zach 는 각 패밀리의 하나 또는 두 개의 글꼴을 미리 로드 할 것을 권장합니다. 덜 중요하다면 일부 글꼴 로드를 지연시키는 것도 의미가 있습니다.

    @font-face 규칙에서 font-family 를 정의할 때 local() 값(이름으로 로컬 글꼴 참조)을 사용하는 것이 매우 일반적입니다.

     /* Warning! Not a good idea! */ @font-face { font-family: Open Sans; src: local('Open Sans Regular'), local('OpenSans-Regular'), url('opensans.woff2') format ('woff2'), url('opensans.woff') format('woff'); }

    아이디어는 합리적입니다. Open Sans와 같은 일부 인기 있는 오픈 소스 글꼴에는 일부 드라이버 또는 앱이 사전 설치되어 있으므로 해당 글꼴을 로컬에서 사용할 수 있는 경우 브라우저는 웹 글꼴을 다운로드할 필요가 없으며 로컬을 표시할 수 있습니다. 글꼴을 즉시. Bram Stein이 언급했듯이 "로컬 글꼴이 웹 글꼴의 이름과 일치하지만 동일한 글꼴이 아닐 가능성이 높습니다. 많은 웹 글꼴이 "데스크톱" 버전과 다릅니다. 텍스트가 다르게 렌더링될 수 있고 일부 문자가 떨어질 수 있습니다. 다른 글꼴로 돌아가면 OpenType 기능이 완전히 누락되거나 줄 높이가 다를 수 있습니다."

    또한 서체가 시간이 지남에 따라 발전함에 따라 로컬에 설치된 버전은 웹 글꼴과 매우 다를 수 있으며 문자가 매우 다르게 보일 수 있습니다. 따라서 Bram에 따르면 @font-face 규칙에서는 로컬에 설치된 글꼴과 웹 글꼴을 혼합하지 않는 것이 좋습니다. Google Fonts는 Roboto에 대한 Android 요청을 제외한 모든 사용자에 대해 CSS 결과에서 local() 을 비활성화하여 그 뒤를 따랐습니다.

    콘텐츠가 표시되기를 기다리는 것을 좋아하는 사람은 없습니다. font-display CSS 설명자를 사용하여 글꼴 로드 동작을 제어하고 콘텐츠를 즉시 ( font-display: optional ) 또는 거의 즉시 (글꼴이 성공적으로 다운로드되는 한 3초의 시간 제한 포함) 읽을 수 있습니다. font-display: swap ). (글쎄요, 그것보다 조금 더 복잡합니다.)

    그러나 텍스트 리플로우의 영향을 최소화하려면 글꼴 로드 API (모든 최신 브라우저에서 지원됨)를 사용할 수 있습니다. 특히 이는 모든 글꼴에 대해 FontFace 개체를 만든 다음 모두 가져오려고 시도한 다음에만 페이지에 적용한다는 것을 의미합니다. 이런 식으로 모든 글꼴을 비동기식으로 로드하여 모든 다시 그리기를 그룹화 한 다음 폴백 글꼴에서 웹 글꼴로 정확히 한 번 전환합니다. 32:15부터 Zach의 설명과 코드 스니펫을 살펴보세요.

    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));

    Font Loading API를 사용하여 글꼴을 매우 일찍 가져오기 위해 Adrian Bece는 줄 바꿈하지 않는 공백 nbsp; body 상단에 aria-visibility: hidden.hidden 클래스를 사용하여 시각적으로 숨깁니다.

    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>

    이것은 글꼴이 성공적으로 로드되면 Font Loading API에 의해 트리거된 변경과 함께 다양한 로드 상태에 대해 선언된 다른 글꼴 패밀리가 있는 CSS와 함께 진행됩니다.

    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }

    모든 최적화에도 불구하고 Lighthouse가 여전히 렌더링 차단 리소스(글꼴)를 제거할 것을 제안하는 이유가 궁금하다면 같은 기사에서 Adrian Bece는 성능이 뛰어난 비동기 글꼴인 Gatsby Omni 글꼴 로더와 함께 Lighthouse를 행복하게 만드는 몇 가지 기술을 제공합니다. Gatsby용 플러그인 로드 및 Flash Of Unstyled Text(FOUT) 처리.

    이제 우리 중 많은 사람들이 CDN 또는 타사 호스트를 사용하여 웹 글꼴을 로드할 수 있습니다. 일반적으로 가능하면 모든 정적 자산을 자체 호스팅하는 것이 항상 더 좋으므로 Google 글꼴을 자체 호스팅하는 번거로움 없는 방법인 google-webfonts-helper를 사용하는 것이 좋습니다. 그리고 가능하지 않다면 페이지 원본을 통해 Google 글꼴 파일을 프록시할 수 있습니다.

    Google은 기본적으로 상당한 작업을 수행하고 있으므로 지연을 피하기 위해 서버를 약간 조정해야 할 수도 있습니다( 감사합니다, Barry! ).

    이것은 특히 Chrome v86(2020년 10월 출시) 이후로 파티션된 브라우저 캐시로 인해 글꼴과 같은 사이트 간 리소스를 동일한 CDN에서 더 이상 공유할 수 없기 때문에 매우 중요합니다. 이 동작은 수년 동안 Safari의 기본값이었습니다.

    그러나 전혀 가능하지 않은 경우 Harry Roberts의 스니펫을 사용하여 가능한 가장 빠른 Google 글꼴에 액세스할 수 있는 방법이 있습니다.

    <!-- By Harry Roberts. https://csswizardry.com/2020/05/the-fastest-google-fonts/ - 1. Preemptively warm up the fonts' origin. - 2. Initiate a high-priority, asynchronous fetch for the CSS file. Works in - most modern browsers. - 3. Initiate a low-priority, asynchronous fetch that gets applied to the page - only after it's arrived. Works in all browsers with JavaScript enabled. - 4. In the unlikely event that a visitor has intentionally disabled - JavaScript, fall back to the original method. The good news is that, - although this is a render-blocking request, it can still make use of the - preconnect which makes it marginally faster than the default. --> <!-- [1] --> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <!-- [2] --> <link rel="preload" as="style" href="$CSS&display=swap" /> <!-- [3] --> <link rel="stylesheet" href="$CSS&display=swap" media="print" onload="this.media='all'" /> <!-- [4] --> <noscript> <link rel="stylesheet" href="$CSS&display=swap" /> </noscript>

    해리의 전략은 먼저 글꼴의 기원을 선제적으로 워밍업하는 것입니다. 그런 다음 CSS 파일에 대해 우선 순위가 높은 비동기 가져오기를 시작합니다. 그 후에 페이지가 도착한 후에만 페이지에 적용되는 낮은 우선 순위의 비동기 가져오기를 시작합니다(인쇄 스타일시트 트릭 사용). 마지막으로 JavaScript가 지원되지 않으면 원래 방법으로 대체합니다.

    아, Google Fonts에 대해 이야기하면 &text 를 사용하여 필요한 문자만 선언하여 Google Fonts 요청 크기의 최대 90%를 줄일 수 있습니다. 또한 최근에 Google Fonts에도 글꼴 표시 지원이 추가되었으므로 즉시 사용할 수 있습니다.

    그래도 조심스러운 한마디. font-display: optional 을 사용하는 경우 웹 글꼴 요청을 일찍 트리거하므로 preload 도 사용하는 것이 차선책일 수 있습니다(가져와야 하는 다른 중요한 경로 리소스가 있는 경우 네트워크 정체 가 발생함). 더 빠른 교차 출처 글꼴 요청을 위해 preconnect 을 사용하지만 다른 출처에서 글꼴을 사전 로드하면 네트워크 경합이 발생할 수 있으므로 사전 preload 에 주의하십시오. 이러한 모든 기술은 Zach의 웹 글꼴 로딩 레시피에서 다룹니다.

    반면에 사용자가 접근성 기본 설정에서 동작 줄이기를 활성화했거나 데이터 절약 모드 를 선택한 경우 웹 글꼴(또는 최소한 두 번째 단계 렌더링)을 선택 해제하는 것이 좋습니다( Save-Data 헤더 참조). , 또는 사용자의 연결 속도가 느린 경우(네트워크 정보 API를 통해).

    사용자가 데이터 저장 모드를 선택한 경우(다른 사용 사례도 있음) 글꼴 선언을 정의 하지 않기 위해 prefers-reduced-data CSS 미디어 쿼리를 사용할 수도 있습니다. 미디어 쿼리는 기본적으로 클라이언트 힌트 HTTP 확장의 Save-Data 요청 헤더가 CSS와 함께 사용할 수 있도록 설정/해제되어 있는지 노출합니다. 현재 플래그 뒤의 Chrome 및 Edge에서만 지원됩니다.

    측정항목? 웹 글꼴 로드 성능을 측정하려면 모든 텍스트 표시 메트릭(모든 글꼴이 로드되고 모든 콘텐츠가 웹 글꼴로 표시되는 순간), 실제 기울임꼴까지의 시간 및 첫 번째 렌더링 후 웹 글꼴 리플로우 수 를 고려하십시오. 분명히 두 메트릭이 모두 낮을수록 성능이 더 좋습니다.

    가변 글꼴 은 어떻습니까? 가변 글꼴에는 상당한 성능 고려 사항이 필요할 수 있습니다. 그것들은 우리에게 인쇄상의 선택을 위한 훨씬 더 넓은 디자인 공간을 제공하지만, 많은 개별 파일 요청에 반대되는 단일 직렬 요청의 비용이 듭니다.

    가변 글꼴은 글꼴 파일의 전체 결합 파일 크기를 크게 줄이지 만 단일 요청이 느려 페이지의 모든 콘텐츠 렌더링을 차단할 수 있습니다. 따라서 글꼴을 문자 집합으로 하위 설정하고 분할하는 것은 여전히 ​​중요합니다. 그러나 좋은 측면에서는 가변 글꼴을 사용하면 기본적으로 정확히 하나의 리플로우가 발생하므로 다시 그리기를 그룹화하는 데 JavaScript가 필요하지 않습니다.

    그렇다면 방탄 웹폰트 로딩 전략 은 무엇일까요? 글꼴을 하위 집합으로 만들고 2단계 렌더링을 위해 준비하고 font-display 설명자로 선언하고 글꼴 로드 API를 사용하여 다시 그리기를 그룹화하고 글꼴을 영구 서비스 작업자의 캐시에 저장합니다. 첫 번째 방문 시 차단 외부 스크립트 직전에 스크립트 사전 로드를 삽입합니다. 필요한 경우 Bram Stein의 Font Face Observer로 대체할 수 있습니다. 글꼴 로드 성능을 측정하는 데 관심이 있는 경우 Andreas Marschke는 Font API 및 UserTiming API를 사용한 성능 추적을 살펴봅니다.

    마지막으로 unicode-range 를 포함하여 큰 글꼴을 더 작은 언어별 글꼴로 나누고 Monica Dinculescu의 글꼴 스타일 일치자를 사용하여 폴백과 글꼴 간의 크기 불일치로 인한 레이아웃 변화를 최소화합니다. 웹 글꼴.

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

    미래가 밝습니까? 점진적 글꼴 강화를 통해 궁극적으로 "특정 페이지에서 글꼴의 필수 부분만 다운로드하고 해당 글꼴에 대한 후속 요청에 대해 후속 페이지에서 요구되는 추가 글리프 세트로 원본 다운로드를 동적으로 '패치'할 수 있습니다. 보기"로 Jason Pamental이 설명합니다. 증분 전송 데모는 이미 사용 가능하며 작업이 진행 중입니다.

빌드 최적화

  1. 우선 순위를 정의했습니까?
    무엇을 다루고 있는지 먼저 파악하는 것이 좋습니다. 모든 자산(JavaScript, 이미지, 글꼴, 타사 스크립트 및 캐러셀, 복잡한 인포그래픽 및 멀티미디어 콘텐츠와 같은 페이지의 "고가" 모듈)의 인벤토리 를 실행하고 그룹으로 분류합니다.

    스프레드시트를 설정합니다 . 레거시 브라우저에 대한 기본 핵심 경험(즉, 완전히 액세스 가능한 핵심 콘텐츠), 유능한 브라우저에 대한 향상된 경험(즉, 풍부하고 완전한 경험) 및 추가 기능 (절대적으로 필요하지 않으며 다음과 같이 지연 로드될 수 있는 자산)을 정의합니다. 웹 글꼴, 불필요한 스타일, 캐러셀 스크립트, 비디오 플레이어, 소셜 미디어 위젯, 큰 이미지). 몇 년 전에 우리는 이 접근 방식을 자세히 설명하는 "Smashing Magazine의 성능 향상"에 대한 기사를 게시했습니다.

    성능을 최적화할 때 우선 순위를 반영해야 합니다. 핵심 경험을 즉시 로드한 다음 개선 사항 을 로드한 다음 추가 기능을 로드하십시오.

  2. 프로덕션에서 기본 JavaScript 모듈을 사용합니까?
    핵심 경험을 레거시 브라우저로 보내고 향상된 경험을 최신 브라우저로 보내는 최신 기술을 기억하십니까? 이 기술의 업데이트된 변형은 모듈/노모듈 패턴이라고도 하는 ES2017+ <script type="module"> 을 사용할 수 있습니다(Jeremy Wagner가 차등 서비스 로 도입하기도 함).

    아이디어는 두 개의 개별 JavaScript 번들 을 컴파일하고 제공하는 것입니다. "일반" 빌드, Babel-transforms 및 polyfills가 있고 실제로 필요로 하는 레거시 브라우저에만 제공하고 변환 또는 변환이 없는 다른 번들(동일한 기능) 폴리필.

    결과적으로 브라우저가 처리해야 하는 스크립트의 양을 줄여 메인 스레드의 차단을 줄이는 데 도움이 됩니다. Jeremy Wagner는 Babel 설정부터 Webpack에서 수정해야 할 사항, 이 모든 작업의 ​​이점에 이르기까지 차등 서비스와 빌드 파이프라인에서 설정하는 방법에 대한 포괄적인 기사를 게시했습니다.

    기본 JavaScript 모듈 스크립트는 기본적으로 지연되므로 HTML 구문 분석이 수행되는 동안 브라우저는 기본 모듈을 다운로드합니다.

    기본 JavaScript 모듈이 기본적으로 지연되는 방식을 보여주는 예
    기본 JavaScript 모듈은 기본적으로 지연됩니다. 기본 JavaScript 모듈에 대한 거의 모든 것. (큰 미리보기)

    하지만 한 가지 경고 사항: 모듈/노모듈 패턴 은 일부 클라이언트에서 역효과를 일으킬 수 있으므로 해결 방법을 고려할 수 있습니다. 그러나 Jeremy의 덜 위험한 차등 서빙 패턴은 사전 로드 스캐너를 우회하여 성능에 영향을 줄 수 있습니다. 예상하다. ( 고마워요, 제레미! )

    실제로 Rollup은 모듈을 출력 형식으로 지원하므로 프로덕션 환경에서 코드를 번들링하고 모듈을 배포할 수 있습니다. Parcel은 Parcel 2에서 모듈을 지원합니다. Webpack의 경우 module-nomodule-plugin은 모듈/nomodule 스크립트 생성을 자동화합니다.

    참고 : 기능 감지만으로는 해당 브라우저에 제공할 페이로드에 대한 정보에 입각한 결정을 내리기에 충분하지 않습니다. 그 자체로는 브라우저 버전에서 장치 기능을 추론할 수 없습니다. 예를 들어 개발 도상국의 저렴한 Android 휴대전화는 대부분 Chrome을 실행하며 제한된 메모리와 CPU 기능에도 불구하고 겨자를 줄입니다.

    결국 Device Memory Client Hints Header를 사용하여 저가형 장치를 보다 안정적으로 타겟팅할 수 있습니다. 작성하는 시점에서 헤더는 Blink에서만 지원됩니다(일반적으로 클라이언트 힌트에 적용됨). Device Memory에는 Chrome에서 사용할 수 있는 JavaScript API도 있으므로 한 가지 옵션은 API를 기반으로 기능을 감지하고 지원되지 않는 경우 모듈/노모듈 패턴 으로 폴백하는 것입니다( 감사합니다, Yoav! ).

  3. 트리 흔들기, 범위 호이스팅 및 코드 분할을 사용하고 있습니까?
    트리 쉐이킹은 실제로 프로덕션에서 사용되는 코드만 포함하여 빌드 프로세스를 정리하고 Webpack에서 사용하지 않는 가져오기를 제거하는 방법입니다. Webpack 및 Rollup을 사용하면 두 도구 모두 import 체인을 평면화하고 코드를 손상시키지 않고 하나의 인라인 함수로 변환할 수 있는 위치를 감지할 수 있는 범위 호이스팅도 있습니다. Webpack을 사용하면 JSON Tree Shaking도 사용할 수 있습니다.

    코드 분할은 요청 시 로드되는 "청크"로 코드베이스를 분할하는 또 다른 Webpack 기능입니다. 모든 JavaScript를 즉시 다운로드, 구문 분석 및 컴파일해야 하는 것은 아닙니다. 코드에서 분할 지점을 정의하면 Webpack이 종속성과 출력된 파일을 처리할 수 있습니다. 이를 통해 초기 다운로드를 작게 유지하고 애플리케이션에서 요청할 때 요청 시 코드를 요청할 수 있습니다. Alexander Kondrov는 Webpack 및 React를 사용한 코드 분할에 대한 환상적인 소개를 제공합니다.

    코드 분할 경로를 취한 다음 <link rel="preload"> 또는 <link rel="prefetch"> 를 사용하여 경로를 미리 로드하도록 브라우저에 프롬프트하는 preload-webpack-plugin 사용을 고려하십시오. Webpack 인라인 지시문은 또한 preload / prefetch 에 대한 제어를 제공합니다. (하지만 우선순위 문제에 주의하십시오.)

    분할점을 정의할 위치는 어디입니까? 사용되는 CSS/JavaScript 청크와 사용되지 않는 청크를 추적합니다. Umar Hansa는 Devtools의 Code Coverage를 사용하여 이를 달성하는 방법을 설명합니다.

    단일 페이지 애플리케이션을 다룰 때 페이지를 렌더링하기 전에 앱을 초기화하는 데 약간의 시간이 필요합니다. 설정에는 사용자 정의 솔루션이 필요하지만 초기 렌더링 시간을 단축하기 위한 모듈과 기술에 주의할 수 있습니다. 예를 들어 React 성능을 디버그하고 일반적인 React 성능 문제를 제거하는 방법과 Angular에서 성능을 개선하는 방법은 다음과 같습니다. 일반적으로 대부분의 성능 문제는 앱을 부트스트랩하는 초기 시간부터 발생합니다.

    그렇다면 공격적으로 코드를 분할하지만 너무 공격적이지는 않은 가장 좋은 방법은 무엇입니까? Phil Walton에 따르면 "동적 가져오기를 통한 코드 분할 외에도 [우리는] 패키지 수준에서 코드 분할을 사용할 수도 있습니다. 여기서 가져온 각 노드 모듈은 패키지 이름을 기반으로 한 청크에 배치됩니다." Phil은 빌드 방법에 대한 자습서도 제공합니다.

  4. Webpack의 출력을 향상시킬 수 있습니까?
    Webpack은 종종 불가사의한 것으로 간주되기 때문에 Webpack의 출력을 더욱 줄이는 데 유용할 수 있는 Webpack 플러그인이 많이 있습니다. 다음은 좀 더 주의가 필요할 수 있는 좀 더 모호한 것들입니다.

    흥미로운 것 중 하나는 Ivan Akulov의 스레드에서 가져온 것입니다. 한 번 호출하고 그 결과를 변수에 저장한 다음 해당 변수를 사용하지 않는 함수가 있다고 상상해 보십시오. Tree-shaking은 변수를 제거하지만, 그렇지 않으면 사용될 수 있기 때문에 함수는 제거 하지 않습니다 . 그러나 함수가 어디에도 사용되지 않는 경우 제거하는 것이 좋습니다. 그렇게 하려면 Uglify와 Terser가 지원하는 /*#__PURE__*/ 를 함수 호출 앞에 붙입니다.

    PURE 함수를 사용할 수 있는 방법을 보여주는 편집기의 JS 코드 스크린샷
    결과가 사용되지 않을 때 이러한 함수를 제거하려면 함수 호출 앞에 /*#__PURE__*/ 를 추가하십시오. Ivan Akulov를 통해.(큰 미리보기)

    Ivan이 권장하는 다른 도구는 다음과 같습니다.

    • purgecss-webpack-plugin은 특히 Bootstrap 또는 Tailwind를 사용할 때 사용하지 않는 클래스를 제거합니다.
    • split-chunks-plugin을 사용하여 optimization.splitChunks: 'all' 을 활성화합니다. 이렇게 하면 웹팩이 더 나은 캐싱을 위해 항목 번들을 자동으로 코드 분할합니다.
    • optimization.runtimeChunk: true . 이렇게 하면 webpack의 런타임이 별도의 청크로 이동되며 캐싱도 향상됩니다.
    • google-fonts-webpack-plugin은 글꼴 파일을 다운로드하므로 서버에서 제공할 수 있습니다.
    • workbox-webpack-plugin을 사용하면 모든 웹팩 자산에 대한 사전 캐싱 설정으로 서비스 작업자를 생성할 수 있습니다. 또한 바로 적용할 수 있는 모듈의 종합 가이드인 Service Worker Packages를 확인하십시오. 또는 preload-webpack-plugin을 사용하여 모든 JavaScript 청크에 대한 preload / prefetch 를 생성합니다.
    • speed-measure-webpack-plugin은 웹팩 빌드 속도를 측정하여 빌드 프로세스의 어느 단계가 가장 시간이 많이 걸리는지 통찰력을 제공합니다.
    • duplicate-package-checker-webpack-plugin은 번들에 동일한 패키지의 여러 버전이 포함되어 있으면 경고합니다.
    • 범위 격리를 사용하고 컴파일 시 동적으로 CSS 클래스 이름을 줄입니다.

Response-loader라는 웹팩 로더를 사용하여 즉시 반응형 이미지를 생성하는 방법을 보여주는 터미널 스크린샷
이미지 속도를 높이는 것은 더 작은 화면에서 더 작은 사진을 제공하는 것입니다. 반응형 로더 사용. Ivan Akulov를 통해. (큰 미리보기)
  1. JavaScript를 웹 워커로 오프로드할 수 있습니까?
    Time-to-Interactive에 대한 부정적인 영향을 줄이려면 무거운 JavaScript를 웹 작업자로 오프로드하는 방법을 살펴보는 것이 좋습니다.

    코드 기반이 계속 증가함에 따라 UI 성능 병목 현상이 나타나 사용자 경험이 느려집니다. DOM 작업이 기본 스레드에서 JavaScript와 함께 실행되고 있기 때문입니다. 웹 작업자를 사용하면 이러한 값비싼 작업을 다른 스레드에서 실행 중인 백그라운드 프로세스로 이동할 수 있습니다. 웹 작업자의 일반적인 사용 사례는 데이터를 미리 가져오고 나중에 필요할 때 사용할 수 있도록 일부 데이터를 미리 로드하고 저장하는 Progressive Web Apps입니다. 그리고 Comlink를 사용하여 기본 페이지와 작업자 간의 통신을 간소화할 수 있습니다. 아직 해야 할 일이 있지만 우리는 거기에 도달하고 있습니다.

    웹 작업자에게 프레임워크 및 앱 로직을 이동하는 다양한 접근 방식을 보여주는 웹 작업자에 대한 몇 가지 흥미로운 사례 연구가 있습니다. 결론: 일반적으로 여전히 몇 가지 문제가 있지만 이미 좋은 사용 사례가 있습니다( Ivan Akulov에게 감사드립니다! ).

    Chrome 80부터 JavaScript 모듈의 성능 이점이 있는 웹 작업자를 위한 새로운 모드 인 모듈 작업자가 출시되었습니다. script type="module" 과 일치하도록 스크립트 로드 및 실행을 변경할 수 있으며 작업자 실행을 차단하지 않고 지연 로드 코드에 동적 가져오기를 사용할 수도 있습니다.

    시작하는 방법? 다음은 살펴볼 가치가 있는 몇 가지 리소스입니다.

    • Surma는 브라우저의 메인 스레드에서 JavaScript를 실행하는 방법과 웹 작업자를 언제 사용해야 하는지에 대한 훌륭한 가이드를 게시했습니다.
    • 또한 메인 스레드 아키텍처에 대한 Surma의 이야기를 확인하십시오.
    • A Quest to Guarantee Responsiveness(Shubhie Panicker 및 Jason Miller)는 웹 작업자를 사용하는 방법과 웹 작업자를 피해야 하는 경우에 대한 자세한 통찰력을 제공합니다.
    • 사용자의 길에서 벗어나기: 웹 작업자를 사용한 버벅거림 감소에서는 웹 작업자 작업에 유용한 패턴, 작업자 간의 효과적인 통신 방법, 메인 스레드에서 복잡한 데이터 처리 처리, 테스트 및 디버그를 강조합니다.
    • Workerize를 사용하면 모듈을 웹 작업자로 이동하여 내보낸 기능을 비동기식 프록시로 자동 반영할 수 있습니다.
    • Webpack을 사용하는 경우 workerize-loader를 사용할 수 있습니다. 또는 작업자 플러그인을 사용할 수도 있습니다.
    웹 작업자를 사용할 때 무엇을 사용하고 피해야 하는지의 예로서 왼쪽에 표시된 DOM의 코드
    코드가 오랫동안 차단될 때 웹 작업자를 사용하지만 DOM에 의존하고 입력 응답을 처리하고 최소한의 지연이 필요한 경우 웹 작업자를 사용하지 마십시오. (Addy Osmani를 통해) (큰 미리보기)

    DOM은 "스레드로부터 안전"하지 않으며 실행하는 코드는 별도의 파일에 포함되어야 하기 때문에 웹 작업자는 DOM에 액세스할 수 없습니다.

  2. WebAssembly에 "핫 경로"를 오프로드할 수 있습니까?
    C/C++/Rust와 같은 고급 언어 컴파일을 위한 이식 가능한 대상으로 설계된 바이너리 명령 형식인 WebAssembly( WASM )로 계산적으로 많은 작업을 오프로드할 수 있습니다. 브라우저 지원이 놀랍고 최근 JavaScript와 WASM 간의 함수 호출이 빨라짐에 따라 실행 가능하게 되었습니다. 또한 Fastly의 에지 클라우드에서도 지원됩니다.

    물론 WebAssembly가 JavaScript를 대체해서는 안 되지만 CPU 사용량이 많은 경우 이를 보완할 수 있습니다. 대부분의 웹 앱에서 JavaScript가 더 적합하고 WebAssembly는 게임과 같이 계산 집약적인 웹 앱 에 가장 잘 사용됩니다.

    WebAssembly에 대해 더 알고 싶다면:

    • Lin Clark은 WebAssembly에 대한 철저한 시리즈를 작성했으며 Milica Mihajlija는 브라우저에서 기본 코드를 실행하는 방법, 그렇게 하려는 이유, JavaScript와 웹 개발의 미래에 대한 모든 의미에 대한 일반적인 개요를 제공합니다.
    • WebAssembly를 사용하여 20X까지 웹 앱 속도를 높인 방법(사례 연구)에서는 느린 JavaScript 계산이 컴파일된 WebAssembly로 대체되어 상당한 성능 향상을 가져온 방법에 대한 사례 연구를 강조합니다.
    • Patrick Hamann은 WebAssembly의 성장하는 역할에 대해 이야기해 왔으며 WebAssembly에 대한 몇 가지 신화를 폭로하고 문제를 탐구하며 오늘날 애플리케이션에서 실제로 사용할 수 있습니다.
    • Google Codelabs는 C에서 네이티브 코드를 가져와 WebAssembly로 컴파일한 다음 JavaScript에서 직접 호출하는 방법을 배우는 60분 과정인 Introduction to WebAssembly를 제공합니다.
    • Alex Danilo는 Google I/O 강연에서 WebAssembly와 이것이 어떻게 작동하는지 설명했습니다. 또한 Benedek Gagyi는 WebAssembly에 대한 실제 사례 연구, 특히 팀이 iOS, Android 및 웹사이트에 대한 C++ 코드베이스의 출력 형식으로 WebAssembly를 사용하는 방법을 공유했습니다.

    언제 웹 작업자, 웹 어셈블리, 스트림 또는 WebGL JavaScript API를 사용하여 GPU에 액세스 해야 하는지 아직 확실하지 않습니까? JavaScript 가속은 언제 무엇을 사용해야 하는지 설명하는 짧지만 유용한 안내서입니다. 또한 편리한 순서도와 많은 유용한 리소스가 함께 제공됩니다.

JavaScript, CSS 및 HTML에 추가되는 WASM 바이너리를 포함하는 브라우저에 화살표가 표시된 왼쪽에 표시된 C++, C 또는 Rust의 그림
Milica Mihajlija는 WebAssembly의 작동 방식과 유용한 이유에 대한 일반적인 개요를 제공합니다. (큰 미리보기)
  1. 레거시 브라우저에만 레거시 코드를 제공합니까?
    ES2017이 최신 브라우저에서 매우 잘 지원되기 때문에 babelEsmPlugin 을 사용하여 대상으로 하는 최신 브라우저에서 지원하지 않는 ES2017+ 기능만 트랜스파일할 수 있습니다.

    Houssein Djirdeh와 Jason Miller는 최근 JavaScript를 Webpack 및 Rollup과 함께 작동하게 하는 방법과 필요한 도구에 대해 자세히 설명하는 최신 및 레거시 JavaScript를 변환하고 제공하는 방법에 대한 포괄적인 가이드를 게시했습니다. 또한 사이트 또는 앱 번들에서 얼마나 많은 JavaScript를 줄일 수 있는지 예측할 수 있습니다.

    JavaScript 모듈은 모든 주요 브라우저에서 지원되므로 script type="module" 을 사용하여 ES 모듈을 지원하는 브라우저가 파일을 로드하도록 하는 반면 이전 브라우저는 script nomodule 로 레거시 빌드를 로드할 수 있습니다.

    요즘에는 변환기나 번들러 없이 브라우저에서 기본적으로 실행되는 모듈 기반 JavaScript를 작성할 수 있습니다. <link rel="modulepreload"> 헤더는 모듈 스크립트의 초기(높은 우선 순위) 로드를 시작하는 방법을 제공합니다. 기본적으로 브라우저가 긴 왕복 시간 동안 할 일이 없도록 가져와야 하는 항목에 대해 알려줌으로써 대역폭 사용을 최대화하는 데 도움이 되는 멋진 방법입니다. 또한 Jake Archibald는 읽을 가치가 있는 ES 모듈에 대해 염두에 두어야 할 문제와 주의할 사항이 포함된 자세한 기사를 게시했습니다.

인라인 스크립트는 차단 외부 스크립트 및 인라인 스크립트가 실행될 때까지 연기됩니다.
Jake Archibald는 ES 모듈과 관련하여 주의해야 할 사항 및 문제가 포함된 자세한 기사를 게시했습니다. 예를 들어 인라인 스크립트는 외부 스크립트를 차단하고 인라인 스크립트가 실행될 때까지 연기됩니다. (큰 미리보기)
  1. 증분 분리로 레거시 코드를 식별하고 다시 작성 합니다.
    오래 지속되는 프로젝트는 먼지와 오래된 코드를 모으는 경향이 있습니다. 종속성을 다시 방문하여 최근에 문제를 일으킨 레거시 코드를 리팩토링하거나 다시 작성하는 데 얼마나 많은 시간이 필요한지 평가하십시오. 물론 항상 큰 작업이지만 레거시 코드의 영향을 알게 되면 점진적 분리로 시작할 수 있습니다.

    먼저, 레거시 코드 호출의 비율이 일정하게 유지되는지 또는 증가하지 않고 감소하는지 추적하는 메트릭을 설정합니다. 공개적으로 팀이 라이브러리를 사용하지 못하도록 하고 풀 요청에 사용되는 경우 CI가 개발자에게 경고하도록 하십시오. 폴리필은 레거시 코드에서 표준 브라우저 기능을 사용하는 재작성된 코드베이스로 전환하는 데 도움이 될 수 있습니다.

  2. 사용하지 않는 CSS/JS를 식별하고 제거 합니다.
    Chrome의 CSS 및 JavaScript 코드 적용을 통해 어떤 코드가 실행/적용되었는지 알 수 있습니다. 적용 범위 기록을 시작하고 페이지에서 작업을 수행한 다음 코드 적용 범위 결과를 탐색할 수 있습니다. 사용하지 않는 코드를 감지했다면 해당 모듈을 찾아 import() 로 지연 로드하십시오(전체 스레드 참조). 그런 다음 적용 범위 프로필을 반복하고 이제 초기 로드 시 더 적은 코드를 제공하는지 확인합니다.

    Puppeteer를 사용하여 프로그래밍 방식으로 코드 적용 범위를 수집할 수 있습니다. Chrome을 사용하면 코드 검사 결과도 내보낼 수 있습니다. Andy Davies가 언급했듯이 최신 브라우저와 레거시 브라우저 모두에 대한 코드 적용 범위를 수집할 수 있습니다.

    더 많은 노출이 필요할 수 있는 Puppetter의 다른 많은 사용 사례와 도구가 있습니다.

    • 예를 들어 모든 빌드에서 사용되지 않는 CSS를 자동으로 시각적으로 비교하거나 모니터링하는 것과 같은 Puppeteer의 사용 사례,
    • Puppeteer를 사용한 웹 성능 레시피,
    • Pupeeteer 및 Playwright 스크립트를 기록하고 생성하는 데 유용한 도구,
    • 또한 DevTools에서 바로 테스트를 기록할 수도 있습니다.
    • Nitay Neeman의 Puppeteer에 대한 포괄적인 개요와 예제 및 사용 사례.
    왼쪽의 Puppeteer Recorder 스크린샷과 오른쪽의 Puppeteer Sandbox 스크린샷
    Puppeteer Recorder 및 Puppeteer Sandbox를 사용하여 브라우저 상호 작용을 기록하고 Puppeteer 및 Playwright 스크립트를 생성할 수 있습니다. (큰 미리보기)

    또한 purgecss, UnCSS 및 Helium은 CSS에서 사용하지 않는 스타일을 제거하는 데 도움이 될 수 있습니다. 그리고 의심스러운 코드 조각이 어딘가에서 사용되었는지 확실하지 않다면 Harry Roberts의 조언을 따를 수 있습니다. 특정 클래스에 대해 1x1px 투명 GIF를 만들어 dead/ 디렉토리(예: /assets/img/dead/comments.gif )에 놓으십시오. /assets/img/dead/comments.gif .

    그런 다음 CSS의 해당 선택기에서 특정 이미지를 배경으로 설정하고 파일이 로그에 표시될 경우 몇 개월 동안 기다리십시오. 항목이 없으면 화면에 해당 레거시 구성 요소가 렌더링되지 않은 것입니다. 계속해서 모두 삭제할 수 있습니다.

    I-feel-adventurous -department의 경우 DevTools를 사용하여 DevTools를 모니터링하여 페이지 세트를 통해 사용하지 않는 CSS 수집을 자동화할 수도 있습니다.

웹팩 비교표
Benedikt Rotsch's는 그의 기사에서 Moment.js에서 date-fns로 전환하면 3G 및 저가형 휴대전화의 First paint에 대해 약 300ms를 단축할 수 있음을 보여주었습니다. (큰 미리보기)
  1. JavaScript 번들의 크기를 자릅니다.
    Addy Osmani가 언급했듯이, 일부만 필요할 때 전체 JavaScript 라이브러리를 제공할 가능성이 높으며, 필요하지 않거나 코드가 중복되는 브라우저를 위한 오래된 폴리필과 함께 제공됩니다. 오버헤드를 방지하려면 빌드 프로세스 중에 사용하지 않는 메서드와 폴리필을 제거하는 webpack-libs-optimizations를 사용하는 것이 좋습니다.

    레거시 브라우저와 최신 브라우저로 보내는 폴리필 을 확인하고 검토하고 이에 대해 보다 전략적인 태도를 취하세요. 브라우저 기능 세트에 대한 요청을 수락하고 요청한 브라우저에 필요한 폴리필만 반환하는 서비스인 polyfill.io를 살펴보십시오.

    일반 워크플로에도 번들 감사 를 추가합니다. 몇 년 전에 추가한 무거운 라이브러리에 대한 가벼운 대안이 있을 수 있습니다. 예를 들어 Moment.js(현재 중단됨)는 다음으로 대체될 수 있습니다.

    • 네이티브 국제화 API,
    • 친숙한 Moment.js API 및 패턴을 사용하는 Day.js,
    • date-fns 또는
    • 룩슨.
    • 사람이 검토한 패키지 권장 사항과 품질 중심 검색을 결합한 Skypack Discover를 사용할 수도 있습니다.

    Benedikt Rotsch의 연구에 따르면 Moment.js에서 date-fns로의 전환은 3G 및 저가형 휴대전화의 First paint에 대해 약 300ms를 단축할 수 있습니다.

    번들 감사의 경우 Bundlephobia는 npm 패키지를 번들에 추가하는 비용을 찾는 데 도움이 될 수 있습니다. size-limit는 JavaScript 실행 시간에 대한 세부 정보로 기본 번들 크기 검사를 확장합니다. 이러한 비용을 Lighthouse Custom Audit와 통합할 수도 있습니다. 이것은 프레임워크에도 적용됩니다. Vue MDC 어댑터(Vue용 재료 구성요소)를 제거하거나 트리밍하면 스타일이 194KB에서 10KB로 떨어집니다.

    종속성과 실행 가능한 대안의 영향에 대해 정보에 입각한 결정을 내리는 데 도움이 되는 추가 도구가 많이 있습니다.

    • 웹팩 번들 분석기
    • 소스 맵 탐색기
    • 번들 버디
    • 번들 공포증
    • Webpack 분석은 특정 모듈이 번들에 포함된 이유를 보여줍니다.
    • 번들 마법사는 또한 전체 페이지에 대한 종속성 맵을 빌드합니다.
    • Webpack 크기 플러그인
    • 비주얼 코드 가져오기 비용

    전체 프레임워크를 제공하는 대신 프레임워크를 다듬고 추가 코드가 필요하지 않은 원시 JavaScript 번들 로 컴파일할 수 있습니다. Svelte는 이를 수행하고 React.js 구성 요소를 빌드 시 기본 DOM 작업으로 변환하는 Rawact Babel 플러그인도 수행합니다. 왜요? 글쎄요, 유지보수 담당자가 설명하듯이, "react-dom에는 증분 렌더링, 스케줄링, 이벤트 처리 등을 위한 코드를 포함하여 렌더링될 수 있는 모든 가능한 구성 요소/HTMLElement에 대한 코드가 포함되어 있습니다. 그러나 이러한 모든 기능이 필요하지 않은 응용 프로그램이 있습니다(초기에는 페이지 로드). 이러한 응용 프로그램의 경우 기본 DOM 작업을 사용하여 대화형 사용자 인터페이스를 구축하는 것이 합리적일 수 있습니다."

size-limit는 JavaScript 실행 시간에 대한 세부 정보와 함께 기본 번들 크기 검사도 제공합니다.
size-limit는 JavaScript 실행 시간에 대한 세부 정보와 함께 기본 번들 크기 검사도 제공합니다. (큰 미리보기)
  1. 우리는 부분 수분을 사용합니까?
    응용 프로그램에서 사용되는 JavaScript의 양으로 인해 클라이언트에 가능한 한 적게 보낼 수 있는 방법을 찾아야 합니다. 그렇게 하는 한 가지 방법(우리는 이미 간략하게 다루었습니다)은 부분적인 수분 공급입니다. 아이디어는 매우 간단합니다. SSR을 수행한 다음 전체 앱을 클라이언트로 보내는 대신 앱의 JavaScript 중 작은 부분만 클라이언트로 보낸 다음 수화됩니다. 정적 웹사이트에 여러 렌더링 루트가 있는 여러 개의 작은 React 앱으로 생각할 수 있습니다.

    "부분 수화의 경우(Next 및 Preact 사용)" 기사에서 Lukas Bombach는 독일의 뉴스 매체 중 하나인 Welt.de의 팀이 부분 수화로 더 나은 성과를 달성한 방법을 설명합니다. 설명과 코드 스니펫을 통해 차세대 초고성능 GitHub 리포지토리를 확인할 수도 있습니다.

    다음과 같은 대체 옵션을 고려할 수도 있습니다.

    • Preact와 Eleventy로 부분적인 수분 공급,
    • React GitHub 리포지토리의 점진적 수화,
    • Vue.js(GitHub repo)의 지연 수화,
    • 사용자가 이를 필요로 하는 UI와 상호 작용할 때 중요하지 않은 리소스(예: 구성 요소, 포함)를 지연 로드하려면 상호 작용 패턴에서 가져옵니다.

    Jason Miller는 React로 점진적 수화를 구현하는 방법에 대한 작업 데모를 게시했습니다. 따라서 즉시 사용할 수 있습니다: 데모 1, 데모 2, 데모 3(GitHub에서도 사용 가능). 또한 react-prerendered-component 라이브러리를 살펴볼 수 있습니다.

    Google 문서에서 loadshare() 시 +485KB의 JavaScript
    자사 코드에 대한 상호작용 시 가져오기는 상호작용 전에 리소스를 미리 가져올 수 없는 경우에만 수행해야 합니다. (큰 미리보기)
  2. React/SPA에 대한 전략을 최적화했습니까?
    단일 페이지 애플리케이션 애플리케이션의 성능에 어려움을 겪고 계십니까? Jeremy Wagner는 클라이언트 측 프레임워크 성능이 다양한 장치에 미치는 영향을 조사하여 하나를 사용할 때 알아야 할 몇 가지 의미와 지침을 강조했습니다.

    결과적으로 다음은 Jeremy가 React 프레임워크에 사용하도록 제안한 SPA 전략입니다(그러나 다른 프레임워크에서는 크게 변경되지 않아야 함).

    • 가능하면 상태 저장 구성 요소를 상태 비저장 구성 요소로 리팩터링하십시오.
    • 서버 응답 시간을 최소화하기 위해 가능한 경우 상태 비저장 구성 요소를 미리 렌더링합니다. 서버에서만 렌더링합니다.
    • 간단한 상호 작용이 있는 상태 저장 구성 요소의 경우 해당 구성 요소를 사전 렌더링 또는 서버 렌더링하는 것을 고려하고 상호 작용을 프레임워크 독립 이벤트 리스너로 교체합니다.
    • 클라이언트에서 상태 저장 구성 요소를 수화해야 하는 경우 가시성 또는 상호 작용에 지연 수화를 사용하십시오.
    • 지연 수화 구성 요소의 경우 requestIdleCallback 을 사용하여 주 스레드 유휴 시간 동안 수화를 예약합니다.

    추구하거나 검토할 수 있는 몇 가지 다른 전략이 있습니다.

    • React 앱의 CSS-in-JS에 대한 성능 고려 사항
    • 동적 가져오기 및 지연 수화를 사용하여 필요할 때만 폴리필을 로드하여 Next.js 번들 크기를 줄입니다.
    • JavaScript의 비밀: React, 성능 최적화 및 다중 스레딩에 대한 이야기, React로 사용자 인터페이스 문제 개선에 대한 긴 7부 시리즈,
    • React 성능을 측정하는 방법과 React 애플리케이션을 프로파일링하는 방법.
    • Alex Holachek의 환상적인 강연, 슬라이드 및 GitHub 리포지토리와 함께 React로 모바일 우선 웹 애니메이션 만들기( Addy, 팁 감사합니다! )
    • webpack-libs-optimizations는 유용한 Webpack별 성능 관련 최적화가 많이 포함된 환상적인 GitHub 리포지토리입니다. Ivan Akulov가 유지 관리합니다.
    • Ivan Akulov가 React의 성능을 개선하는 방법에 대한 가이드인 Notion의 React 성능 개선과 앱을 약 30% 더 빠르게 만드는 유용한 포인터를 제공합니다.
    • React Refresh Webpack Plugin(실험적)은 구성 요소 상태를 유지하고 후크 및 기능 구성 요소를 지원하는 핫 리로딩을 허용합니다.
    • 번들 크기에 영향을 주지 않는 새로 제안된 구성 요소인 번들 크기가 없는 React Server 구성 요소에 주의하십시오. 이 프로젝트는 현재 개발 중이지만 커뮤니티의 모든 피드백에 감사드립니다(Sophie Alpert의 훌륭한 설명자).
  3. JavaScript 청크에 대해 예측 프리페치를 사용하고 있습니까?
    우리는 발견적 방법을 사용하여 JavaScript 청크를 미리 로드할 시기를 결정할 수 있습니다. 추측.js는 Google 애널리틱스 데이터를 사용하여 사용자가 지정된 페이지에서 다음에 방문할 가능성이 가장 높은 페이지를 결정하는 도구 및 라이브러리 세트입니다. Google 애널리틱스 또는 기타 소스에서 수집한 사용자 탐색 패턴을 기반으로 하는Guess.js는 머신 러닝 모델을 구축하여 각 후속 페이지에 필요한 JavaScript를 예측하고 미리 가져옵니다.

    따라서 모든 대화형 요소는 참여 확률 점수를 받고 이 점수를 기반으로 클라이언트 측 스크립트는 미리 리소스를 미리 가져오기로 결정합니다. 이 기술을 Next.js 애플리케이션, Angular 및 React에 통합할 수 있으며 설정 프로세스를 자동화하는 Webpack 플러그인도 있습니다.

    분명히, 불필요한 데이터를 소비하고 원하지 않는 페이지를 미리 가져오도록 브라우저에 메시지를 표시할 수 있으므로 미리 가져오는 요청 수를 상당히 보수적으로 유지하는 것이 좋습니다. 좋은 사용 사례는 체크아웃에 필요한 유효성 검사 스크립트를 미리 가져오거나 중요한 클릭 유도문안이 뷰포트에 들어올 때 추측적인 미리 가져오는 것입니다.

    덜 세련된 것이 필요하십니까? DNStradamus는 아웃바운드 링크가 뷰포트에 나타날 때 DNS 프리페치를 수행합니다. Quicklink, InstantClick 및 Instant.page는 다음 페이지 탐색을 더 빠르게 로드하기 위해 유휴 시간 동안 뷰포트에서 자동으로 링크를 미리 가져 오는 작은 라이브러리입니다. Quicklink를 사용하면 React Router 경로와 Javascript를 미리 가져올 수 있습니다. 또한 데이터를 고려하므로 2G 또는 Data-Saver 가 켜져 있는 경우 프리페치하지 않습니다. 모드가 뷰포트 프리페칭 (기본값)을 사용하도록 설정된 경우 Instant.page도 마찬가지입니다.

    예측 프리페치의 과학을 자세히 살펴보고 싶다면 Divya Tagtachian이 처음부터 끝까지 모든 옵션을 다루는 예측 프리페치 기술에 대한 훌륭한 강연을 들을 수 있습니다.

  4. 대상 JavaScript 엔진에 대한 최적화를 활용하십시오.
    사용자 기반에서 어떤 JavaScript 엔진이 지배적인지 연구한 다음 이를 최적화하는 방법을 탐색하십시오. 예를 들어, Blink-browsers, Node.js 런타임 및 Electron에서 사용되는 V8에 대해 최적화할 때 모놀리식 스크립트에 대한 스크립트 스트리밍을 사용합니다.

    스크립트 스트리밍을 사용하면 다운로드가 시작되면 async 또는 defer scripts 를 별도의 백그라운드 스레드에서 구문 분석할 수 있으므로 경우에 따라 페이지 로드 시간이 최대 10%까지 향상됩니다. 실제로 <head> 에서 <script defer> 를 사용하여 브라우저가 리소스를 조기에 발견한 다음 백그라운드 스레드에서 구문 분석할 수 있도록 합니다.

    주의 사항: Opera Mini는 스크립트 지연을 지원하지 않으므로 인도 또는 아프리카용으로 개발 중인 경우 defer 이 무시되어 스크립트가 평가될 때까지 렌더링이 차단됩니다(Jeremy에게 감사드립니다!) .

    또한 V8의 코드 캐싱에 연결할 수 있습니다. 이를 사용하는 코드에서 라이브러리를 분리하거나 다른 방법으로 라이브러리와 사용을 단일 스크립트로 병합하고 작은 파일을 함께 그룹화하고 인라인 스크립트를 피할 수 있습니다. 또는 v8-compile-cache를 사용할 수도 있습니다.

    일반적으로 JavaScript와 관련하여 염두에 두어야 할 몇 가지 사례가 있습니다.

    • 가독성, 재사용 및 리팩터링 가능한 코드를 작성하기 위한 대규모 패턴 모음인 JavaScript용 클린 코드 개념.
    • CompressionStream API를 사용하여 JavaScript에서 데이터를 압축할 수 있습니다(예: 데이터를 업로드하기 전에 gzip으로 압축)(Chrome 80 이상).
    • 분리된 창 메모리 누수 및 웹 앱의 메모리 누수 수정은 까다로운 JavaScript 메모리 누수를 찾고 수정하는 방법에 대한 자세한 가이드입니다. 또한 DevTools 콘솔에서 queryObjects(SomeConstructor)를 사용할 수 있습니다( 감사합니다, Mathias! ).
    • 다시 내보내기는 로드 및 런타임 성능에 좋지 않으며 이를 피하면 번들 크기를 크게 줄이는 데 도움이 됩니다.
    • options 매개변수에서 플래그를 설정하여 수동 이벤트 리스너로 스크롤 성능을 향상시킬 수 있습니다. 따라서 브라우저는 리스너가 완료된 후가 아니라 즉시 페이지를 스크롤할 수 있습니다. (Kayce Basques를 통해).
    • scroll 또는 touch* 리스너가 있는 경우 passive: true 를 addEventListener에 전달합니다. 이렇게 하면 브라우저에서 내부에서 event.preventDefault() 를 호출할 계획이 없음을 알리므로 이러한 이벤트를 처리하는 방식을 최적화할 수 있습니다. (Ivan Akulov를 통해)
    • 웹에서 사용자 입력에 대한 인터럽트 개념으로 로딩과 응답성 사이의 간격을 메우려고 시도하고 JavaScript가 양보하지 않고 입력을 확인할 수 있도록 하는 새로운 API인 isInputPending()을 사용하여 더 나은 JavaScript 일정을 달성할 수 있습니다. 브라우저.
    • 이벤트 리스너가 실행된 후 자동으로 제거할 수도 있습니다.
    • Firefox의 최근 출시된 Warp, SpiderMonkey(Firefox 83에서 제공), Baseline Interpreter 및 몇 가지 JIT 최적화 전략에 대한 중요한 업데이트입니다.
시간 로딩 및 응답성을 이해하는 데 도움이 되는 그림
브라우저에 실행을 양보하는 오버헤드를 발생시키지 않으면서 사용자 입력이 있는지 여부를 사전에 확인하는 시간을 나타내는 규칙적인 간격에 흰색 선이 있는 JS 실행을 보여주는 파란색 배너
isInputPending()은 로딩과 반응성 사이의 간극을 메우려는 새로운 브라우저 API입니다.(큰 미리보기)
제8자 스크립트에 이르기까지 서로 다른 도메인에 대한 각 요청의 체인을 보여주는 맵 그림
CNN.com에 대한 요청 맵은 제8자 스크립트에 이르기까지 서로 다른 도메인에 대한 각 요청의 체인을 보여줍니다. 원천. (큰 미리보기)
  1. 항상 타사 자산을 자체 호스팅하는 것을 선호합니다.
    다시 말하지만 기본적으로 정적 자산을 자체 호스팅합니다. 많은 사이트가 동일한 공용 CDN과 동일한 버전의 JavaScript 라이브러리 또는 웹 글꼴을 사용하는 경우 방문자가 브라우저에 이미 캐시된 스크립트 및 글꼴을 사용하여 사이트를 방문하여 경험 속도가 상당히 빨라진다고 가정하는 것이 일반적입니다. . 그러나 일어날 가능성은 매우 낮습니다.

    보안상의 이유로 핑거프린팅을 피하기 위해 브라우저는 2013년에 Safari와 작년에 Chrome에 도입된 분할 캐싱을 구현했습니다. 따라서 두 사이트가 정확히 동일한 타사 리소스 URL을 가리키는 경우 코드는 도메인당 한 번 다운로드 되고 캐시는 개인 정보 보호 문제로 인해 해당 도메인에 "샌드박스"됩니다( 감사합니다, David Calhoun! ). 따라서 공용 CDN을 사용하면 자동으로 성능이 향상되지 않습니다.

    또한 리소스는 예상한 만큼 브라우저 캐시에 상주하지 않으며 자사 자산은 타사 자산보다 캐시에 남아 있을 가능성이 더 큽니다. 따라서 자체 호스팅은 일반적으로 더 안정적이고 안전하며 성능면에서도 좋습니다.

  2. 타사 스크립트의 영향을 제한합니다.
    모든 성능 최적화가 이루어지면 비즈니스 요구 사항에서 오는 타사 스크립트를 제어할 수 없는 경우가 많습니다. 타사 스크립트 메트릭은 최종 사용자 경험의 영향을 받지 않으므로 너무 자주 하나의 단일 스크립트가 불쾌한 타사 스크립트의 긴 꼬리를 호출하여 전용 성능 노력을 망치게 됩니다. 이러한 스크립트가 가져오는 성능 저하를 억제하고 완화하려면 리소스 힌트(예: dns-prefetch 또는 preconnect )를 통해 로드 및 실행을 지연하고 연결을 워밍업하는 것만으로는 충분하지 않습니다.

    현재 모든 JavaScript 코드 실행 시간의 57%가 타사 코드에 사용됩니다. 중앙값 모바일 사이트는 12개의 제3자 도메인 에 액세스하며 중앙값은 37개의 서로 다른 요청(또는 각 제3자에 대한 약 3개의 요청)입니다.

    또한 이러한 타사는 종종 타사 스크립트 를 초대하여 엄청난 성능 병목 현상을 일으키고 때로는 페이지의 8자 스크립트까지 발생합니다. 따라서 종속성과 태그 관리자를 정기적으로 감사하면 비용이 많이 드는 놀라움이 발생할 수 있습니다.

    Yoav Weiss가 타사 스크립트에 대한 강연에서 설명했듯이 또 다른 문제는 이러한 스크립트가 동적 리소스를 다운로드하는 경우가 많다는 것입니다. 리소스는 페이지 로드 간에 변경되므로 리소스가 다운로드될 호스트와 리소스가 무엇인지 알 수 없습니다.

    위에 표시된 것처럼 연기하는 것은 시작에 불과할 수 있지만 타사 스크립트도 앱에서 대역폭과 CPU 시간을 훔치기 때문입니다. 우리는 좀 더 공격적으로 앱이 초기화되었을 때만 로드할 수 있습니다.

    /* Before */ const App = () => { return <div> <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> </div> } /* After */ const App = () => { const[isRendered, setRendered] = useState(false); useEffect(() => setRendered(true)); return <div> {isRendered ? <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> : null} </div> }

    "제3자 태그의 사이트 속도 영향 줄이기"에 대한 환상적인 게시물에서 Andy Davies는 비용 식별에서 영향 감소에 이르기까지 제3자의 발자국을 최소화하는 전략을 탐구합니다.

    Andy에 따르면 태그가 사이트 속도에 영향을 미치는 두 가지 방법이 있습니다. 태그는 방문자 장치의 네트워크 대역폭 및 처리 시간 을 놓고 경쟁하며 구현 방식에 따라 HTML 구문 분석도 지연시킬 수 있습니다. 따라서 첫 번째 단계는 WebPageTest를 사용하여 스크립트를 사용하거나 사용 하지 않고 사이트 테스트하여 타사가 미치는 영향을 식별하는 것입니다. Simon Hearne의 요청 맵을 사용하면 크기, 유형 및 로드를 유발한 원인에 대한 세부 정보와 함께 페이지에서 타사를 시각화할 수도 있습니다.

    바람직하게는 자체 호스트하고 단일 호스트 이름을 사용하지만 요청 맵을 사용하여 제4자 호출을 노출하고 스크립트 변경 시기를 감지합니다. 타사 감사에 Harry Roberts의 접근 방식을 사용하고 이와 같은 스프레드시트를 생성할 수 있습니다(Harry의 감사 워크플로도 확인).

    그 후에 기존 스크립트에 대한 경량 대안을 탐색하고 중복 및 주요 원인을 더 가벼운 옵션으로 천천히 대체할 수 있습니다. 아마도 일부 스크립트는 전체 태그 대신 대체 추적 픽셀로 대체될 수 있습니다.

    lite-youtube 맞춤 요소를 사용하는 3KB의 JavaScript를 보여주는 왼쪽 예, lite-youtube 맞춤 요소를 사용하는 +540KB의 JavaScript를 보여주는 중간 및 오른쪽 예
    실제 YouTube 플레이어보다 훨씬 작은 lite-youtube-embed와 같이 정면으로 YouTube를 로드합니다. (이미지 출처) (큰 미리보기)

    그것이 실행 가능하지 않다면 우리는 적어도 파사드와 함께 제3자 리소스를 지연 로드할 수 있습니다. 즉, 실제 내장된 제3자와 유사해 보이지만 작동하지 않으므로 페이지 로드에 대한 부담이 훨씬 적은 정적 요소입니다. 따라서 트릭 은 상호 작용 시에만 실제 임베드를 로드하는 것 입니다.

    예를 들어 다음을 사용할 수 있습니다.

    • Vimeo 플레이어용 lite-vimeo-embed,
    • Vimeo 플레이어용 lite-vimeo,
    • YouTube 플레이어용 lite-youtube-embed,
    • 라이브 채팅을 위한 react-live-chat-loader(사례 연구 및 다른 사례 연구),
    • iframe을 위한 lazyframe.

    태그 관리자가 일반적으로 크기가 큰 이유 중 하나는 많은 사용자 세그먼트, 페이지 URL, 사이트 등과 함께 동시에 실행되는 많은 동시 실험 때문입니다. 따라서 Andy에 따르면 태그 관리자를 줄이면 두 가지 모두를 줄일 수 있습니다. 다운로드 크기 및 브라우저에서 스크립트를 실행하는 데 걸리는 시간.

    그리고 깜박임 방지 스니펫이 있습니다. Google Optimize, VWO(Visual Web Optimizer) 등과 같은 타사에서 만장일치로 사용하고 있습니다. 이러한 스니펫은 일반적으로 실행 중인 A/B 테스트 와 함께 주입됩니다. 다른 테스트 시나리오 사이에서 깜박임을 피하기 위해 opacity: 0 으로 문서 body 을 숨긴 다음 몇 초 후에 호출되어 opacity 를 다시 가져오는 함수를 추가합니다. . 이로 인해 막대한 클라이언트 측 실행 비용으로 인해 렌더링이 크게 지연되는 경우가 많습니다.

    방문자가 탐색을 시작할 때 깜박임 방지 스니펫에 의해 콘텐츠가 숨겨지는 방법과 시기를 보여주는 0.0초에서 6.0초까지 7개의 미리보기가 표시됨
    A/B 테스트를 사용하면 고객은 종종 이와 같은 깜박임을 볼 수 있습니다. 깜박임 방지 스니펫은 이를 방지하지만 성능 측면에서도 비용이 듭니다. Andy Davies를 통해. (큰 미리보기)

    따라서 깜박임 방지 시간 초과가 트리거되는 빈도를 추적하고 시간 초과를 줄이십시오. 기본 설정은 페이지 표시를 최대 4초까지 차단하여 전환율을 떨어뜨립니다. Tim Kadlec에 따르면 "친구는 친구가 클라이언트 측 A/B 테스트를 하게 하지 않습니다". CDN(예: 에지 컴퓨팅 또는 에지 슬라이스 재렌더링)에 대한 서버 측 A/B 테스트 는 항상 더 성능이 좋은 옵션입니다.

    강력한 Google 태그 관리자 를 처리해야 하는 경우 Barry Pollard는 Google 태그 관리자의 영향을 포함하는 몇 가지 지침을 제공합니다. 또한 Christian Schaefer는 광고 로드 전략을 살펴봅니다.

    주의: 일부 타사 위젯은 감사 도구로부터 자신을 숨기므로 발견하고 측정하기가 더 어려울 수 있습니다. 제3자를 스트레스 테스트하려면 DevTools의 성능 프로필 페이지에서 상향식 요약을 검토하고 요청이 차단되거나 시간 초과된 경우 어떤 일이 발생하는지 테스트합니다. 후자의 경우 WebPageTest의 Blackhole 서버 blackhole.webpagetest.org 를 사용할 수 있습니다. hosts 파일에서 특정 도메인을 가리킬 수 있습니다.

    그러면 어떤 옵션이 있습니까? 시간 초과로 리소스 다운로드를 경주하여 서비스 워커를 사용하는 것을 고려하고 리소스가 특정 시간 초과 내에 응답하지 않으면 빈 응답을 반환하여 브라우저에 페이지 구문 분석을 계속하도록 지시합니다. 또한 성공하지 못하거나 특정 기준을 충족하지 않는 타사 요청을 기록하거나 차단할 수 있습니다. 가능하면 공급업체 서버가 아닌 자체 서버에서 타사 스크립트를 로드하고 지연 로드하십시오.

    또 다른 옵션은 콘텐츠 보안 정책(CSP) 을 설정하여 오디오 또는 비디오 다운로드 금지와 같은 타사 스크립트의 영향을 제한하는 것입니다. 가장 좋은 방법은 <iframe> 을 통해 스크립트를 포함하여 스크립트가 iframe의 컨텍스트에서 실행되므로 페이지의 DOM에 액세스할 수 없고 도메인에서 임의의 코드를 실행할 수 없도록 하는 것입니다. iframe은 sandbox 속성을 사용하여 추가로 제한할 수 있으므로 iframe이 수행할 수 있는 모든 기능(예: 스크립트 실행 방지, 경고 방지, 양식 제출, 플러그인, 상단 탐색 액세스 등)을 비활성화할 수 있습니다.

    기능 정책을 사용하여 브라우저 내 성능 린팅을 통해 타사를 확인할 수도 있습니다. 사이트의 특정 브라우저 기능을 선택하거나 선택 해제합니다. (참고로, 크기가 크거나 최적화되지 않은 이미지, 크기가 조정되지 않은 미디어, 동기화 스크립트 등을 피하는 데 사용할 수도 있습니다.) 현재 Blink 기반 브라우저에서 지원됩니다.

    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'
    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'

    많은 타사 스크립트가 iframe에서 실행되기 때문에 허용량을 철저히 제한해야 합니다. 샌드박스 처리된 iframe은 항상 좋은 생각이며 sandbox 속성의 여러 allow 값을 통해 각 제한을 해제할 수 있습니다. 샌드박싱은 거의 모든 곳에서 지원되므로 타사 스크립트를 허용해야 하는 최소한의 작업으로 제한합니다.

    엔티티의 스크립트가 평균적으로 실행되는 데 걸리는 시간을 시각화하는 ThirdPartyWeb.Today 웹 사이트의 스크린샷
    ThirdPartyWeb.Today는 카테고리(분석, 소셜, 광고, 호스팅, 태그 관리자 등)별로 모든 타사 스크립트를 그룹화하고 엔터티의 스크립트를 실행하는 데 걸리는 평균 시간을 시각화합니다. (큰 미리보기)

    교차로 관찰기 사용을 고려하십시오. 이벤트를 전달하거나 DOM에서 필요한 정보(예: 광고 가시성)를 가져오는 동안 광고를 iframe할 수 있습니다 . 기능 정책, 리소스 크기 제한 및 CPU/대역폭 우선 순위와 같은 새로운 정책에 주의하여 유해한 웹 기능 및 브라우저 속도를 늦추는 스크립트(예: 동기 스크립트, 동기 XHR 요청, document.write 및 오래된 구현)를 제한하십시오.

    마지막으로, 타사 서비스를 선택할 때 Patrick Hulce의 ThirdPartyWeb.Today를 확인하는 것이 좋습니다. 이 서비스는 모든 타사 스크립트를 범주(분석, 소셜, 광고, 호스팅, 태그 관리자 등)별로 그룹화 하고 엔터티의 스크립트가 얼마나 긴지 시각화하는 서비스입니다. (평균적으로) 실행합니다. 분명히 가장 큰 엔터티는 그들이 있는 페이지에 최악의 성능 영향을 미칩니다. 페이지를 훑어보는 것만으로도 예상해야 하는 성능 발자국에 대한 아이디어를 얻을 수 있습니다.

    아, 그리고 일반적인 용의자를 잊지 마십시오. 공유를 위한 타사 위젯 대신 정적 소셜 공유 버튼(예: SSBG)과 대화형 맵 대신 대화형 맵에 대한 정적 링크를 사용할 수 있습니다.

자사 및 타사 요청 비율을 비교한 그래프 예: 자사 요청의 27%에 해당하는 399KB, 타사 요청의 73%에 해당하는 1.15MB
Casper.com은 Optimizely를 자체 호스팅하여 사이트에서 1.7초를 단축할 수 있었던 방법에 대한 자세한 사례 연구를 게시했습니다. 그럴만한 가치가 있습니다. (이미지 출처) (큰 미리보기)
  1. HTTP 캐시 헤더를 올바르게 설정하십시오.
    캐싱은 해야 할 일인 것처럼 보이지만 제대로 하기는 꽤 어려울 수 있습니다. expires , max-age , cache-control 및 기타 HTTP 캐시 헤더가 올바르게 설정되었는지 다시 확인해야 합니다. 적절한 HTTP 캐시 헤더가 없으면 브라우저는 last-modified 이후 경과 시간의 10%에 자동으로 설정하여 잠재적인 과소 및 과소 캐싱으로 끝납니다.

    일반적으로 리소스는 매우 짧은 시간(변경될 가능성이 있는 경우) 또는 무기한(정적인 경우) 캐시할 수 있어야 합니다. 필요할 때 URL에서 버전을 변경할 수 있습니다. Cache-Forever 전략이라고 부를 수 있습니다. 이 전략에서는 Cache-ControlExpires 헤더를 브라우저에 전달하여 자산이 1년 내에만 만료되도록 할 수 있습니다. 따라서 브라우저는 자산이 캐시에 있는 경우 자산을 요청하지도 않습니다.

    API 응답은 예외입니다(예: /api/user ). 캐싱을 방지하기 위해 max-age=0, no-store 아닌 private, no store 를 사용할 수 있습니다.

     Cache-Control: private, no-store

    Cache-control: immutable 을 사용하여 사용자가 다시 로드 버튼을 눌렀을 때 긴 명시적 캐시 수명의 재검증을 방지합니다. 다시 로드의 경우 immutable 은 HTTP 요청을 저장하고 동적 HTML이 더 이상 다수의 304 응답과 경쟁하지 않으므로 로드 시간을 개선합니다.

    immutable 수 없는 것을 사용하려는 일반적인 예는 이름에 해시가 있는 CSS/JavaScript 자산입니다. 그들을 위해 우리는 아마도 가능한 한 오랫동안 캐시하고 그들이 재검증되지 않도록 하기를 원할 것입니다.

    Cache-Control: max-age: 31556952, immutable

    Colin Bendell의 연구에 따르면 immutablemax-age 를 사용하는 경우에도 304 리디렉션을 약 50%만큼 줄입니다. 클라이언트는 여전히 새로 고침 시 다시 유효성을 검사하고 차단합니다. Firefox, Edge 및 Safari에서 지원되며 Chrome은 여전히 ​​이 문제에 대해 논의 중입니다.

    Web Almanac에 따르면 "사용률이 3.5%로 증가했으며 Facebook 및 Google 타사 응답에서 널리 사용됩니다."

    Android Chrome 및 iOS Safari에서 검색된 데이터를 사용하여 대륙 전체에 걸친 캐시 제어의 효율성
    Cache-Control: Immutable은 Cloudinary에서 Colin Bendell의 연구에 따르면 304를 약 50% 감소시킵니다. (큰 미리보기)

    오래된 오래된 재검증을 기억하십니까? Cache-Control 응답 헤더(예: Cache-Control: max-age=604800 )로 캐싱 시간을 지정하면 max-age 가 만료된 후 브라우저가 요청한 콘텐츠를 다시 가져와 페이지 로드 속도를 느리게 합니다. 이 속도 저하를 stale-while-revalidate 로 피할 수 있습니다. 기본적으로 캐시가 백그라운드에서 비동기식으로 재검증하는 한 오래된 자산을 사용할 수 있는 추가 시간 창을 정의합니다. 따라서 클라이언트의 대기 시간(네트워크 및 서버 모두에서)을 "숨깁니다".

    2019년 6~7월에 Chrome과 Firefox는 HTTP Cache-Control 헤더에서 stale-while-revalidate 지원을 시작했습니다. 따라서 결과적으로 오래된 자산이 더 이상 중요한 경로에 있지 않으므로 후속 페이지 로드 지연 시간을 개선해야 합니다. 결과: 반복 보기에 대한 RTT가 0입니다.

    특히 CDN과 관련하여 가변 헤더를 조심하고 새로운 요청이 이전 요청과 약간(그러나 크게 다르지는 않음) 다를 때마다 유효성 검사를 위한 추가 왕복을 방지하는 데 도움이 되는 HTTP 표현 변형에 주의하십시오( 감사합니다, Guy 및 Mark ) .

    또한 불필요한 헤더(예: x-powered-by , pragma , x-ua-compatible , expires , X-XSS-Protection 등)를 보내고 있지 않고 유용한 보안 및 성능 헤더(예: Content-Security-Policy , X-Content-Type-Options 등). 마지막으로 단일 페이지 애플리케이션에서 CORS 요청의 성능 비용을 염두에 두십시오.

    참고 : 우리는 종종 캐시된 자산을 즉시 검색한다고 가정하지만 연구에 따르면 캐시에서 개체를 검색하는 데 수백 밀리초가 걸릴 수 있습니다. 실제로 Simon Hearne에 따르면 "때로는 네트워크가 캐시보다 빠를 수 있으며 캐시에서 자산을 검색하는 것은 많은 수의 캐시된 자산(파일 크기 아님)과 사용자 기기로 인해 비용이 많이 들 수 있습니다. 예: Chrome OS 평균 캐시 검색 5개의 캐시된 리소스가 있는 ~50ms에서 25개의 리소스가 있는 최대 ~100ms로 두 배가 됩니다."

    게다가 우리는 종종 번들 크기가 큰 문제가 아니며 사용자가 한 번 다운로드한 다음 캐시된 버전을 사용한다고 가정합니다. 동시에 CI/CD를 사용하여 하루에 여러 번 코드를 프로덕션으로 푸시하고 캐시가 매번 무효화되므로 캐싱 문제에 대해 전략적입니다.

    캐싱과 관련하여 읽을 가치가 있는 리소스가 많이 있습니다.

    • 민간인을 위한 캐시 제어, Harry Roberts와 함께 모든 캐싱에 대해 자세히 알아보십시오.
    • HTTP 캐싱 헤더에 대한 Heroku의 입문서,
    • Jake Archibald의 캐싱 모범 사례,
    • Ilya Grigorik의 HTTP 캐싱 입문서,
    • Jeff Posnick의 stale-while-revalidate로 최신 상태를 유지합니다.
    • CS Visualized: Lydia Hallie의 CORS는 CORS, 작동 방식 및 이해 방법에 대한 훌륭한 설명입니다.
    • CORS에 대해 이야기하면서 여기 Eric Portis의 Same-Origin Policy에 대한 복습이 있습니다.
오른쪽에서 이름이 다른 OS 및 브라우저의 캐시된 자산 수에 따른 캐시 검색 시간을 보여주는 그래프(위에서 아래로): Desktop Chrome OS, Tablet Android OS, Mobile Android OS, Desktop Mac =S X, Desktop Windows, Desktop Linux
우리는 브라우저 캐시가 거의 즉각적이라고 가정하지만 데이터에 따르면 캐시에서 개체를 검색하는 데 수백 밀리초가 걸릴 수 있습니다! 네트워크가 캐시보다 빠를 때에 대한 Simon Hearne의 연구에서 발췌. (큰 미리보기)

배달 최적화

  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 속성에 대한 참조 테이블을 확인하세요. 그리고 합성.

네트워킹 및 HTTP/2

  1. OCSP 스테이플링이 활성화되어 있습니까?
    서버에서 OCSP 스테이플링을 활성화하면 TLS 핸드셰이크 속도를 높일 수 있습니다. OCSP(온라인 인증서 상태 프로토콜)는 CRL(인증서 해지 목록) 프로토콜의 대안으로 만들어졌습니다. 두 프로토콜 모두 SSL 인증서가 해지되었는지 확인하는 데 사용됩니다.

    그러나 OCSP 프로토콜은 브라우저가 인증서 정보 목록을 다운로드한 다음 검색하는 데 시간을 할애할 필요가 없으므로 핸드셰이크에 필요한 시간이 줄어듭니다.

  2. SSL 인증서 해지의 영향을 줄였습니까?
    "EV 인증서의 성능 비용"에 대한 기사에서 Simon Hearne은 일반 인증서에 대한 훌륭한 개요와 인증서 선택이 전체 성능에 미칠 수 있는 영향을 제공합니다.

    Simon이 쓴 것처럼 HTTPS의 세계에는 트래픽을 보호하는 데 사용되는 몇 가지 유형의 인증서 유효성 검사 수준이 있습니다.

    • DV( 도메인 유효성 검사 )는 인증서 요청자가 도메인을 소유하고 있는지 확인하고,
    • 조직 검증 (OV)은 조직이 도메인을 소유하고 있는지,
    • 확장 검증 (EV)은 엄격한 검증을 통해 조직이 도메인을 소유하고 있는지 검증합니다.

    이러한 모든 인증서는 기술 측면에서 동일합니다. 인증서에 제공된 정보와 속성만 다릅니다.

    EV 인증서는 사람이 인증서를 검토하고 유효성을 확인해야 하므로 비용이 많이 들고 시간이 많이 걸립니다 . 반면에 DV 인증서는 많은 호스팅 제공업체 및 CDN에 잘 통합된 개방형 자동화 인증 기관(예: Let's Encrypt)에서 무료로 제공되는 경우가 많습니다. 사실, 이 글을 쓰는 시점에서 2억 2,500만 개 이상의 웹사이트(PDF)를 지원하지만 페이지의 2.69%(Firefox에서 열림)만 차지합니다.

    그렇다면 무엇이 문제인가? 문제는 EV 인증서가 위에서 언급한 OCSP 스테이플링을 완전히 지원하지 않는다는 것 입니다. 스테이플링을 사용하면 서버가 인증서가 해지되었는지 인증 기관에 확인한 다음 이 정보를 인증서에 추가("스테이플")할 수 있지만 스테이플링 없이 클라이언트가 모든 작업을 수행해야 하므로 TLS 협상 중에 불필요한 요청이 발생합니다. . 연결 상태가 좋지 않으면 눈에 띄는 성능 비용(1000ms+)이 발생할 수 있습니다.

    EV 인증서는 웹 성능을 위한 좋은 선택이 아니며 DV 인증서보다 성능에 훨씬 더 큰 영향을 미칠 수 있습니다. 최적의 웹 성능을 위해 항상 OCSP 스테이플 DV 인증서를 제공하십시오. 또한 EV 인증서보다 훨씬 저렴하고 번거롭지 않습니다. 글쎄, 적어도 CRLite를 사용할 수 있을 때까지는.

    일반, 압축 또는 둘 다의 경우 사이트 UDP 데이터그램에 따른 핸드셰이크 수를 보여주는 그래프
    압축 문제: 압축되지 않은 인증서 체인의 40–43%는 너무 커서 3개의 UDP 데이터그램의 단일 QUIC 비행에 맞지 않습니다. (이미지 크레디트:) Fastly) (큰 미리보기)

    참고 : QUIC/HTTP/3를 사용하면 TLS 인증서 체인이 QUIC 핸드셰이크의 바이트 수를 지배하는 하나의 가변 크기 콘텐츠라는 점에 주목할 가치가 있습니다. 크기는 수백 바이트에서 10KB 이상까지 다양합니다.

    따라서 TLS 인증서를 작게 유지하는 것은 QUIC/HTTP/3에서 매우 중요합니다. 큰 인증서는 다중 핸드셰이크를 유발하기 때문입니다. 또한 인증서가 압축되어 있는지 확인해야 합니다. 그렇지 않으면 인증서 체인이 너무 커서 단일 QUIC 항공편에 맞지 않을 수 있습니다.

    다음에서 문제와 솔루션에 대한 자세한 내용과 포인터를 찾을 있습니다.

    • EV 인증서는 웹을 느리고 신뢰할 수 없게 만듭니다. Aaron Peters,
    • SSL 인증서 해지가 웹 성능에 미치는 영향 Matt Hobbs,
    • Simon Hearne의 EV 인증서 성능 비용,
    • QUIC 핸드셰이크가 빠르려면 압축이 필요합니까? 패트릭 맥마누스 지음.
  3. 아직 IPv6을 채택하셨습니까?
    IPv4의 공간이 부족하고 주요 모바일 네트워크에서 IPv6을 빠르게 채택하고 있기 때문에(미국은 거의 50% IPv6 채택 임계값에 도달했습니다), 미래를 대비하기 위해 DNS를 IPv6으로 업데이트하는 것이 좋습니다. 네트워크 전체에 이중 스택 지원이 제공되는지 확인하십시오. IPv6과 IPv4가 동시에 실행될 수 있습니다. 결국 IPv6은 이전 버전과 호환되지 않습니다. 또한 연구에 따르면 IPv6은 NDP(이웃 검색) 및 경로 최적화로 인해 해당 웹 사이트를 10~15% 더 빠르게 만들었습니다.
  4. 모든 자산이 HTTP/2(또는 HTTP/3)를 통해 실행되는지 확인하십시오.
    Google이 지난 몇 년 동안 더 안전한 HTTPS 웹을 추진함에 따라 HTTP/2 환경으로의 전환은 확실히 좋은 투자입니다. 실제로 Web Almanac에 따르면 모든 요청의 64%가 이미 HTTP/2를 통해 실행되고 있습니다.

    HTTP/2는 완벽하지 않고 우선순위 문제가 있지만 매우 잘 지원된다는 점을 이해하는 것이 중요합니다. 그리고 대부분의 경우에 더 좋습니다.

    주의 사항: HTTP/2 서버 푸시가 Chrome에서 제거되고 있으므로 구현이 서버 푸시에 의존하는 경우 다시 방문해야 할 수 있습니다. 대신 이미 Fastly에서 실험으로 통합된 Early Hint를 볼 수 있습니다.

    여전히 HTTP에서 실행 중인 경우 가장 시간이 많이 걸리는 작업은 먼저 HTTPS로 마이그레이션한 다음 HTTP/2 멀티플렉싱 및 병렬화를 수용하도록 빌드 프로세스를 조정하는 것입니다. HTTP/2를 Gov.uk로 가져오는 것은 CORS, SRI 및 WPT를 통해 방법을 찾는 것과 같은 작업에 대한 환상적인 사례 연구입니다. 이 기사의 나머지 부분에서는 HTTP/2로 전환 중이거나 이미 HTTP/2로 전환했다고 가정합니다.

2016년 1월 2일부터 2020년 10월 1일까지 데스크톱과 모바일 모두에서 HTTP/2 요청의 시계열을 보여주는 그래프
Web Almanac에 따르면 2020년 후반에 모든 요청의 64%가 HTTP/2를 통해 제공됩니다. 이는 공식 표준화된 지 불과 4년 만입니다. (이미지 출처: Web Almanac) (큰 미리보기)
  1. HTTP/2를 적절하게 배포합니다.
    다시 말하지만, HTTP/2를 통해 자산을 제공하는 것은 지금까지 자산을 제공한 방식을 부분적으로 점검함으로써 이점을 얻을 수 있습니다. 모듈 패키징과 많은 작은 모듈을 병렬로 로드하는 것 사이에서 균형을 잘 찾아야 합니다. 하루가 끝나면 여전히 가장 좋은 요청은 요청이 없는 것이지만 목표는 자산의 빠른 첫 번째 전달과 캐싱 사이에서 적절한 균형을 찾는 것입니다.

    한편으로는 전체 인터페이스를 여러 개의 작은 모듈로 분할하여 빌드 프로세스의 일부로 압축하고 병렬로 로드하는 대신 자산을 완전히 연결하는 것을 피하고 싶을 수 있습니다. 파일 하나를 변경해도 전체 스타일 시트나 JavaScript를 다시 다운로드할 필요가 없습니다. 또한 구문 분석 시간을 최소화하고 개별 페이지의 페이로드를 낮게 유지합니다.

    반면에 포장은 여전히 ​​중요합니다. 많은 작은 스크립트를 사용하면 전체 압축이 저하 되고 캐시에서 개체를 검색하는 비용이 증가합니다. 큰 패키지를 압축하면 사전 재사용의 이점을 얻을 수 있지만 작은 개별 패키지는 그렇지 않습니다. 이를 해결하기 위한 표준 작업이 있지만 현재로서는 아직 멀었습니다. 둘째, 브라우저는 아직 이러한 워크플로에 최적화되어 있지 않습니다 . 예를 들어 Chrome은 리소스 수에 선형적으로 IPC(프로세스 간 통신)를 트리거하므로 수백 개의 리소스를 포함하면 브라우저 런타임 비용이 발생합니다.

    점진적 CSS 로딩을 사용하는 HTML 코드
    HTTP/2로 최상의 결과를 얻으려면 Chrome의 Jake Archibald가 제안한 대로 CSS를 점진적으로 로드하는 것이 좋습니다.

    그래도 CSS를 점진적으로 로드할 수 있습니다. 사실 인바디 CSS는 더 이상 Chrome용 렌더링을 차단하지 않습니다. 그러나 몇 가지 우선 순위 문제가 있으므로 간단하지는 않지만 실험해 볼 가치가 있습니다.

    HTTP/2 연결 병합을 사용하면 HTTP/2의 이점을 누리면서 도메인 샤딩을 사용할 수 있지만 실제로 이를 달성하는 것은 어렵고 일반적으로 좋은 방법으로 간주되지 않습니다. 또한 HTTP/2 및 하위 리소스 무결성이 항상 작동하는 것은 아닙니다.

    무엇을 할까요? HTTP/2를 통해 실행하는 경우 약 6-10개의 패키지 를 보내는 것이 적절한 절충안처럼 보입니다(레거시 브라우저에서는 나쁘지 않습니다). 웹사이트에 적합한 균형을 찾기 위해 실험하고 측정합니다.

  2. 단일 HTTP/2 연결을 통해 모든 자산을 전송합니까?
    HTTP/2의 주요 장점 중 하나는 단일 연결을 통해 자산을 전송할 수 있다는 것입니다. 그러나 때로는 우리가 뭔가 잘못했을 수 있습니다. 예를 들어 CORS 문제가 있거나 crossorigin 속성을 잘못 구성하여 브라우저가 새 연결을 열도록 강제할 수 있습니다.

    모든 요청이 단일 HTTP/2 연결을 사용하는지 또는 무언가 잘못 구성되었는지 확인하려면 DevTools → 네트워크에서 "연결 ID" 열을 활성화하십시오. 예를 들어 여기에서 모든 요청은 동일한 연결(286)을 공유합니다. 단, manifest.json은 별도의 연결(451)을 엽니다.

Chrome 브라우저에서 열린 DevTools의 스크린샷
모든 요청은 동일한 HTTP/2 연결(286)을 공유합니다. 단, 별도의 연결(451)을 여는 manifest.json은 예외입니다. iamakulov를 통해. (큰 미리보기)
  1. 서버와 CDN이 HTTP/2를 지원합니까?
    다른 서버와 CDN(여전히)은 HTTP/2를 다르게 지원합니다. CDN 비교를 사용하여 옵션을 확인하거나 서버의 성능과 지원되는 기능을 빠르게 찾아보십시오.

    HTTP/2 우선 순위(비디오) 및 HTTP/2 우선 순위 지정에 대한 테스트 서버 지원에 대한 Pat Meenan의 놀라운 연구를 참조하십시오. Pat에 따르면 Linux 4.9 커널 이상에서 안정적으로 작동하려면 BBR 혼잡 제어를 활성화하고 tcp_notsent_lowat 를 16KB로 설정하는 것이 좋습니다( 감사합니다, Yoav! ). Andy Davies는 브라우저, CDN 및 Cloud Hosting Services에서 HTTP/2 우선 순위 지정에 대해 유사한 연구를 수행했습니다.

    그 상태에서 커널이 TCP BBR을 지원하는지 다시 확인하고 가능한 경우 활성화하십시오. 현재 Google Cloud Platform, Amazon Cloudfront, Linux(예: Ubuntu)에서 사용됩니다.

  2. HPACK 압축이 사용 중입니까?
    HTTP/2를 사용하는 경우 불필요한 오버헤드를 줄이기 위해 서버가 HTTP 응답 헤더에 대해 HPACK 압축을 구현하는지 다시 확인하십시오. 일부 HTTP/2 서버는 사양을 완전히 지원하지 않을 수 있으며 HPACK이 예입니다. H2spec은 이를 확인하는 훌륭한(기술적으로 세부적인 경우) 도구입니다. HPACK의 압축 알고리즘은 매우 인상적이며 작동합니다.
  3. 서버의 보안이 방탄인지 확인하십시오.
    HTTP/2의 모든 브라우저 구현은 TLS를 통해 실행되므로 보안 경고나 페이지의 일부 요소가 작동하지 않는 것을 피하고 싶을 것입니다. 보안 헤더가 올바르게 설정되었는지 다시 확인하고 알려진 취약점을 제거하고 HTTPS 설정을 확인하십시오.

    또한 모든 외부 플러그인 및 추적 스크립트가 HTTPS를 통해 로드되고 교차 사이트 스크립팅이 불가능하며 HTTP Strict Transport Security 헤더와 콘텐츠 보안 정책 헤더가 모두 올바르게 설정되었는지 확인하십시오.

  4. 서버와 CDN이 HTTP/3를 지원합니까?
    HTTP/2는 웹에 여러 가지 중요한 성능 향상을 가져왔지만 상당한 패킷 손실이 있는 느린 네트워크에서 눈에 띄는 TCP의 head-of-line 차단과 같이 개선해야 할 부분도 많이 남겼습니다. HTTP/3는 이러한 문제를 잘 해결하고 있습니다(기사).

    HTTP/2 문제를 해결하기 위해 IETF는 Google, Akamai 등과 함께 최근에 HTTP/3으로 표준화된 새로운 프로토콜을 개발하고 있습니다.

    Robin Marx는 HTTP/3에 대해 아주 잘 설명했고, 다음 설명은 그 설명을 기반으로 합니다. 핵심적으로 HTTP/3은 기능 측면에서 HTTP/2와 매우 유사 하지만 내부적으로는 매우 다르게 작동합니다. HTTP/3는 더 빠른 핸드셰이크, 더 나은 암호화, 더 안정적인 독립 스트림, 더 나은 암호화 및 흐름 제어와 같은 여러 개선 사항을 제공합니다. 주목할만한 차이점은 HTTP/3이 TCP가 아닌 UDP 다이어그램 위에 캡슐화된 QUIC 패킷과 함께 QUIC를 전송 계층으로 사용한다는 것입니다.

    QUIC는 TLS 1.3을 프로토콜에 완전히 통합하는 반면 TCP에서는 맨 위에 계층화됩니다. 일반적인 TCP 스택에서는 TCP와 TLS가 별도의 핸드셰이크를 수행해야 하기 때문에 몇 번의 왕복 오버헤드가 있지만 QUIC를 사용하면 두 가지 모두를 단일 왕복으로 결합하고 완료 할 수 있습니다. TLS 1.3을 사용하면 후속 연결에 대한 암호화 키를 설정할 수 있으므로 두 번째 연결부터 "0-RTT"라고 하는 첫 번째 왕복에서 애플리케이션 계층 데이터를 이미 보내고 받을 수 있습니다.

    또한 HTTP/2의 헤더 압축 알고리즘은 우선 순위 시스템과 함께 완전히 재작성되었습니다. 또한 QUIC는 각 QUIC 패킷 헤더의 연결 ID를 통해 Wi-Fi에서 셀룰러 네트워크로의 연결 마이그레이션 을 지원합니다. 대부분의 구현은 커널 공간이 아닌 사용자 공간에서 이루어지므로(TCP에서와 같이) 앞으로 프로토콜이 발전할 것으로 예상해야 합니다.

    모든 것이 큰 차이를 만들까요? 아마도 그렇습니다. 특히 모바일에서 로딩 시간에 영향을 미칠 뿐만 아니라 최종 사용자에게 자산을 제공하는 방법에도 영향을 미칩니다. HTTP/2에서는 여러 요청이 연결을 공유하지만 HTTP/3에서는 요청도 연결을 공유하지만 독립적으로 스트리밍하므로 삭제된 패킷이 더 이상 모든 요청에 ​​영향을 미치지 않고 하나의 스트림에만 영향을 줍니다.

    즉, 하나의 큰 JavaScript 번들을 사용하면 하나의 스트림이 일시 중지되면 자산 처리 속도가 느려지지만 여러 파일이 병렬로 스트리밍되는 경우(HTTP/3) 영향이 덜 중요합니다. 그래서 포장은 여전히 ​​중요 합니다.

    HTTP/3는 아직 진행 중입니다. Chrome, Firefox 및 Safari에는 이미 구현이 있습니다. 일부 CDN은 이미 QUIC 및 HTTP/3을 지원합니다. 2020년 말 Chrome은 HTTP/3 및 IETF QUIC 배포를 시작했으며 실제로 모든 Google 서비스(Google Analytics, YouTube 등)는 이미 HTTP/3를 통해 실행되고 있습니다. LiteSpeed ​​웹 서버는 HTTP/3를 지원하지만 Apache, nginx 또는 IIS는 아직 지원하지 않지만 2021년에는 빠르게 변경될 것입니다.

    결론 : 서버와 CDN에서 HTTP/3를 사용할 수 있는 옵션이 있다면 그렇게 하는 것이 좋습니다. 주요 이점은 특히 대기 시간이 긴 연결에서 여러 개체를 동시에 가져오는 것입니다. 해당 분야에 대한 연구가 많지 않아 아직 확실하지 않지만 첫 번째 결과는 매우 유망합니다.

    프로토콜의 세부 사항과 장점에 대해 더 자세히 알아보려면 다음을 확인하는 것이 좋습니다.

    • HTTP/3 설명, HTTP/3 및 QUIC 프로토콜을 문서화하기 위한 공동 작업. 다양한 언어로 제공되며 PDF로도 제공됩니다.
    • Daniel Stenberg와 함께 HTTP/3으로 웹 성능을 향상시키십시오.
    • Robin Marx와 함께 QUIC에 대한 아카데믹 가이드는 QUIC 및 HTTP/3 프로토콜의 기본 개념을 소개하고, HTTP/3가 헤드 오브 라인 차단 및 연결 마이그레이션을 처리하는 방법, HTTP/3이 항상 지속되도록 설계되는 방법을 설명합니다(감사합니다, Simon !).
    • HTTP3Check.net에서 서버가 HTTP/3에서 실행 중인지 확인할 수 있습니다.

테스트 및 모니터링

  1. 감사 워크플로를 최적화했습니까?
    별 것 아닌 것처럼 들릴 수도 있지만 손끝에서 올바른 설정을 하면 테스트 시간을 상당히 절약할 수 있습니다. WebPageTest의 공개 인스턴스에 테스트를 제출하기 위해 Tim Kadlec의 Alfred Workflow for WebPageTest를 사용하는 것을 고려하십시오. 실제로 WebPageTest에는 모호한 기능이 많이 있으므로 시간을 내어 WebPageTest Waterfall View 차트를 읽는 방법과 WebPageTest Connection View 차트를 읽는 방법을 배워 성능 문제를 더 빨리 진단하고 해결하십시오.

    또한 Google 스프레드시트에서 WebPageTest를 구동하고 Lighthouse CI를 사용하여 Travis 설정에 접근성, 성능 및 SEO 점수를 통합하거나 Webpack에 바로 통합할 수 있습니다.

    여러 소스에서 성능 데이터를 자동으로 수집할 수 있는 모듈식 도구인 최근 출시된 AutoWebPerf를 살펴보십시오. 예를 들어 중요한 페이지에 대한 일일 테스트를 설정하여 CrUX API의 현장 데이터와 PageSpeed ​​Insights의 Lighthouse 보고서에서 실험실 데이터를 캡처할 수 있습니다.

    그리고 무언가를 빠르게 디버그해야 하지만 빌드 프로세스가 현저하게 느린 것 같다면 "공백 제거 및 기호 맹글링은 정교한 코드 변환이 아니라 대부분의 JavaScript에서 축소된 코드의 크기 감소의 95%를 차지합니다. 압축을 비활성화하면 Uglify 빌드 속도가 3~4배 빨라집니다."

검토가 필요하고 검사가 성공적으로 해결될 때까지 병합이 차단된다는 GitHub의 풀 요청 알림 스크린샷
Lighthouse CI를 사용하여 Travis 설정에 접근성, 성능 및 SEO 점수를 통합하면 기여하는 모든 개발자에게 새 기능의 성능 영향이 강조 표시됩니다. (이미지 출처) (큰 미리보기)
  1. 프록시 브라우저와 레거시 브라우저에서 테스트했습니까?
    Chrome 및 Firefox에서 테스트하는 것만으로는 충분하지 않습니다. 웹사이트가 프록시 브라우저와 레거시 브라우저에서 어떻게 작동하는지 살펴보세요. 예를 들어 UC Browser와 Opera Mini는 아시아에서 상당한 시장 점유율을 차지하고 있습니다(아시아에서는 최대 35%). 나중에 큰 놀라움을 피하기 위해 관심 국가의 평균 인터넷 속도를 측정하십시오. 네트워크 조절로 테스트하고 높은 DPI 장치를 에뮬레이트합니다. BrowserStack은 원격 실제 장치에서 테스트하는 데 환상적이며 사무실에 있는 최소한 몇 대의 실제 장치로도 이를 보완합니다. 그만한 가치가 있습니다.
  1. 404 페이지의 성능을 테스트해 보셨습니까?
    일반적으로 우리는 404페이지에 대해 두 번 생각하지 않습니다. 결국 클라이언트가 서버에 존재하지 않는 페이지를 요청하면 서버는 404 상태 코드 및 관련 404 페이지로 응답합니다. 그렇게 많지 않죠?

    404 응답의 중요한 측면은 브라우저로 전송되는 실제 응답 본문 크기 입니다. Matt Hobbs의 404페이지 연구에 따르면 404 응답의 대다수는 누락된 파비콘, WordPress 업로드 요청, 깨진 JavaScript 요청, 매니페스트 파일, CSS 및 글꼴 파일에서 비롯됩니다. 클라이언트가 존재하지 않는 자산을 요청할 때마다 404 응답을 받게 되며 종종 그 응답은 엄청납니다.

    404 페이지에 대한 캐싱 전략 을 검토하고 최적화하십시오. 우리의 목표는 HTML 응답을 예상할 때만 브라우저에 HTML을 제공하고 다른 모든 응답에 대해 작은 오류 페이로드를 반환하는 것입니다. Matt에 따르면 "원점 앞에 CDN을 배치하면 CDN에 404 페이지 응답을 캐시할 수 있습니다. CDN이 없으면 404 페이지를 공격하는 것이 DoS 공격 벡터로 사용될 수 있기 때문에 유용합니다. CDN이 캐시된 버전으로 응답하도록 하는 대신 원본 서버가 모든 404 요청에 응답하도록 강제합니다."

    404 오류는 성능을 저하시킬 뿐만 아니라 트래픽 비용도 발생할 수 있으므로 Lighthouse 테스트 제품군에 404 오류 페이지를 포함하고 시간 경과에 따른 점수를 추적하는 것이 좋습니다.

  2. GDPR 동의 프롬프트의 성능을 테스트했습니까?
    GDPR 및 CCPA 시대에는 EU 고객이 추적을 선택하거나 선택 해제할 수 있는 옵션을 제공하기 위해 타사에 의존하는 것이 일반적이 되었습니다. 그러나 다른 타사 스크립트와 마찬가지로 해당 스크립트의 성능은 전체 성능 노력에 상당히 치명적인 영향을 미칠 수 있습니다.

    물론 실제 동의는 스크립트가 전체 성능에 미치는 영향을 변경할 가능성이 있으므로 Boris Schapira가 언급했듯이 몇 가지 다른 웹 성능 프로필을 연구하고 싶을 수 있습니다.

    • 동의를 완전히 거부했으며,
    • 동의가 부분적으로 거부되었으며,
    • 전적으로 동의했습니다.
    • 사용자가 동의 프롬프트에 대해 조치를 취하지 않았습니다(또는 프롬프트가 콘텐츠 차단기에 의해 차단됨).

    일반적으로 쿠키 동의 프롬프트는 CLS에 영향을 미치지 않아야 하지만 때때로 영향을 미치므로 무료 및 오픈 소스 옵션인 Osano 또는 cookie-consent-box를 사용하는 것이 좋습니다.

    일반적으로 마우스 이벤트의 수평 또는 수직 오프셋을 결정하고 앵커에 상대적으로 팝업을 올바르게 배치해야 하므로 팝업 성능 을 조사할 가치가 있습니다. Noam Rosenthal은 웹 성능 사례 연구: Wikipedia 페이지 미리보기(비디오 및 회의록으로도 사용 가능) 문서에서 Wikimedia 팀의 학습 내용을 공유합니다.

  3. 성능 진단 CSS를 유지합니까?
    성능이 저하된 코드가 배포되었는지 확인하기 위해 모든 종류의 검사를 포함할 수 있지만 쉽게 해결할 수 있는 몇 가지 간단한 결과에 대한 빠른 아이디어를 얻는 것이 유용한 경우가 많습니다. 이를 위해 Tim Kadlec의 뛰어난 성능 진단 CSS(지연 로드 이미지, 크기가 지정되지 않은 이미지, 레거시 형식 이미지 및 동기 스크립트를 강조 표시하는 Harry Roberts의 스니펫에서 영감을 얻었습니다.

    예를 들어 스크롤 없이 볼 수 있는 이미지가 지연 로드되지 않도록 하고 싶을 수 있습니다. 예를 들어 사용되지 않는 웹 글꼴을 강조 표시하거나 아이콘 글꼴을 감지하기 위해 필요에 따라 스니펫을 사용자 정의할 수 있습니다. 디버깅하는 동안 실수를 확인하거나 현재 프로젝트를 매우 빠르게 감사하기 위한 아주 작은 도구입니다.

    /* Performance Diagnostics CSS */ /* via Harry Roberts. https://twitter.com/csswizardry/status/1346477682544951296 */ img[loading=lazy] { outline: 10px solid red; }
  1. 접근성에 대한 영향을 테스트했습니까?
    브라우저가 페이지를 로드하기 시작하면 DOM을 구축하고, 실행 중인 스크린 리더와 같은 보조 기술이 있으면 접근성 트리도 생성합니다. 그런 다음 화면 판독기는 정보를 검색하고 사용자가 사용할 수 있도록 접근성 트리를 쿼리해야 합니다. 그리고 때로는 시간이 걸립니다.

    빠른 대화형 시간에 대해 이야기할 때 일반적으로 사용자가 링크 및 버튼을 클릭하거나 탭하여 페이지와 상호 작용할 수 있는 시간을 나타내는 지표를 의미합니다. 화면 판독기에서는 컨텍스트가 약간 다릅니다. 이 경우 빠른 대화형 시간은 스크린 리더가 주어진 페이지에 대한 탐색을 알릴 수 있고 스크린 리더 사용자가 실제로 키보드를 눌러 상호 작용할 수 있을 때까지 경과하는 시간 을 의미합니다.

    Leonie Watson은 접근성 성능, 특히 느린 로딩이 스크린 리더 발표 지연에 미치는 영향에 대해 놀라운 연설을 했습니다. 스크린 리더는 빠른 속도로 진행되는 안내 방송과 빠른 탐색에 사용되므로 잠재적으로 시력이 좋은 사용자보다 인내심이 덜할 수 있습니다.

    JavaScript를 사용한 큰 페이지 및 DOM 조작으로 인해 스크린 리더 발표가 지연됩니다. 스크린 리더로 약간의 주의와 테스트를 사용할 수 있는 다소 미개척 영역은 말 그대로 모든 플랫폼(Jaws, NVDA, Voiceover, Narrator, Orca)에서 사용할 수 있습니다.

  2. 지속적인 모니터링이 설정되어 있습니까?
    WebPagetest의 개인 인스턴스를 갖는 것은 빠르고 무제한 테스트에 항상 유용합니다. 그러나 Sitespeed, Calibre 및 SpeedCurve와 같은 지속적인 모니터링 도구와 자동 경고를 사용하면 성능에 대한 보다 자세한 그림을 얻을 수 있습니다. 고유한 사용자 타이밍 표시를 설정하여 비즈니스별 메트릭을 측정하고 모니터링합니다. 또한 시간 경과에 따른 변경 사항을 모니터링하기 위해 자동화된 성능 회귀 경고를 추가하는 것이 좋습니다.

    RUM 솔루션을 사용하여 시간 경과에 따른 성능 변화를 모니터링하는 방법을 살펴보십시오. 자동화된 단위 테스트와 유사한 부하 테스트 도구의 경우 스크립팅 API와 함께 k6을 사용할 수 있습니다. 또한 SpeedTracker, Lighthouse 및 Calibre를 살펴보십시오.

빠른 승리

이 목록은 매우 포괄적이며 모든 최적화를 완료하는 데 시간이 꽤 걸릴 수 있습니다. 그렇다면 상당한 개선을 위해 단 1시간이 주어진다면 무엇을 하시겠습니까? 모든 것을 17개의 낮은 행잉 과일 로 요약해 보겠습니다. 분명히 시작하기 전과 끝나면 3G 및 케이블 연결에서 가장 큰 콘텐츠가 포함된 페인트 및 대화형 시간을 포함하여 결과를 측정합니다.

  1. 실제 경험을 측정하고 적절한 목표를 설정하십시오. 가장 빠른 경쟁자보다 최소 20% 더 빠른 것을 목표로 하십시오. 가장 큰 콘텐츠가 포함된 페인트 < 2.5초, 첫 번째 입력 지연 < 100ms, 느린 3G에서 상호 작용 시간 < 5초, 반복 방문의 경우 TTI < 2초 이내로 유지하십시오. 최소한 첫 번째 콘텐츠가 포함된 페인트 및 대화형 시간을 위해 최적화하십시오.
  2. Squoosh, mozjpeg, guetzli, pingo 및 SVGOMG로 이미지를 최적화하고 이미지 CDN으로 AVIF/WebP를 제공합니다.
  3. 주요 템플릿에 대한 중요한 CSS를 준비하고 각 템플릿의 <head> 에 인라인합니다. CSS/JS의 경우 최대 파일 크기 예산 내에서 작동합니다. 170KB gzip(0.7MB 압축 해제).
  4. 스크립트 다듬기, 최적화, 지연 및 지연 로드. 번들러 구성에 투자하여 중복을 제거하고 경량 대안을 확인하십시오.
  5. 항상 정적 자산을 자체 호스팅하고 항상 타사 자산을 자체 호스팅하는 것을 선호합니다. 타사 스크립트의 영향을 제한합니다. 정면을 사용하고 상호 작용 시 위젯을 로드하고 깜박임 방지 스니펫을 조심하십시오.
  6. 프레임워크를 선택할 때 선택하십시오. 단일 페이지 애플리케이션의 경우 중요한 페이지를 식별하고 정적으로 제공하거나 최소한 사전 렌더링하고 구성 요소 수준에서 점진적 수화를 사용하고 상호 작용 시 모듈을 가져옵니다.
  7. 클라이언트 측 렌더링만으로는 성능을 위해 좋은 선택이 아닙니다. 페이지가 많이 변경되지 않으면 미리 렌더링하고 가능한 경우 프레임워크 부팅을 연기합니다. 가능하면 스트리밍 서버 측 렌더링을 사용하십시오.
  8. <script type="module"> 및 module/nomodule 패턴이 있는 레거시 브라우저에만 레거시 코드를 제공합니다.
  9. CSS 규칙을 재그룹화하여 실험하고 본문 내 CSS를 테스트합니다.
  10. 리소스 힌트를 추가하여 더 빠른 dns-lookup , preconnect , prefetch , preloadprerender 로 전송 속도를 높입니다.
  11. 웹 글꼴의 하위 집합을 지정하고 비동기식으로 로드하고 빠른 첫 번째 렌더링을 위해 CSS의 font-display 를 활용합니다.
  12. HTTP 캐시 헤더와 보안 헤더가 올바르게 설정되어 있는지 확인하십시오.
  13. 서버에서 Brotli 압축을 활성화합니다. (불가능하다면 최소한 Gzip 압축이 활성화되어 있는지 확인하십시오.)
  14. 서버가 Linux 커널 버전 4.9 이상에서 실행되는 동안 TCP BBR 혼잡을 활성화하십시오.
  15. 가능한 경우 OCSP 스테이플링 및 IPv6을 활성화합니다. 항상 OCSP 스테이플 DV 인증서를 제공하십시오.
  16. HTTP/2에 대해 HPACK 압축을 활성화하고 사용 가능한 경우 HTTP/3으로 이동합니다.
  17. 서비스 워커 캐시에 글꼴, 스타일, JavaScript 및 이미지와 같은 자산을 캐시합니다.

체크리스트 다운로드(PDF, Apple Pages)

이 체크리스트를 염두에 두고 모든 종류의 프론트 엔드 성능 프로젝트에 대비해야 합니다. 체크리스트의 인쇄 가능한 PDF와 편집 가능한 Apple Pages 문서 를 자유롭게 다운로드하여 필요에 따라 체크리스트를 사용자화하십시오.

  • 체크리스트 PDF 다운로드(PDF, 166KB)
  • Apple Pages에서 체크리스트 다운로드(.pages, 275KB)
  • MS Word에서 체크리스트 다운로드(.docx, 151KB)

대안이 필요한 경우 Dan Rublic의 프런트 엔드 체크리스트, Jon Yablonski의 "Designer's Web Performance Checklist" 및 FrontendChecklist를 확인할 수도 있습니다.

오프 위 고!

일부 최적화는 작업 또는 예산 범위를 벗어나거나 처리해야 하는 레거시 코드를 감안할 때 과도할 수 있습니다. 괜찮아! 이 체크리스트를 일반(그리고 포괄적인) 가이드로 사용하고 상황에 적용되는 문제 목록을 직접 만드십시오. 그러나 가장 중요한 것은 최적화하기 전에 문제를 식별하기 위해 자신의 프로젝트를 테스트하고 측정하는 것입니다. 2021년에도 행복한 공연 결과를 얻으세요 여러분!


Guy Podjarny, Yoav Weiss, Addy Osmani, Artem Denysov, Denys Mishunov, Ilya Pukhalski, Jeremy Wagner, Colin Bendell, Mark Zeman, Patrick Meenan, Leonardo Losoviz, Andy Davies, Rachel Andrew, Anselm Hannemann, Barry Pollard에게 감사드립니다. Hamann, Gideon Pyzer, Andy Davies, Maria Prosvernina, Tim Kadlec, Rey Bango, Matthias Ott, Peter Bowyer, Phil Walton, Mariana Peralta, Pepijn Senders, Mark Nottingham, Jean Pierre Vincent, Philipp Tellis, Ryan Townsend, Ingrid Bergman, Mohamed Hussain SH, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson, Adir Amsalem, Aleksey Kulikov 및 Rodney Rehm은 물론 모든 사람이 사용할 수 있도록 성능 최적화 작업에서 배운 기술과 교훈을 공유한 환상적인 커뮤니티 . 당신은 정말 스매싱입니다!