머리말
현재 JavaScript 코드가 포함되어 있는지 또는 외부 링크 파일에 있든, 페이지의 다운로드 및 렌더링을 중지하고 스크립트가 실행될 때까지 기다려야합니다. JavaScript 실행 프로세스가 길어질수록 브라우저가 사용자 입력에 대한 응답을 기다리는 시간이 길어집니다. 스크립트를 다운로드하고 실행할 때 브라우저가 차단하는 이유는 스크립트가 페이지 또는 JavaScript의 네임 스페이스를 변경하여 다음 페이지의 내용에 영향을 줄 수 있기 때문입니다. 일반적인 예는 페이지에서 Listing 1과 같은 document.write() 사용하는 것입니다.
목록 1 JavaScript 코드 임베디드 예제
<html> <head> <title> 소스 예제 </title> </head> <body> <p> <script type = "text/javaScript"> document.write ( "오늘은" + (new date ()). Todatestring ()); </script> </p> </body> </html>
브라우저에서 <cript> 태그가 발생하면 현재 HTML 페이지는 javaScript가 <P> 태그에 컨텐츠를 추가하거나 다른 요소를 소개하거나 태그를 제거할지 여부를 알 수있는 방법이 없습니다. 따라서 현재 브라우저는 페이지 처리를 중지하고 먼저 JavaScript 코드를 실행 한 다음 계속 구문 분석하고 페이지를 렌더링합니다. SRC 속성을 사용하여 JavaScript를로드 할 때도 마찬가지입니다. 브라우저는 먼저 외부 링크 파일에서 코드를 다운로드 한 다음 구문 분석하고 실행해야합니다. 이 과정에서 페이지 렌더링 및 사용자 상호 작용이 완전히 차단됩니다.
스크립트 위치
HTML 4 사양에 따르면 <cript> 태그는 HTML 문서의 <head> 또는 <body>에 배치 될 수 있으며 여러 번 나타날 수 있습니다. 웹 개발자는 일반적으로 <head>에 외부 링크 JavaScript를로드 한 다음 <link> 태그를 사용하여 외부 링크 CSS 파일 또는 기타 페이지 정보를로드합니다. 예를 들어, 목록 2
비효율적 인 스크립트 위치의 예 2 예
<html> <head> <title> 소스 예제 </title> <script type = "text/javaScript"src = "script1.js"> </script> <script> <script> <text/javaScript "src ="script2.js "> </script> <script> <script"src = "script2.js"> type = "text/javaScript"src = "script3.js"> </script> <link rel = "stylesheet"type = "text/css"href = "styles.css"> </head> <body> <p> Hello World! </p> </body> </html>
그러나이 기존의 접근 방식은 심각한 성능 문제를 숨 깁니다. 목록 2의 예에서 브라우저가 <cript> 태그 (라인 4)를 구문 분석 할 때 브라우저는 후속 컨텐츠를 구문 분석하는 것을 중지하고 스크립트 파일 다운로드 및 코드 실행을 우선 순위로 삼아 후속 Styles.css 스타일 파일이나 <body> 태그를로드 할 수 없습니다. <body> 태그를로드 할 수 없으므로 페이지는 자연스럽게 렌더링되지 않습니다. 따라서 JavaScript 코드가 완전히 실행될 때까지 페이지가 비어 있습니다. 그림 1은 페이지로드하는 동안 스크립트 및 스타일 파일의 다운로드 프로세스를 설명합니다.
그림 1 JavaScript 파일의로드 및 실행을 차단하여 다른 파일의 다운로드
흥미로운 현상을 찾을 수 있습니다. 첫 번째 JavaScript 파일이 다운로드를 시작하고 페이지에서 다른 파일의 다운로드를 차단합니다. 또한 script1.js 다운로드가 완료되고 script2.js가 다운로드를 시작하기 전에 지연이 있습니다. 이는 Script1.js 파일의 실행 프로세스입니다. 각 파일은 다운로드를 시작하기 전에 이전 파일이 다운로드 및 실행 될 때까지 기다려야합니다. 이 파일을 하나씩 다운로드하는 동안 사용자는 빈 페이지를 봅니다.
IE 8, Firefox 3.5, Safari 4 및 Chrome 2부터 모두 JavaScript 파일을 병렬로 다운로드 할 수 있습니다. <cript> 태그가 외부 리소스를 다운로드 할 때 다른 <cript> 태그를 차단하지 않기 때문에 좋은 소식입니다. 불행히도 JavaScript 다운로드 프로세스는 스타일 파일 및 이미지와 같은 다른 리소스의 다운로드를 여전히 차단합니다. 스크립트 다운로드 프로세스는 서로 영향을 미치지 않지만 페이지는 여전히 모든 JavaScript 코드를 다운로드하여 실행하기 전에 기다려야합니다. 따라서 최신 브라우저는 병렬 다운로드를 허용하여 성능을 향상 시키지만 문제가 완전히 해결되지 않았으며 스크립트 차단은 여전히 문제입니다.
스크립트는 페이지에서 다른 리소스의 다운로드를 차단하므로 전체 페이지 다운로드에 미치는 영향을 최소화하기 위해 <body> 태그 하단에 모든 <cript> 태그를 배치하는 것이 좋습니다. 예를 들어, 목록 3
목록 3 권장 코드 배치의 예
<html> <head> <title> 소스 예제 </title> <link rel = "stylesheet"type = "text/css"href = "styles.css"> </head> <pody> <p> hello world! </p> <!-효율적인 스크립트 포지셔닝-> <script> script "src ="script ""Script1의 예제 ". type = "text/javaScript"src = "script2.js"> </script> src = "script3.js"> </script> </body> </html>
이 코드는 HTML 문서에 <cript> 태그를 배치하는 권장 위치를 보여줍니다. 스크립트 다운로드는 다른 스크립트를 차단하지만 대부분의 페이지가 사용자에게 다운로드되어 표시되었으므로 페이지 다운로드는 너무 느리게 나타나지 않습니다. 이것은 JavaScript를 최적화하기위한 첫 번째 규칙입니다. 스크립트를 맨 아래에 놓습니다.
스크립트를 구성하십시오
페이지가 처음 다운로드 될 때 각 <cript> 태그가 차단되므로 페이지에 포함 된 <cript> 태그 수를 줄이면이 상황을 개선하는 데 도움이됩니다. 이는 외부 링크 스크립트뿐만 아니라 임베디드 스크립트 수에 대한 것입니다. HTML 페이지를 구문 분석하는 동안 브라우저에서 <cript> 태그가 발생할 때마다 스크립트 실행으로 인해 특정 지연이 발생하므로 지연 시간을 최소화하면 페이지의 전체 성능이 크게 향상됩니다.
이 문제는 외부 JavaScript 파일을 처리 할 때 약간 다릅니다. HTTP 요청의 추가 성능 오버 헤드가 주어지면 단일 100KB 파일을 다운로드하는 것이 520KB 파일을 다운로드하는 것보다 빠릅니다. 즉, 페이지에서 외부 링크 스크립트 수를 줄이면 성능이 향상됩니다.
일반적으로 큰 웹 사이트 나 응용 프로그램은 여러 JavaScript 파일에 의존해야합니다. 성능 소비를 줄이기 위해 <cript> 태그 만 참조하면 여러 파일을 하나로 병합 할 수 있습니다. 오프라인 포장 도구 또는 실시간 온라인 서비스를 통해 파일 병합을 달성 할 수 있습니다.
외부 링크 스타일 시트를 참조한 후 임베디드 스크립트를 넣으면 페이지가 차단되어 스타일 시트가 다운로드 될 때까지 기다릴 수 있습니다. 이는 임베디드 스크립트가 실행될 때 가장 정확한 스타일 정보를 얻을 수 있도록하기 위해 수행됩니다. 따라서 <link> 태그 직후에 포함 된 스크립트를 따르지 않는 것이 좋습니다.
비 블로킹 스크립트
기능이 풍부한 웹 애플리케이션 또는 대형 웹 사이트에서 JavaScript 파일 크기를 줄이고 HTTP 요청을 제한하는 것이 항상 가능하지는 않습니다. 웹 애플리케이션 기능이 많을수록 JavaScript 코드가 많을수록 필요합니다. 단일 더 큰 JavaScript 파일을 다운로드하면 HTTP 요청 만 한 번만 생성되지만 오랫동안 브라우저를 잠그게됩니다. 이를 피하려면 일부 특정 기술을 통해 JavaScript 파일을 페이지에 점차적으로로드하여 어느 정도 브라우저를 차단하지 않도록해야합니다.
차단 해제 스크립트의 비밀은 페이지가로드 된 후에 만 JavaScript 코드가로드된다는 것입니다. 즉, 창 객체의 온부하 이벤트가 발생한 후 스크립트를 다운로드하는 것을 의미합니다. 이 효과를 달성하는 방법에는 여러 가지가 있습니다.
로드 스크립트 지연
html 4는 <cript> 태그 : DEFER의 확장 속성을 정의합니다. DEFER 속성은이 요소에 포함 된 스크립트가 DOM을 수정하지 않으므로 코드가 실행을 안전하게 지연시킬 수 있음을 나타냅니다. DEFER 속성은 IE 4 및 Firefox 3.5 이후 브라우저에서만 지원되므로 이상적인 크로스 브라우저 솔루션이 아닙니다. 다른 브라우저에서는 DEFER 속성이 직접 무시되므로 <Script> 태그는 기본 방식으로 처리되므로 막힘이 발생합니다. 그러나 대상 브라우저가 지원하는 경우에도 여전히 유용한 솔루션입니다. 목록 4가 예입니다
Listing 4 지연 속성 사용 방법의 예
<script type = "text/javaScript"src = "script1.js"defer> </script>
연기 속성이있는 <cript> 태그는 문서의 어느 곳에도 배치 할 수 있습니다. 해당 JavaScript 파일은 페이지가 <cript> 태그에 구문 분석되면 다운로드가 시작되지만 DOM로드, 즉 Onload 이벤트가 시작될 때까지 실행되지 않습니다. DEFER 속성이있는 JavaScript 파일이 다운로드되면 브라우저의 다른 프로세스를 차단하지 않으므로 이러한 파일은 다른 리소스 파일과 병렬로 다운로드 할 수 있습니다.
DEFER 속성이있는 <cript> 요소는 내장 또는 외부 스크립트에 관계없이 DOM이로드 될 때까지 실행되지 않습니다. Listing 5의 예는 연기 속성이 스크립트 동작에 어떤 영향을 미치는지 보여줍니다.
Listing 5 스크립트 동작에 대한 연기 속성의 효과
<html> <head> <title> 스크립트 연기 예 </title> </head> <body> <Script Type = "Text/JavaScript"Defer> Alert ( "DEFER"); </script> <script type = "text/javaScript"> alert ( "script"); </script> <script type = "text/javaScript"> window.onload = function () {alert ( "load"); }; </script> </body> </html>이 코드는 페이지 처리 중에 3 개의 대화 상자를 나타냅니다. DEFER 속성을 지원하지 않는 브라우저의 팝업 순서는 "Defer", "Script"및 "Load"입니다. 연기 속성을 지원하는 브라우저에서 팝업 순서는 "스크립트", "지연"및 "로드"입니다. 지연 속성이있는 <cript> 요소는 두 번째 속성 이후에 실행되지 않지만 Onload 이벤트가 트리거되기 전에 호출됩니다.
대상 브라우저에 Internet Explorer 및 Firefox 3.5 만 포함 된 경우 DEFER 스크립트가 실제로 유용합니다. 도메인에서 여러 브라우저를 지원 해야하는 경우이를 구현하는 더 일관된 방법이 있습니다.
html 5는 <cript> 태그에 대한 새로운 확장 속성을 정의합니다 : Async. 기능은 연기와 동일하며 스크립트로드로 인해 페이지로드를 차단하지 않고 스크립트를 비동기로로드하고 실행할 수 있습니다. 그러나 주목해야 할 것은 Async의 경우 JavaScript 스크립트가 다운로드되면 실행되므로 원래 순서로 실행되지 않을 가능성이 높습니다. JavaScript 스크립트 전후의 종속성이있는 경우 Async를 사용하여 오류가 발생할 가능성이 높습니다.
동적 스크립트 요소
DOM (Document Object Model)을 사용하면 JavaScript를 사용하여 HTML의 거의 모든 문서 컨텐츠를 동적으로 생성 할 수 있습니다. 페이지의 다른 요소와 마찬가지로 <cript> 요소는 표준 DOM 기능으로 매우 쉽게 만들 수 있습니다.
Listing 6 표준 DOM 기능으로 <cript> 요소를 작성합니다
var script = document.createElement ( "스크립트"); script.type = "text/javaScript"; script.src = "script1.js"; document.getElementsByTagName ( "Head") [0] .AppendChild (스크립트);
새로운 <cript> 요소는 script1.js 소스 파일을로드합니다. 요소가 페이지에 추가 된 직후이 파일을 다운로드하십시오. 이 기술의 핵심 요점은 다운로드가 시작 되더라도 파일의 다운로드 및 실행이 다른 페이지 처리를 차단하지 않는다는 것입니다. 나머지의 페이지 코드에 영향을 미치지 않고이 코드를 <head> 섹션에 배치 할 수도 있습니다 (파일을 다운로드하는 데 사용되는 HTTP 연결 제외).
동적 스크립트 노드를 사용하여 파일이 다운로드되면 반환 된 코드는 일반적으로 즉시 실행됩니다 (Firefox 및 Opera를 제외하고 모든 이전 동적 스크립트 노드가 실행을 완료 할 때까지 기다립니다). 이 메커니즘은 스크립트가 "자체 실행"유형 일 때 잘 작동하지만 스크립트에 페이지에 다른 스크립트를 호출하기위한 인터페이스 만 포함하면 문제가 발생합니다. 이 경우 스크립트 다운로드가 완료되었는지 여부와 준비가되었는지 여부를 추적해야합니다. Dynamic <Script> 노드를 사용하여 이벤트를 발행하여 관련 정보를 얻을 수 있습니다.
Firefox, Opera, Chorme 및 Safari 3+는 <Script> 노드 리셉션이 완료된 후 Onload 이벤트를 발행합니다. 이 이벤트를 들으려면 스크립트에서 알림을받을 수 있습니다.
Onload 이벤트를 듣고 7 개의 JavaScript 스크립트로드 목록
var script = document.createElement ( "script") script.type = "text/javaScript"; // firefox, Opera, Chrome, Safari 3+script.onload = function () {alert ( "스크립트로드!");}; script.src = "script1.js"; documInternet Explorer는 ReadyStateChange 이벤트를 방출하는 또 다른 구현을 지원합니다. <cript> 요소에는 값이 외부 파일을 다운로드하는 프로세스로 값이 변경되는 ReadyState 속성이 있습니다. ReadyState에는 5 가지 값이 있습니다.
1. "비 초기화": 기본 상태
2. "로드": 다운로드가 시작됩니다
3. "로드": 다운로드 완료
4. "Interactive": 다운로드가 완료되었지만 아직 사용할 수 없습니다.
5. "완료": 모든 데이터가 준비되었습니다
Microsoft 문서에 따르면 <cript> 요소의 수명주기 동안 이러한 ReadyState 값은 나타나지 않을 수 있지만 항상 어떤 값이 사용될지는 나타내지 않습니다. 실제로, 우리가 가장 관심있는 것은 "로드 된"및 "완전한"상태입니다. Internet Explorer는이 두 ReadyState 값으로 표시되는 최종 상태가 없습니다. 때로는 <cript> 요소가 "로더"를 얻지 만 "완료"는 없지만 경우에 따라 "완료"가 나타나고 "로드 된"도 사용할 수 없습니다. 가장 안전한 방법은 ReadyStateChange 이벤트 에서이 두 상태를 확인하는 것입니다. 상태 중 하나가 나타나면 ReadyStateChange 이벤트 핸들을 삭제합니다 (이벤트가 두 번 처리되지 않도록) :
Reading States를 확인하여 8 개의 JavaScript 스크립트로드
var script = document.createElement ( "script") script.type = "text/javaScript"; // Internet ExplorERScript.onReadyStateChange = function () {if (script.readyState = "로드 된"|| 스크립트.ReadingState == "완료"). 경고 ( "스크립트로드."); }}; script.src = "script1.js"; documb대부분의 경우 기능을 호출하여 JavaScript 파일의 동적로드를 구현하려고합니다. 다음 기능은 표준 구현 및 IE 구현에 필요한 기능을 캡슐화합니다.
기능별 9 캡슐화 나열
함수 loadScript (url, 콜백) {var script = document.createElement ( "script") script.type = "text/javaScript"; if (script.readystate) {// script.onreadyStateChange = function () {if (script.readystate = "|| script.readystate =="complete ") {script.onreadyStateChange = null; 콜백 (); }}; } else {// 기타 script.onload = function () {callback (); }; } script.src = url; document.getElementsByTagName ( "Head") [0] .AppendChild (스크립트);}이 함수는 JavaScript 파일의 URL과 JavaScript 수신이 완료 될 때 트리거되는 콜백 함수의 두 매개 변수를 수신합니다. 속성 점검은 모니터링 할 이벤트를 결정하는 데 사용됩니다. 마지막 단계에서는 SRC 속성을 설정하고 <Script> 요소를 페이지에 추가하십시오. 이 loadscript () 함수는 다음과 같이 사용됩니다.
LoadScript () 함수를 사용하는 방법
loadScript ( "script1.js", function () {alert ( "파일이로드되었습니다!");});페이지에 많은 JavaScript 파일을 동적으로로드 할 수 있지만 브라우저가 파일이로드 된 순서를 보장하지 않도록주의하십시오. 모든 주요 브라우저 중에서 Firefox와 Opera만이 지정한 순서대로 스크립트가 실행되도록합니다. 다른 브라우저는 서버가 반환하는 순서대로 다른 코드 파일을 다운로드하여 실행합니다. 다음과 같이 순서를 보장하기 위해 작업을 함께 다운로드 할 수 있습니다.
LoadScript () 함수를 통해 여러 JavaScript 스크립트로드 11
loadScript ( "script1.js", function () {loadScript ( "script2.js", function () {loadscript ( "script3.js", alert ( "모든 파일이로드되었습니다!");});}); });이 코드는 script2.js를로드하기 전에 script1.js를 사용할 수 있기를 기다린 다음 script2.js를 사용할 수있게 된 후 script3.js를로드하기 시작합니다. 이 방법은 가능하지만 다운로드 및 실행할 파일이 많으면 여전히 약간 번거 롭습니다. 여러 파일의 순서가 매우 중요하다면 더 좋은 방법은 파일을 올바른 순서로 하나의 파일에 연결하는 것입니다. 독립형 파일은 한 번에 모든 코드를 다운로드 할 수 있습니다 (이는 비동기 적으로 수행되므로 큰 파일을 사용하는 데 손실이 없습니다).
동적 스크립트 로딩은 브로우 브라우저가 될 수 있고 사용하기 쉽기 때문에 비 차단 JavaScript 다운로드에서 가장 일반적으로 사용되는 패턴입니다.
xhttprequest (xhr) 객체 사용
이 기술은 먼저 XHR 객체를 생성 한 다음 JavaScript 파일을 다운로드 한 다음 동적 <Script> 요소로 페이지에 JavaScript 코드를 주입합니다. 목록 12는 간단한 예입니다.
XHR 객체를 통해 12 개의 JavaScript 스크립트로드를 나열합니다
var xhr = new xmlhttprequest (); xhr.open ( "get", "script1.js", true); xhr.onreadyStateChange = function () {if (xhr.readystate == 4) {if (xhr.status> = 200 && xhr.status <300 | xhr.status an qAl 4). 문서 .CreateElement ( "스크립트"); script.type = "text/javaScript"; script.text = xhr.responsetext; document.body.appendChild (스크립트); }}}; xhr.send (null);이 코드는 Script1.js 파일을 가져 오기 위해 서버에 GET 요청을 보냅니다. OnreadyStateChange 이벤트 핸들러는 ReadyState가 4인지 확인한 다음 HTTP 상태 코드가 유효한지 확인합니다 (2xx는 유효한 응답을 의미하며 304는 캐시 된 응답을 의미합니다). 유효한 응답이 수신되면 새 <cript> 요소가 생성되고 텍스트 속성이 서버에서 수신 된 대응 문자열로 설정됩니다. 그렇게하면 실제로 인라인 코드로 <cript> 요소가 생성됩니다. 새 <cript> 요소가 문서에 추가되면 코드가 실행되고 사용할 준비가됩니다.
이 접근법의 주요 장점은 즉시 실행되지 않은 JavaScript 코드를 다운로드 할 수 있다는 것입니다. 코드는 <cript> 태그 외부에서 반환되므로 (즉, <cript> 태그의 대상이되지 않음) 다운로드 후 자동으로 실행되지 않으므로 모든 것이 준비 될 때까지 실행을 연기 할 수 있습니다. 또 다른 장점은 동일한 코드가 모든 최신 브라우저에서 예외를 제외하지 않는다는 것입니다.
이 방법의 주요 제한 사항은 JavaScript 파일이 페이지와 동일한 도메인에 배치해야하며 CDN에서 다운로드 할 수 없다는 것입니다 (CDN은 "Content Delivery Network"를 참조하므로 큰 웹 페이지는 일반적으로 XHR 스크립트 주입 기술을 사용하지 않습니다.
일반적으로 사용하는 기능을 추가하십시오
함수 loadjs (url, 콜백, charset) {var head = document.getElementsByTagName ( "head") [0]; var script = document.createElement ( "스크립트"); if (!! charset) script.charset = "utf-8"; script.src = url; script.onload = script.onreadyStateChange = function () {var f = script.readystate; if (f && f! = "로드 된"&& f! = "완료") return; script.onload = script.onreadyStateChange = null; head.removechild (스크립트) if (콜백) {콜백 () || 콜백}; }; Head.appendChild (스크립트);} // js 동기로드 함수 getScripts (i, linkarray, fn) {env || getenv (); var script = document.createElement ( 'script'); script.type = 'text/javaScript'; script.src = linkarray [i]; var head = document.head || document.getElementsByTagName ( 'head') [0]; Head.appendChild (스크립트); if (env.ie && 'script))의 if (env.ie &&'on readreadstatechange '(스크립트에서'draggable ')) {// 즉, 브라우저를로드 스크립트. if (i === linkarray.length-1) {if (fn) {fn (); }} else {getScripts (++ i, linkarray, fn); }}}}; } else {script.onload = function () {if (i === linkarray.length-1) {if (fn) {fn (); }} else {getScripts (++ i, linkarray, fn); }}}; }} // js는 GetScripts (0, [ 'http://caibaojian.com/demo/base.js', 'http://caibaojian.com/demo/reset.js'], function () {alert ( 'Callback');};요약
JavaScript의 성능 영향을 줄이는 몇 가지 방법이 있습니다.
모든 <cript> 태그를 페이지 하단에, 즉 태그를 닫기 전에 스크립트가 실행되기 전에 페이지가 렌더링되었는지 확인합니다.
가능한 한 스크립트를 병합하십시오. 페이지의 <cript> 태그가 적을수록로드가 빨라지고 응답이 빨라집니다. 이것은 외부 스크립트와 임베디드 스크립트 모두에 해당됩니다.
차단되지 않은 JavaScript 스크립트를 사용하여 다운로드하십시오.
<cript> 태그의 연기 속성을 사용하십시오 (IE 및 Firefox 3.5 이상에서만 사용할 수 있음).
동적으로 만든 <cript> 요소를 사용하여 코드를 다운로드하고 실행합니다.
XHR 객체를 사용하여 JavaScript 코드를 다운로드하여 페이지에 주입하십시오.
위의 전략은 많은 JavaScript가 필요한 웹 사이트 및 응용 프로그램의 실제 성능을 크게 향상시킬 수 있습니다.
위는 JavaScript 성능 최적화 요약로드 및 실행의 전체 내용입니다. 모든 사람에게 도움이되기를 바랍니다.