Post
JS) 효율적으로 script를 fetch하는 방법
HTML을 parsing 하는 중 script 태그에서 효율적으로 fetching 후 실행하는 방법은 과연 무엇일까?
1) Head 태크 하단의 script 태그
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="main.js></script>
</head>
<body>
</body>
</html>
일반적인 방법으로 head 태그의 밑에서 js파일을 다운 받는다면 어떻게 될까?
-
브라우저가 한 줄씩 태그들을 분석한다.
-
CSS와 병합하여 DOM 요소들로 변환한다.
-
script 태그가 보이면 자바스크립트 파일을 다운 받는다(이때 parsing은 잠시 멈춘다)
-
자바스크립트 파일이 실행된다.(이때 parsing은 잠시 멈춘다)
-
HTML parsing이 계속된다.
단점 : JS 파일 용량이 크다면 fetching 및 사용자가 완성된 페이지를 보는데 시간이 오래 걸린다.
2) body 태크 제일 하단의 script 태그
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div></div>
<script src="main.js></script>
</body>
</html>
- 브라우저가 HTML 태그들을 다 parsing 한 후 script 파일을 다운받아 실행한다.
장점 : JS 파일을 다 fetching 하기 전 페이지를 볼 수 있다.
단점 : : JS파일을 다운 받기 전까지 페이지가 제대로 실행되지 않는다.
(DOM과 연동되는 JS코드가 필요하다면, parsing이 완료 되어도 JS코드가 없으니 실행이 안된다! )
3) script 태그 + async
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script asyn src="main.js></script>
</head>
<body>
</body>
</html>
(asyn는 boolean 값이므로 선언하는 것만으로도 true로 설정되어 사용할 수 있다)
-
HTML을 parsing 하다가 asyn를 만나면 병렬로 js파일을 다운(이떄 HTML parsing은 잠시 중단) - 실행한다.
-
이후 HTML parsing을 계속 한다.
장점 : parsing을 하면서 fetching을 할 수 있기 때문에 다운로드 받는 시간을 줄일 수 있다.
단점
-
자바스크립트가 HTML이 parsing 되기 전에 실행되기 때문에 자바스크립트에서 querySelector를 통해 DOM 요소를 조작해야 한다면? 에러위험이 있다.
-
js 파일을 fetching 및 exectuing 하는 동안 HTML parsing이 blocked 되기 때문에 사용자가 페이지를 보는데 시간이 걸린다.
4) script 태그 + defer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script defer src="main.js></script>
</head>
<body>
</body>
</html>
-
HTML parsing을 하다가 defer을 만나면 JS를 fetching하면서 HTML parsing 계속된다.
-
HTML parsing이 끝난 이후 executing이 된다.
async와 defer
async가 여러개 있다면, 정의된 순서가 아닌 다운로드 순서대로 실행된다.
(만약 b.js 전에 a.js가 실행되어야 한다면 에러가 발생할 수 있다)
defer은 parsing 하는 동안 필요한 JS 파일을 다 fetching해둔다.
parsing이 끝난 이후, 스크립트 순서대로 js 파일이 실행된다.
참고 : https://www.youtube.com/watch?v=tJieVCgGzhs (드림코딩 엘리 유튜브 영상)