[javascript] HTML 마크 업에서 <script> 태그를 어디에 두어야합니까?

HTML 문서에 JavaScript를 포함시킬 때 <script>태그와 포함 된 JavaScript 를 넣을 적절한 위치는 어디 입니까? 나는 당신이 <head>섹션에 이것을 배치해서는 안된다는 것을 기억하는 것 같지만 <body>, 페이지가 완전히 렌더링되기 전에 JavaScript를 파싱해야하기 때문에 섹션 의 시작 부분에 배치하는 것도 좋지 않습니다. 이것은 떠날 것으로 보인다 <body>에 대한 논리적 장소로 섹션 <script>태그를.

그렇다면 태그 를 넣을 올바른 장소 어디 <script>입니까?

(이 질문은 참고 문헌 이 질문 은 자바 스크립트 함수 호출에서 이동해야한다고 제안되었던, <a>에 태그 <script>내가 특별히 jQuery를 사용하고 있습니다. 태그하지만,보다 일반적인 답변은 또한 적절한됩니다.)



답변

브라우저가 <script>태그가 있는 웹 사이트를로드하면 어떻게됩니까 ?

  1. HTML 페이지를 가져옵니다 (예 : index.html)
  2. HTML 파싱 시작
  3. 파서가 <script>외부 스크립트 파일을 참조하는 태그를 발견했습니다 .
  4. 브라우저가 스크립트 파일을 요청합니다. 그 동안 파서는 페이지의 다른 HTML 파싱을 차단하고 중지합니다.
  5. 얼마 후 스크립트가 다운로드되어 실행됩니다.
  6. 구문 분석기는 나머지 HTML 문서를 계속 구문 분석합니다.

4 단계는 사용자 경험을 저하시킵니다. 웹 사이트는 기본적으로 모든 스크립트를 다운로드 할 때까지로드를 중지합니다. 사용자가 싫어하는 것이 있다면 웹 사이트가로드되기를 기다리는 것입니다.

왜 이런 일이 발생합니까?

모든 스크립트는 document.write()다른 DOM 조작을 통해 자체 HTML을 삽입 할 수 있습니다 . 이는 파서가 스크립트가 다운로드되어 실행될 때까지 기다려야 문서의 나머지 부분을 안전하게 파싱 할 수 있습니다. 결국, 스크립트 는 문서에 자체 HTML을 삽입했을 있습니다.

그러나 대부분의 JavaScript 개발자 는 문서가로드 되는 동안 더 이상 DOM 조작하지 않습니다 . 대신 문서를로드하기 전에 문서를 수정하기 전에 기다립니다. 예를 들면 다음과 같습니다.

<!-- index.html -->
<html>
    <head>
        <title>My Page</title>
        <script src="my-script.js"></script>
    </head>
    <body>
        <div id="user-greeting">Welcome back, user</div>
    </body>
</html>

자바 스크립트 :

// my-script.js
document.addEventListener("DOMContentLoaded", function() {
    // this function runs when the DOM is ready, i.e. when the document has been parsed
    document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});

브라우저가 my-script.js가 문서를 다운로드하여 실행할 때까지 문서를 수정하지 않는다는 것을 모르기 때문에 파서는 구문 분석을 중지합니다.

낡은 추천

이 문제를 해결하는 기존의 접근 방식 <script>은의 맨 아래에 태그 를 넣는 <body>것이 었습니다. 이는 파서가 끝날 때까지 차단되지 않기 때문입니다.

이 방법에는 자체 문제가 있습니다. 전체 문서를 파싱 할 때까지 브라우저에서 스크립트 다운로드를 시작할 수 없습니다. 큰 스크립트 및 스타일 시트가있는 더 큰 웹 사이트의 경우 가능한 빨리 스크립트를 다운로드 할 수 있어야 성능이 매우 중요합니다. 웹 사이트가 2 초 이내에로드되지 않으면 사람들은 다른 웹 사이트로 이동합니다.

최적의 솔루션에서 브라우저는 가능한 한 빨리 스크립트를 다운로드하기 시작하면서 동시에 나머지 문서를 구문 분석합니다.

현대적인 접근

오늘날 브라우저 는 스크립트 에서 asyncdefer속성을 지원합니다 . 이러한 속성은 스크립트가 다운로드되는 동안 브라우저를 구문 분석하는 것이 안전하다는 것을 브라우저에 알려줍니다.

비동기

<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>

async 속성을 가진 스크립트는 비동기 적으로 실행됩니다. 즉, 스크립트는 다운로드하는 즉시 브라우저를 차단하지 않고 실행됩니다.
이는 스크립트 1보다 먼저 스크립트 2를 다운로드하여 실행할 수 있음을 의미합니다.

http://caniuse.com/#feat=script-async 에 따르면 모든 브라우저의 97.78 %가이를 지원합니다.

연기하다

<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>

defer 속성을 가진 스크립트가 순서대로 실행됩니다 (즉, 첫 번째 스크립트 1, 그런 다음 스크립트 2). 또한 브라우저를 차단하지 않습니다.

비동기 스크립트와 달리 지연 스크립트는 전체 문서가로드 된 후에 만 ​​실행됩니다.

http://caniuse.com/#feat=script-defer 에 따르면 모든 브라우저의 97.79 %가이를 지원합니다. 98.06 %가 최소한 부분적으로 지원합니다.

브라우저 호환성에 대한 중요한 참고 사항 : 일부 상황에서 IE <= 9는 지연된 스크립트를 순서대로 실행할 수 있습니다. 당신이 그 브라우저를 지원해야하는 경우, 읽어 보시기 바랍니다 처음!

결론

현재의 최신 기술은 <head>태그 에 스크립트를 넣고 async또는 defer속성을 사용하는 것입니다. 이를 통해 브라우저를 차단하지 않고도 스크립트를 최대한 빨리 다운로드 할 수 있습니다.

좋은 점은 웹 사이트가 이러한 속성을 지원하지 않는 다른 2 %의 브라우저에서 여전히 98 %의 속도를 유지하면서 올바르게로드되어야한다는 것입니다.


답변

에 표시된대로 닫는 본문 태그 바로 앞에

http://developer.yahoo.com/performance/rules.html#js_bottom

스크립트를 맨 아래에 놓으십시오

스크립트로 인한 문제는 병렬 다운로드를 차단한다는 것입니다. HTTP / 1.1 사양은 브라우저가 호스트 이름 당 2 개 이하의 구성 요소를 동시에 다운로드 할 것을 제안합니다. 여러 호스트 이름에서 이미지를 제공하는 경우 두 개 이상의 다운로드가 동시에 발생할 수 있습니다. 그러나 스크립트를 다운로드하는 동안 브라우저는 다른 호스트 이름에서도 다른 다운로드를 시작하지 않습니다.


답변

비 차단 스크립트 태그는 다음과 같은 곳에 배치 할 수 있습니다.

<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
  • async 스크립트는 사용 가능한 즉시 비동기식으로 실행됩니다
  • defer 문서 파싱이 끝나면 스크립트가 실행됩니다.
  • async defer 비동기가 지원되지 않으면 스크립트가 지연 동작으로 폴백

이러한 스크립트는 문서 준비 후 / 비동기 적으로 실행되므로 다음을 수행 할 수 없습니다.

<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
  * might throw "jQuery is not defined" error
  * defer will not work either
-->

아니면 이거:

<script src="document.write(something).js" async></script>
<!--
  * might issue "cannot write into document from an asynchronous script" warning
  * defer will not work either
-->

아니면 이거:

<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
  * might throw "jQuery is not defined" error (no guarantee which script runs first)
  * defer will work in sane browsers
-->

아니면 이거:

<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
  * might not locate #header (script could fire before parser looks at the next line)
  * defer will work in sane browsers
-->

그러나 비동기 스크립트는 다음과 같은 장점을 제공합니다.

  • 리소스의 병렬 다운로드 :
    브라우저는 스크립트가 다운로드되어 실행될 때까지 기다리지 않고도 스타일 시트, 이미지 및 기타 스크립트를 병렬로 다운로드 할 수 있습니다.
  • 소스 순서 독립성 :
    차단에 대해 걱정하지 않고 스크립트를 헤드 나 바디에 배치 할 수 있습니다 (CMS를 사용하는 경우 유용). 그래도 실행 순서는 중요합니다.

콜백을 지원하는 외부 스크립트를 사용하여 실행 순서 문제를 피할 수 있습니다. 많은 타사 JavaScript API는 이제 비 차단 실행을 지원합니다. 다음은 Google Maps API를 비동기 적 으로 로드 하는 예입니다 .


답변

야후! 뛰어난 성능 팀은 <script>태그를 문서 본문의 끝에 배치 하여 페이지 렌더링을 차단하지 않는 것입니다.

그러나 Google 웹 로그 분석 자바 스크립트 파일의로드 시간에 대한 이 답변 에 설명 된 것처럼 더 나은 성능을 제공하는 몇 가지 새로운 방법이 있습니다 .

Steve Souders (클라이언트 측 성능 전문가)의 다음과 같은 훌륭한 슬라이드 가 있습니다.

  • 외부 JavaScript 파일을 병렬로로드하는 다양한 기술
  • 로딩 시간 및 페이지 렌더링에 미치는 영향
  • 브라우저에 표시되는 “진행 중”표시기 (예 : 상태 표시 줄에 ‘로드 중’, 모래 시계 마우스 커서)

답변

JQuery를 사용 $(document).ready()하는 경우 가장 좋은 곳에 자바 스크립트를 배치하고 함수를 실행하기 전에 항목이 올바르게로드되는지 확인하십시오.

참고 사항 : <head>섹션의 모든 스크립트 태그 가 가장 깨끗한 위치 인 것처럼 보입니다.


답변

2019 년의 최신 접근 방식은 ES6 모듈 유형 스크립트를 사용하는 것 입니다.

<script type="module" src="..."></script>

기본적으로 모듈은 비동기 적으로로드되고 지연됩니다. 즉, 어느 곳에 나 배치 할 수 있으며 페이지로드가 끝나면 병렬로로드되어 실행됩니다.

스크립트와 모듈의 차이점은 다음과 같습니다.

https://stackoverflow.com/a/53821485/731548

스크립트와 비교 한 모듈 실행은 다음과 같습니다.

https://developers.google.com/web/fundamentals/primers/modules#defer

지원은 다음과 같습니다.

https://caniuse.com/#feat=es6-module


답변

스크립트가 head 요소 이외의 다른 곳에 있으면 XHTML은 유효성을 검사하지 않습니다. 그것은 어디에나있을 수 있습니다.

jQuery와 같은 것을 사용하여 실행을 연기 할 수 있으므로 구문 분석 중 약간의 성능 저하를 제외하고는 위치에 관계가 없습니다.