defer, async 속성 및 JS 비동기 로드 및 솔 루 션 실행

24891 단어
스 크 립 트 파일 의 로 딩 을 최적화 하여 페이지 의 로 딩 속 도 를 향상 시 키 는 것 은 전단 엔지니어 가 페이지 로 딩 속 도 를 높이 는 데 매우 중요 한 것 입 니 다.각 브 라 우 저가 스 크 립 트 파일 을 분석 하 는 서로 다른 메커니즘 과 스 크 립 트 를 불 러 오 면 다른 자원 과 파일 의 불 러 오 는 것 을 막 을 수 있 기 때문이다.브 라 우 저 해상도 기 가 < script > 을 만 났 을 때 즉시 불 러 옵 니 다 (불 러 오기: 다운로드, 해석, 실행). 브 라 우 저 는 다른 자원 과 문서 에 대한 불 러 오기 가 중 단 됩 니 다.페이지 의 로 딩 속 도 를 높이 기 위해 서 는 JS 가 다른 자원 의 로 딩 을 막 지 않도록 해 야 합 니 다.
웹 킷 과 파이 어 폭 스 는 JS 의 실행 과정 을 최적화 하고 '프 리 캐 스 팅' 이라는 과정 을 추 가 했 습 니 다. '프 리 캐 스 팅' 과정 은 DOM 트 리 를 수정 하지 않 기 때문에 다른 해석 과정 과 병행 할 수 있 습 니 다. 이 과정 은 프 리 캐 스 팅 기 에 의 해 이 루어 지 며, DOM 트 리 의 실행 과정 은 주 해석 기 에 의 해 이 루어 질 수 있 습 니 다. 해석 과정 을 통 해 JavaScript 글 에서 언급 된 JS 의 실행 과정 을 알 수 있 습 니 다.'예비 분석' 과정 은 브 라 우 저의 예비 해석 기 에 의 해 이 루어 져 야 하 며, 예비 해석 기 는 스타일 시트 와 그림 을 분석 하 는 일 도 맡 고 있 습 니 다.
다른 한편, 브 라 우 저 동료 가 http 를 요청 하 는 수량 도 제한 되 어 있 습 니 다. js 를 불 러 오 는 것 은 불 러 오 는 스타일 처럼 병행 되 지 않 습 니 다. 스타일 시트 는 디 스 플레이 트 리 를 구축 하 는 일부분 입 니 다. 브 라 우 저 는 페이지 구 조 를 DOM 트 리 와 디 스 플레이 트 리 두 부분 으로 구성 되 어 있 으 며, 디 스 플레이 실행 양식 표 는 스타일 시트 만 바 꿀 뿐 DOM 트 리 는 바 뀌 지 않 습 니 다. 디 스 플레이 트 리 와 DOM 트 리 는 대응 되 지만,일일이 대응 하 는 것 이 아 닙 니 다. 따라서 다른 자원 과 문서 에 대한 불 러 오 는 것 을 멈 출 필요 가 없습니다.
페이지 로 딩 속 도 를 높이 는 가장 간단 하고 빠 른 방법 은 스 크 립 트 파일 을 body 밑 에 두 는 것 입 니 다. 그러나 이것 은 페이지 로 딩 속 도 를 높이 는 가장 좋 은 방안 이 아 닙 니 다. 다음은 다른 방안 을 소개 합 니 다.
먼저 < script > 시 스 크 립 트 지연 과 비동기 실행 을 위 한 두 가지 속성 을 소개 합 니 다: defer 와 async.
Defer, Async 속성
defer 는 html 4.0 에서 정의 합 니 다. 이 속성 은 브 라 우 저 로 하여 금 스 크 립 트 의 실행 을 지연 시 킬 수 있 습 니 다. 문서 해석 이 완료 되면 문서 가 나타 나 는 순서에 따라 다운로드 하여 해석 합 니 다. 즉, defer 속성의 < script > 은 < script > 을 body 에 두 는 효과 와 유사 합 니 다. async 는 HTML 5 에 추 가 된 속성 입 니 다. IE 10 과 브 라 우 저 는 이 속성 을 지원 합 니 다. 이 속성 은 스 크 립 트 를 비동기 로 불 러 오 는 역할 을 합 니 다. 즉, 브 라 우 저가 async 속성의 < script > 을 만 났 을 때 브 라 우 저가 css 를 불 러 오 는 것 과 마찬가지 로 비동기 로 불 러 옵 니 다. async 속성 을 지원 하 는 브 라 우 저 는 문제 가 없 는 것 같 지만 defer 속성 은 브 라 우 저 마다 지원 정도 가 다 릅 니 다. 테스트 코드 는 다음 과 같 습 니 다.
<script type="text/javascript" defer>
    alert('defer')
</script>
<script type="text/javascript">
    alert('script')
</script>
<script type="text/javascript">
    window.onload = function(){
        alert('onload')
    }
</script>
        
defer 테스트 코드 는 코드 를 로 컬 자체 테스트 에 복사 할 수 있 고 외부 스 크 립 트 src 를 도입 하여 내 연 스 크 립 트 를 직접 붙 일 수 있 습 니 다.
상기 코드 를 실행 하여 다음 과 같은 결론 을 얻 을 수 있 습 니 다.
외부 JS 는 각 브 라 우 저 에서 실행 결과 와 정 의 된 실행 순서 가 정상 이 며, alert 정 보 는 script - > defer - > onload 순서에 따라 팝 업 됩 니 다. 내 연 스 크 립 트, 스 크 립 트 가 IE9 / 8 / 7 / 6 로 정 의 된 순서대로 정 보 를 팝 업 하면 다른 브 라 우 저 는 defer - > script - > onload 순서대로 정 보 를 팝 업 하여 defer 가 효력 을 잃 었 음 을 표시 합 니 다. 여러 개의 내 연 defer 스 크 립 트 가 있 거나 body 와 head 가 분포 되 어 있 거나 iframe 에 도 내 연 defer 스 크 립 트 가 있 으 면 IE6 에서 일치 합 니 다. 스 크 립 트 에 defer 속성 을 추가 하여 불 러 오 는 것 을 지연 시 키 려 면 외부 스 크 립 트 가 좋 습 니 다. 내 연 된 defer 는 대부분의 브 라 우 저 가 지원 하지 않 을 뿐만 아니 라 IE6 의 표현 도 일치 하지 않 습 니 다.
따라서 스 크 립 트 를 body 밑 에 두 는 것 이 스 크 립 트 에 defer 속성 을 추가 하 는 것 보다 스 크 립 트 를 지연 시 키 는 것 이 좋 습 니 다. yslow 가 제안 한 것 처럼 put style top, put script bottom.
브 라 우 저의 defer 와 async 속성 을 만 나 는 < script > 브 라 우 저의 실행 과정 은 다음 과 같 습 니 다 (아래 자바 script 권위 지침 에서 따 옴).
WEB 브 라 우 저 는 Document 대상 을 만 들 고 WEB 페이지 를 분석 하기 시 작 했 습 니 다. HTML 요소 와 텍스트 내용 을 분석 한 후 Element 대상 과 Text 노드 를 문서 에 추가 합 니 다. 이 과정의 readystate 속성 값 은 "loading" 입 니 다.
HTML 해상도 기 가 async 와 defer 속성 이 없 는 < script > 을 만 났 을 때 이 요 소 를 문서 에 추가 한 다음 줄 이나 외부 스 크 립 트 를 실행 합 니 다. 이 스 크 립 트 들 은 동기 화 되 며 스 크 립 트 다운로드 (필요 하 다 면) 와 실행 해상도 기 를 일시 정지 합 니 다. 이 스 크 립 트 는 document. write () 를 사용 할 수 있 습 니 다.입력 흐름 에 텍스트 를 삽입 합 니 다. 해석 기 가 복 구 될 때 이 텍스트 들 은 문서 의 일부분 이 됩 니 다. 동기 화 스 크 립 트 는 항상 함수 와 등록 뒤에 사용 되 는 등록 이벤트 처리 프로그램 만 정의 하지만 문서 트 리 를 옮 겨 다 니 고 조작 할 수 있 습 니 다. 실행 할 때 이미 저장 되 어 있 기 때 문 입 니 다. 동기 화 스 크 립 트 는 자신의 < script > 요소 와 이전 문서 에 저 장 된 것 을 볼 수 있 습 니 다.용 해석 기 가 async 속성 을 설정 한 < script > 요 소 를 만 났 을 때 스 크 립 트 를 다운로드 하고 문 서 를 계속 해석 합 니 다. 스 크 립 트 는 다운로드 가 끝 난 후 가능 한 한 빨리 실행 되 지만 해석 기 는 멈 추 지 않 고 다운 로드 를 기다 리 고 있 습 니 다. 비동기 스 크 립 트 는 document. write () 를 금지 합 니 다.방법. < script > 요소 와 그 전의 모든 문서 요 소 를 볼 수 있 으 며, 다른 문서 내용 에 접근 할 수 없 거나 아예 접근 할 수 없습니다. 문서 가 해석 되면 document. ready State 속성 이 "inteactive" 로 변 합 니 다. defer 속성 이 있 는 모든 스 크 립 트 는 문서 에 나타 나 는 순서대로 실 행 됩 니 다. 비동기 스 크 립 트 도 이 시간 에 실 행 될 수 있 습 니 다. 지연 스 크 립 트 는 전체 문서 트 리 에 접근 할 수 있 습 니 다. document. write () 방법 을 사용 하지 마 십시오. 브 라 우 저 는 Document 대상 에서 DOMContentLoaded 이 벤트 를 실행 합 니 다. 이것 은 프로그램 이 동기 화 스 크 립 트 실행 단계 에서 비동기 이벤트 구동 단계 로 이동 하 는 것 을 의미 합 니 다. 그러나 이 때 비동기 스 크 립 트 가 실행 되 지 않 았 을 수도 있 습 니 다. 이 때 문 서 는 완전히 해석 되 었 지만 브 라 우 저 는 그림 과 같은 다른 내용 을 불 러 오 기 를 기다 리 고 있 을 수 있 습 니 다. 이 모든 내용 이 불 러 올 때 모든 비동기 스 크 립 트 가 불 러 오고 실 행 됩 니 다. document. ready State 속성 은 "complete" 로 바 뀌 었 고 WEB 브 라 우 저 는 Window 대상 의 load 이벤트 에서 출발 합 니 다. 이 순간 부터 비동기 이 벤트 를 호출 하여 사용자 입력 이벤트, 네트워크 이벤트, 계산기 만 료 등에 비동기 응답 합 니 다. JS 비동기 로드
브 라 우 저가 async, defer 속성의 스 크 립 트 실행 순 서 를 알 고 있 습 니 다. 이 두 속성 을 이용 하여 JS 의 차단 문 제 를 개선 할 수 있 습 니 다. 이 두 속성 을 사용 하면 몇 가지 가능 한 상황 이 있 습 니 다.
defer 는 true 입 니 다. 스 크 립 트 를 불 러 오 는 것 을 지연 시 키 고 문서 해석 이 완료 되 기 전에 실행 합 니 다. async 는 true: 비동기 로 스 크 립 트 를 불 러 옵 니 다. 다운로드 가 끝 난 후에 실행 합 니 다. window 의 load 이벤트 전에 실행 합 니 다 이 두 속성 을 이용 하여 js 를 비동기 로 불 러 오고 그들의 단점 도 알 아야 합 니 다.
defer 속성 을 사용 하면 외부 script 이 좋 습 니 다.
defer, async 스 크 립 트 를 사용 하여 document. write () 방법 사용 금지 스 크 립 트 가 접근 하려 는 스타일 속성 이 불 러 오지 않 은 스타일 시트 일 경우 브 라 우 저 는 이 스 크 립 트 가 스타일 시트 로 딩 이 완료 되 기 를 기다 리 는 것 을 금지 합 니 다. 이 는 스타일 시트 가 스 크 립 트 의 실행 을 막 은 것 과 같 습 니 다. 따라서 defer, async 스 크 립 트 를 사용 할 때 스타일 정 보 를 요청 하지 않 는 것 이 좋 습 니 다. defer 를 사용 하 든 async 속성 을 사용 하 든 먼저 페이지 의 js 파일 을 정리 해 야 합 니 다. 각 스 크 립 트 파일 간 의 의존성, 어떤 파일 이 불 러 오 는 것 을 지연 시 킬 수 있 는 지 등 js 코드 의 통합 과 분 리 를 한 다음 페이지 에 따라 이 두 속성 을 합 리 적 으로 사용 해 야 합 니 다. defer 속성 성명 은 이 스 크 립 트 에 document. write 또는 dom 수정 이 없 을 것 입 니 다.
모든 스 크 립 트 분석 이 완료 되면 자 바스 크 립 트 는 두 번 째 단계 로 넘 어 갑 니 다. 이 단 계 는 비동기 이 며 이벤트 로 작 동 됩 니 다. 이벤트 구동 단계 에서 WEB 브 라 우 저 는 이벤트 처리 프로그램 함 수 를 호출 하여 비동기 로 발생 하 는 이벤트 에 응답 합 니 다. 이벤트 처리 함 수 를 호출 하 는 것 은 사용자 입력, 네트워크 활동, 실행, 자 바스 크 립 트 의 오류 로 실 행 됩 니 다.
등록 이벤트 처리 프로그램 함 수 를 통 해 프로그램 을 처리 합 니 다. 등 록 된 이벤트 가 발생 할 때 이 함수 들 을 비동기 로 호출 합 니 다. setTimeout () 과 setInterval () 도 모두 비동기 입 니 다. 따라서 페이지 내용 에 내 연 된 script 이 setTimeout () 에 있 습 니 다.실행 은 비동기 JS 의 한 방법 입 니 다. 물론 코드 프로그램 을 DOMReady 에 두 고 실행 하 는 것 도 비동기 로 불 러 오 는 방법 입 니 다. 둘 다 코드 실행 단 계 를 이벤트 구동 단계 에 두 었 습 니 다.
dom 에서 만 든 script 탭 은 브 라 우 저 에서 비동기 입 니 다. 다음 과 같 습 니 다.
function delay_js(src){
    var objScript = document.createElement('script');
    objScript.setAttribute('src', src);
    objScript.setAttribute('type', 'text/javascript');
    document.body.appendChild(objScript);
    return objScript;
}
        
비동기 로 JS 불 러 오기
이 코드 를 비동기 로 불 러 온 JS 다운 로드 는 다른 것 과 마찬가지 로 병행 되 지만 실행 단 계 는 페이지 렌 더 링 을 막 고 window. onload 의 이 벤트 를 연장 합 니 다. 어떻게 하면 JS 를 다운로드 하고 실행 해도 페이지 렌 더 링 을 막 지 않 을 수 있 습 니까? 다음 과 같 습 니 다.
function loadjs(src, succ) {
    var elem = delay_js(src);
    if ((navigator.userAgent.indexOf('MSIE') == -1) ? false: true) {
        elem.onreadystatechange = function() {
            if (/loaded|complete/.test(this.readyState)){
                succ()
            }
        };
    }else{
        elem.onload = function(){
            succ();
        }
    }
    elem.onerror = function() {};
}
        
JS 비동기 다운로드 + 실행 방안
코드 분석:
IE 브 라 우 저 가 아 닌 script 의 onload 사건 을 포착 할 수 있 으 며, IE 는 script. onload 사건 을 포착 하지 못 하기 때문에 script. onreadystatechange 를 이용 할 수 밖 에 없습니다. onready statechange 상 태 를 검사 할 때 IE7 / 8 의 마지막 상 태 는 loaded 에 불과 합 니 다. IE6 의 마지막 상 태 는 complete 일 수도 있 고 loaded 일 수도 있 으 므 로 정규 loaded | complete 두 상 태 를 모두 검사 합 니 다. 비동기 로 JS 를 불 러 오 는 문 제 는 document. write 로 문서 내용 을 출력 할 수 없습니다. document. write 가 어디 까지 출력 해 야 할 지 알 수 없 지만 DOMReady 이후 에 작업 dom 을 수행 할 수 있 습 니 다.
비동기 로 불 러 오 는 다른 방법
DOMContentLoaded 와 OnLoad 이벤트, async 속성 및 defer 속성 script 을 제외 하고 JS 비동기 로 딩 을 해결 할 수 있 는 다른 방법 도 있 습 니 다.
ajax 를 통 해 js 내용 을 가 져 온 다음 eval 에서 실행 합 니 다.
var xhrObj = getXHRObject();
 xhrObj.onreadystatechange =
   function() {
     if ( xhrObj.readyState != 4 ) return;
     eval(xhrObj.responseText);
   };
 xhrObj.open('GET', 'A.js', true);
 xhrObj.send('');
                    
iframe 만 들 기: iframe 요 소 를 만 들 고 삽입 합 니 다.
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var doc = iframe.contentWindow.document;
doc.open().write('<body onload="insertJS()">');
doc.close();
                    
이 방법 은 도 메 인 간 문제 가 있 습 니 다. 부모 페이지 도 메 인 이름 이 수정 되면 자바 script 프로 토 콜 을 통 해 같은 도 메 인 이름 업그레이드 문 구 를 실행 합 니 다. 페이지 내 js 의 내용 은 주석 이 실행 되 지 않 지만 필요 할 때 주석 을 지우 고 eval 은 js 를 실행 합 니 다. 페이지 에 document. write Script 태그 setTimeout 으로 0 초 지연 및 기타 방법 조합 그리고 앞서 말씀 드 린 이벤트 구동 단계 의 실행 및 defer 또는 async 속성 을 증가 시 키 는 것 은 모두 비동기 로 JS 를 불 러 오 는 방법 입 니 다. 어떤 방법 을 사용 하 더 라 도 우 리 는 수요 에 따라 각자 취사선택 해 야 합 니 다. 그러나 어떤 방법 을 사용 하 더 라 도 실행 순 서 를 보장 할 수 없습니다. 모든 js 내용 을 모듈 화 하 는 방식 으로 나 누 어야 합 니 다. 어떤 모듈 에 의존 관계 가 있 는 지, 어떤 모듈 이 비동기 화 할 수 있 는 지, JS.어떻게 나 눌 수 있 는 지 는 참작 하고 참작 해 야 한다

좋은 웹페이지 즐겨찾기