>웹 프론트엔드 >JS 튜토리얼 >스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석

스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석

高洛峰
高洛峰원래의
2016-12-03 13:51:061078검색

1. 서문

선배들이 작성한 코드는 다음과 같습니다

<script src="#link("xxxx/xx/home/home.js")" type="text/javascript" async defer></script>

실제로는 비동기와 비동기가 모두 있습니다. 그것은 선배 운전자의 일종의 검은 기술일 것이고 두 사람 사이에 어떤 마법의 화학반응이 일어날 것이 틀림없다고 생각하여, 나는 경건한 마음으로 서둘러 책과 문서를 뒤져 살펴보았다. 먼저 각각의 정의를 알아보세요.

2. 조사해 보세요

먼저 async 및 defer의 정의를 살펴보겠습니다. Red Book Telescope를 열면 이것이 소개입니다

2.1 defer

이 속성의 목적은 스크립트가 실행될 때 페이지 구조에 영향을 미치지 않음을 나타내는 것입니다. 즉, 스크립트는 실행되기 전에 전체 페이지가 구문 분석될 때까지 지연됩니다. 따라서 <script> 요소에 defer 속성을 설정하는 것은 브라우저에 즉시 다운로드하고 실행을 지연시키라고 지시하는 것과 같습니다. </script>

HTML5 사양에서는 스크립트가 나타나는 순서대로 실행되도록 요구하므로 첫 번째 지연된 스크립트가 두 번째 지연된 스크립트보다 먼저 실행되고 이 두 스크립트는 DOMContentLoaded 이벤트 전에 실행됩니다. 실제로 지연 스크립트는 반드시 순서대로 실행되는 것은 아니며 DOMContentLoad 시간이 트리거되기 전에 반드시 실행되는 것도 아니므로 지연 스크립트를 하나만 포함하는 것이 가장 좋습니다.

2.2 async

이 속성은 defer와 유사하며 스크립트 처리 동작을 변경하는 데 사용됩니다. 또한 지연과 유사하게 비동기는 외부 스크립트 파일에서만 작동하며 브라우저에 파일을 즉시 다운로드하도록 지시합니다. 그러나 지연과 달리 비동기로 표시된 스크립트는 순서대로 실행된다는 보장이 없습니다.

두 번째 스크립트 파일은 첫 번째 스크립트 파일보다 먼저 실행될 수 있습니다. 따라서 두 가지가 서로 종속되지 않도록 하는 것이 중요합니다. async 속성을 지정하는 목적은 페이지가 두 스크립트가 다운로드되어 실행될 때까지 기다리지 않도록 하여 페이지의 다른 콘텐츠를 비동기적으로 로드하는 것을 방지하는 것입니다.

요약하면 이 두 속성을 사용하면 스크립트 태그가 비동기적으로 로드되지만 실행 시점은 다릅니다. Segmentfault에 대한 답변의 그림 인용

스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석

파란색 선은 네트워크 읽기를 나타내고 빨간색 선은 실행 시간을 나타내며 둘 다 스크립트용입니다. HTML 구문 분석을 나타냅니다. .

즉, async가 순서가 맞지 않는 반면 defer는 순차적으로 실행되므로 다른 스크립트에 의존하지 않는 Baidu Analytics 또는 Google Analytics와 같은 라이브러리에는 async가 더 적합하다고 판단됩니다. 그림에서 볼 수 있듯이 일반 <script> 태그의 로드 및 구문 분석은 DOM 렌더링을 차단합니다. 이것이 바로 <body> 첫째, 리소스 로딩으로 인한 장기간의 흰색 화면을 방지하기 위해 js가 DOM 작업을 수행할 수 있으므로 모든 DOM이 렌더링된 후에 실행되어야 한다는 점도 또 다른 이유입니다. </script>

2.3 정말요?

그러나 이 그림(Baidu에서 찾은 거의 유일한 답변)은 표준적인 상황일 뿐이며 대부분의 브라우저는 이를 구현할 때 최적화를 수행합니다.

크롬이 어떤 일을 하는지 살펴보자. URL에 해당하는 웹페이지.

2. 로더는 네트워크 모듈을 사용하여 연결을 설정하고 요청을 보내고 응답을 받습니다.


3. WebKit은 다양한 웹 페이지나 리소스로부터 데이터를 수신하며, 그 중 일부는 동기식 또는 비동기식으로 얻을 수 있습니다.


4. 웹페이지가 HTML 인터프리터에게 넘겨져 일련의 단어(토큰)로 변환됩니다.


5. 인터프리터는 단어를 기반으로 노드(Node)를 구축하여 DOM 트리를 형성합니다.


6. 노드가 자바스크립트 코드인 경우 자바스크립트 엔진을 호출하여 해석하고 실행합니다.


7. JavaScript 코드는 DOM 트리의 구조를 수정할 수 있습니다.


8. 노드가 이미지, CSS, 비디오 등과 같은 다른 리소스에 의존해야 하는 경우 리소스 로더를 호출하여 로드하지만 비동기식이므로 지속적인 작업을 방해하지 않습니다. 현재 DOM 트리 생성 JavaScript 리소스 URL(비동기로 표시되지 않음)인 경우 생성을 계속하기 전에 JavaScript 엔진이 JavaScript 리소스를 로드하고 실행할 때까지 현재 DOM 트리 생성을 중지해야 합니다. DOM 트리.


따라서 일반적으로 Chrome 브라우저는 먼저 HTML 문서를 요청한 다음 그 안의 다양한 리소스에 대해 해당 리소스 로더를 호출하여 비동기 네트워크 요청을 수행하는 동시에 DOM 렌더링을 수행합니다. <script> 태그를 만날 때까지 기본 프로세스는 렌더링을 중지하고 리소스가 로드될 때까지 기다린 다음 V8 엔진을 호출하여 js를 구문 분석한 다음 DOM 구문 분석을 계속합니다. 제가 이해한 바에 따르면 async 속성을 추가하는 것은 독립적으로 로드하고 실행하기 위해 별도의 프로세스를 여는 것과 같고, defer는 <body> 하단에 <script>를 배치하는 것과 같은 효과가 있습니다. <p><br/>3. 실험 1<p>3.1 데모<p><br/>위의 결론을 검증하기 위해 테스트해 보겠습니다<p> <p> <pre class="brush:html;toolbar:false">&lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; &lt;meta charset=&quot;UTF-8&quot;&gt; &lt;title&gt;Document&lt;/title&gt; &lt;link href=&quot;http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.css&quot; rel=&quot;stylesheet&quot;&gt; &lt;link href=&quot;http://cdn.staticfile.org/foundation/6.0.1/css/foundation.css&quot; rel=&quot;stylesheet&quot;&gt; &lt;script src=&quot;http://lib.sinaapp.com/js/angular.js/angular-1.2.19/angular.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;http://libs.baidu.com/backbone/0.9.2/backbone.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;http://libs.baidu.com/jquery/2.0.0/jquery.js&quot;&gt;&lt;/script&gt; &lt;/head&gt; &lt;body&gt; ul&gt;li{这是第$个节点}*1000 &lt;/body&gt; &lt;/html&gt;</pre><p>다양한 CDN의 CSS 2개와 JS 3개를 참조하여 본문에 1000li를 생성하는 간단한 데모입니다. 외부 참조 리소스의 위치를 ​​조정하고 관련 속성을 추가하여 Chrome의 타임라인을 사용하여 확인하세요. <p>3.2 <p><img src="https://img.php.cn//upload/image/696/384/898/1480744154246530.jpg" title="1480744154246530.jpg" alt="스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석"/><p>에 배치하면 리소스가 비동기적으로 로드되지만 <body>의 렌더링이 차단되고 흰색 화면이 나타납니다. 주문 즉시 <p>3.3 스크립트를 실행하여 <body> <p><img src="https://img.php.cn//upload/image/639/130/331/1480744171245752.jpg" title="1480744171245752.jpg" alt="스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석"/><p> 리소스를 비동기적으로 로드하고 < body>를 렌더링하고 로드 버튼을 클릭합니다. JS를 순차적으로 실행<p>3.3 <head> 헤더에 배치하고 async<p><img src="https://img.php.cn//upload/image/392/809/508/1480744186346776.jpg" title="1480744186346776.jpg" alt="스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석"/>를 사용하여 리소스를 로드합니다. 로드 후 즉시 JS 리소스를 실행하며 순서대로 진행되며 더 빠른 사람이 먼저 실행됩니다<p>3.4 <head> 헤드에 배치하고 defer<p><p><img src="https://img.php.cn//upload/image/414/954/733/1480744198930605.jpg" title="1480744198930605.jpg" alt="스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석"/> DOM 렌더링 후 리소스를 비동기적으로 로드한 다음 JS<p>3.5를 순서대로 실행하고 <head> 헤드에 배치한 후 async와 defer를 동시에 사용합니다<p> <p><img src="https://img.php.cn//upload/image/312/914/529/1480744214244130.jpg" title="1480744214244130.jpg" alt="스크립트 태그의 지연 및 비동기 속성에 대한 간략한 분석"/>성능은 async, open a와 일치하며 오버레이 효과가 있는지 확인하기 위해 상상력을 사용하여 이 두 속성의 위치를 ​​교환했습니다. = =, <p> 요약하자면, 웹킷 엔진에서는 여전히 Baidu Google과 같은 독립 라이브러리를 사용해야 하는 경우 <script>를 작성하는 것이 좋습니다. Analytics 또는 Buliuzi의 경우 <script> 태그를 <head> 헤더에 작성해야 하는 경우 defer 속성을 사용할 수 있습니다. <p> <p> 그럼 선배들의 심리를 파악해보고, 동시에 쓰는 이유는 무엇인지, 호환성은 무엇인지 <br/>caniuse, async를 사용 IE<=9에서는 지원하지 않지만, 다른 브라우저는 괜찮습니다. 연기는 IE<=9에서 지원되지만 버그가 있을 수 있으며 다른 브라우저는 괜찮습니다. 이 문제는 "Telescope"가 연기 이유를 하나만 권장하는 이유입니다. 따라서 비동기가 지원되지 않는 경우 연기를 활성화하도록 두 속성이 모두 지정되지만 경우에 따라 연기에는 여전히 버그가 있습니다. <p>비동기 속성이 지정된 경우에도 지연 속성을 지정하여 비동기만 지원하고 비동기를 지원하지 않는 레거시 웹 브라우저가 동기식 차단 동작 대신 지연 동작으로 대체되도록 할 수 있습니다. default.<p>5. 결론<p><p>사실 가장 안전한 방법은 <body> 하단에 <script>를 쓰는 것입니다. 화면 문제, 실행 순서 문제 없음, 편히 쉬세요. 지연 및 비동기를 건드리지 마세요~<br/>현재는 Chrome 웹킷의 렌더링 메커니즘만 연구했는데, Firefox 및 IE는 계속해야 합니다. 연구, 사진, CSS 및 기타 외부 리소스 렌더링에 대한 연구는 계속 진행 중입니다. <p><p></script>
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.