블로그 성능 개선 (리소스 로딩)
작성일: 2023-10-23Prerequisite
- 블로그 성능 분석
이번에는 리소스 로딩에 따른 Rednering Blocking 개선을 진행해보겠습니다.
현재 블로그의 리소스 로딩 순서는 아래와 같습니다.
_includes/head.html
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="google-site-verification" content="3gB9dKJy3OEOfBDFjyygUv7UEtbCLSaSsj1iRgGMLqM" />
<meta name="naver-site-verification" content="3c1362974d453b6fe1fdd5089325e29980b1369e" />
{% include_cached favicon.html %}
<link id="main-css" rel="stylesheet" href="{{ '/assets/css/just-the-docs-light.css' | relative_url }}">
<script src="{{ '/assets/js/vendor/lunr.min.js' | relative_url }}"></script>
<script src="{{ '/assets/js/vendor/lunr.stemmer.support.min.js' | relative_url }}"></script>
<script src="{{ '/assets/js/vendor/lunr.multi.min.js' | relative_url }}"></script>
<script src="{{ '/assets/js/vendor/lunr.ko.min.js' | relative_url }}"></script>
<script src="{{ '/assets/js/fslightbox.js' | relative_url }}"></script>
<script src="{{ '/assets/js/lazysizes.min.js' | relative_url }}"></script>
<script src="{{ '/assets/js/just-the-docs.js' | relative_url }}"></script>
{%- if site.ga_tracking != nil %}
{% assign ga_tracking_ids = site.ga_tracking | split: "," %}
<script src="https://www.googletagmanager.com/gtag/js?id={{ ga_tracking_ids.first }}"></script>
{%- endif %}
{% seo %}
</head>
다행히 리소스 파일 사이즈가 작아 빠르게 불러오지만 lighthouse 분석 결과 문제가 된다고 알려주고 있습니다.
defer
- 스크립트 로드가 완료되어도 HTML 파싱 완료 후에 스크립트 실행
- 스크립트 태그가 여러개 있으면 선언한 순서대로 실행
async
- 스크립트 로드 완료 후 HTML 파싱이 중단되고 스크립트 실행
- 스크립트 태그가 여러개 있으면 로드한 순서대로 실행 (순서를 보장할 수 없음)
저의 블로그 특성 상 HTML 파싱이 완료된 후에 스크립트가 실행되어도 상관없어 스크립트에 defer 속성을 추가하여 HTML 파싱 후 스크립트가 실행되도록 변경했습니다.
추가로 google tag manager 스크립트는 tag 생성 로직이 함께 포함되야 하므로 가독성을 위해 just-the-docs 스크립트 안에 넣어서 함께 처리했습니다.
_includes/head.html
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="google-site-verification" content="3gB9dKJy3OEOfBDFjyygUv7UEtbCLSaSsj1iRgGMLqM" />
<meta name="naver-site-verification" content="3c1362974d453b6fe1fdd5089325e29980b1369e" />
{% include_cached favicon.html %}
<link id="main-css" rel="stylesheet" href="{{ '/assets/css/just-the-docs-light.css' | relative_url }}">
<script defer src="{{ '/assets/js/vendor/lunr.min.js' | relative_url }}"></script>
<script defer src="{{ '/assets/js/vendor/lunr.stemmer.support.min.js' | relative_url }}"></script>
<script defer src="{{ '/assets/js/vendor/lunr.multi.min.js' | relative_url }}"></script>
<script defer src="{{ '/assets/js/vendor/lunr.ko.min.js' | relative_url }}"></script>
<script defer src="{{ '/assets/js/fslightbox.js' | relative_url }}"></script>
<script defer src="{{ '/assets/js/lazysizes.min.js' | relative_url }}"></script>
<script defer src="{{ '/assets/js/just-the-docs.js' | relative_url }}"></script>
{% seo %}
</head>
assets/js/just-the-docs.js
function tagManager() {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{% for ga_property in ga_tracking_ids %}
gtag('config', '{{ ga_property }}'{% unless site.ga_tracking_anonymize_ip == nil %}, { 'anonymize_ip': true }{% endunless %});
{% endfor %}
}
function loadScript(url) {
return new Promise((resolve, reject) => {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.defer = true;
script.onload = resolve;
script.onerror = () => reject(`스크립트 로드 중에 오류가 발생했습니다: ${url}`);
document.head.appendChild(script);
});
}
jtd.onReady(function(){
initNav();
...
{%- if site.ga_tracking != nil %}
{% assign ga_tracking_ids = site.ga_tracking | split: "," %}
loadScript('https://www.googletagmanager.com/gtag/js?id={{ ga_tracking_ids.first }}')
tagManager();
{%- endif %}
window.onload = setTimeout(() => {
document.querySelectorAll(".skeleton_loading").forEach(element => {
element.classList.toggle("fade")
})
}, 300)
});
변경 후 스크립트 실행이 지연된 것을 확인하였고, 성능 점수도 좋아진 것을 확인했습니다.
Reference
[HTML] script 태그의 위치와 defer, async 속성
https://www.inflearn.com/course/lecture?courseSlug=인프콘2023-다시보기&unitId=177896&tab=curriculum