브라우저의 HTML 렌더링을 막는 것
렌더링 블록의 원인이 되는 리소스를 블록 리소스(Block resource) 라고 한다.
블록 리소스는 브라우저의 렌더링 과정을 지연시킨다.
JS는 DOM 트리와 CSSOM 트리를 변경할 수 있기 때문에 HTML 파싱 중 인라인 <script>
태그를 만나면 로딩 및 실행이 완료될 때 까지 DOM 트리 생성을 중단 한다.
일반적으로 사용하는 아래 방식은 HTML 파싱을 막지 않으며 JS 코드에서도 완성된 DOM 트리에 접근한다.
<script src="./script.js"></script>
크기가 큰 HTML 문서의 최하단에 <script>
태그가 있을 시 스크립트를 다운하고 실행까지 시간이 지연될 수 있다.
백그라운드에서 스크립트를 다운한다. 다운이 완료되면 DOMContentLoaded
이벤트 발생전에 실행한다.
DOMContentLoaded
이벤트는 브라우저가 HTML을 모두 파싱하여 DOM 트리 구성을 완료하였을때 발생
스타일 시트나 이미지와 같은 자원들의 로딩은 기다리지 않는다.
백그라운드에서 다운되기 때문에 로딩시간을 빠르게 줄일 수 있고 HTML 파싱을 막지 않는다. DOM트리가 완성된 후 실행되기 때문에 DOM요소에 접근이 가능하다. 여러 개인 경우 순서대로 실행한다.
defer와 유사하게 HTML 파싱을 막지 않으며 백그라운드에서 다운하나, 다운이 완료되면 바로 실행한다.
이때 실행이 끝날 때 까지 HTML 파싱을 멈춘다.
다운완료 시점에 실행 순서가 결정되므로 의존성이 있는 스크립트 들이 있다면 사용에 주의해야 한다.
실행시점이 예측 불가능 하거나 의존성이 있거나, 이벤트 발생 시점과 연관이 있다면 사용을 피해야 한다.
독립적인 역할을 하는 스크립트에서만 사용하는 것 이 좋다.
브라우저는 렌더링을 하기 위해 렌더 트리를 구성한다. 이때 DOM과 CSSOM 트리를 구성하는데, CSSOM은 CSS를 모두 파싱한 후 구성이 가능하다. 구성에 문제가 생긴다면 렌더 트리를 구성하지 못하고 렌더링이 차단된다.
렌더링 블록을 막기 위한 추천 방식
<style type="text/css">
@import url("./style.css");
</style>
@import url("style-header.css");
@import url("style-main.css");
@import url("style-footer.css");
@import url("style-sidebar.css");
@import
는 다른 스타일 시트의 스타일 규칙을 가져올 수 있는 규칙이다. 코드의 간결함 등을 위해서는 바람직하지만 성능적인 측면에서는 좋은 방법이 아니다.
@import
를 사용하여 시트를 가져올 때 병렬로 다운로드 할 수 없기 때문 이다.
그럼 그 시간만큼 렌더링 프로세스는 지연이 되게 된다.
위 @import
방식에 대한 해결 방법이다.
여러 CSS를 추가할 때 link
태그로 추가하는 것
번들러를 통하여 CSS 파일을 합치거나 필요한 상황에서만 로딩되게 최적화가 필요하다.
inline css 방식은 HTML 문서에 직접 삽입하는 방식이라 파싱을 빠르게 할 수 있다.(요청이 줄어들기 때문)
하지만 용량이 크다면 그만큼 또 지연을 일으킬 수 있다. 그리고 캐시가 되지 않는다.
초기 뷰포트 영역에 필요한 CSS만 추출하여 inline CSS에 삽입하는 방식
이 방식은 모든 CSS를 초기에 로딩하지 않아도 되며, 이로 인해 렌더링 시간이 단축된다.
나머지 CSS 파일은 비동기로 로딩한다.
HTTP2의 서버 푸시는 클라이언트에서 사용하는 리소스를 미리 알고 전송해주는데 critical CSS가 존재한다면 파싱하는 시간으로 렌더링이 더 느려진다.
critical css generator 혹은 플러그인/라이브러리 쉽게 추출이 가능하다.
단, 같은 사이트여도 페이지 마다 생김새가 다르며 그로 인하여 critical css의 범위도 달라진다. 최대한 넓은 폭으로 css 선정해야 한다. 최대한 여러 페이지에서 추출하며 선정하여야 한다.
참고