IT story

스크립트 순서로드 및 실행

hot-time 2020. 4. 9. 08:11
반응형

스크립트 순서로드 및 실행


html 페이지에 JavaScript를 포함시키는 방법에는 여러 가지가 있습니다. 다음 옵션에 대해 알고 있습니다.

  • 인라인 코드 또는 외부 URI에서로드
  • <head> 또는 <body> 태그에 포함됨 [ 1 , 2 ]
  • 없음 defer또는 async속성이있는 경우 (외부 스크립트 만 해당)
  • 정적 소스에 포함되거나 다른 스크립트에 의해 동적으로 추가됨 (다른 구문 분석 상태에서 다른 방법으로)

하드 디스크, javascript : URIs 및 onEvent-attributes [ 3 ] 에서 브라우저 스크립트를 계산하지 않고 이미 JS를 실행하는 16 가지 대안이 있으며 무언가를 잊어 버린 것 같습니다.

나는 빠른 (병렬) 로딩에 관심이 없으며 실행 순서 (로드 순서 및 문서 순서 에 따라 다름)에 대해 더 궁금합니다 . 실제로 모든 경우를 다루는 좋은 (크로스 브라우저) 참조가 있습니까? 예를 들어 http://www.websiteoptimization.com/speed/tweak/defer/ 는 6 개만 처리하며 대부분 오래된 브라우저를 테스트합니다.

그렇지 않다는 것을 두려워하면서 여기에 내 질문이 있습니다. 초기화 및 스크립트로드를위한 (외부) 헤드 스크립트가 있습니다. 그런 다음 본문 끝에 두 개의 정적 인라인 스크립트가 있습니다. 첫 번째 것은 스크립트 로더가 다른 스크립트 요소 (외부 js 참조)를 본문에 동적으로 추가 할 수있게합니다. 정적 인라인 스크립트 중 두 번째는 추가 된 외부 스크립트의 js를 사용하려고합니다. 다른 사람이 실행 된 것에 의존 할 수 있습니까 (그리고 왜 :-)?


동적 스크립트를로드하거나 그들을 표시하지 않는 경우 defer또는 async, 다음 스크립트는 페이지에서 발생하는 순서로로드됩니다. 외부 스크립트인지 인라인 스크립트인지는 중요하지 않습니다. 페이지에서 발견 된 순서대로 실행됩니다. 외부 스크립트 뒤에 오는 인라인 스크립트는 이전에 온 모든 외부 스크립트가로드되어 실행될 때까지 유지됩니다.

비동기 스크립트 (비동기 화로 지정되는 방법에 관계없이)는 예기치 않은 순서로로드 및 실행됩니다. 브라우저는 그것들을 병렬로로드하며 원하는 순서대로 자유롭게 실행할 수 있습니다.

여러 비동기 항목 중에서 예측 가능한 순서는 없습니다. 예측 가능한 순서가 필요한 경우 비동기 스크립트에서로드 알림을 등록하고 적절한 항목이로드 될 때 수동으로 javascript 호출을 시퀀싱하여 코딩해야합니다.

스크립트 태그가 동적으로 삽입되면 실행 순서는 브라우저에 따라 다릅니다. 이 참조 기사 에서 Firefox의 동작을 확인할 수 있습니다 . 간단히 말해서, 최신 버전의 Firefox는 스크립트 태그가 다르게 설정되어 있지 않으면 기본적으로 비동기로 추가 된 스크립트 태그를 비동기로 설정합니다.

스크립트 태그 async가로드 되 자마자 실행될 수 있습니다. 실제로 브라우저는 파서가 다른 작업을 중단하고 해당 스크립트를 실행할 수 있습니다. 따라서 거의 언제든지 실행할 수 있습니다. 스크립트가 캐시 된 경우 거의 즉시 실행될 수 있습니다. 스크립트를로드하는 데 시간이 걸리면 파서가 완료된 후에 실행될 수 있습니다. 기억해야 할 한 가지는 async언제든지 실행할 수 있으며 그 시간은 예측할 수 없다는 것입니다.

스크립트 defer파서는 전체 파서가 완료 될 때까지 기다렸다가 표시된 defer순서대로 표시된 모든 스크립트를 실행합니다 . 이를 통해 서로 의존하는 여러 스크립트를로 표시 할 수 있습니다 defer. 문서 파서가 완료 될 때까지 모두 연기되지만, 종속성을 유지하는 순서대로 실행됩니다. defer스크립트가 파서가 완료된 후에 처리 될 대기열에 놓인 것처럼 생각 합니다. 기술적으로 브라우저는 언제든지 백그라운드에서 스크립트를 다운로드 할 수 있지만 파서가 페이지를 구문 분석하고 defer또는 로 표시되지 않은 인라인 스크립트를 구문 분석하고 실행할 때까지 파서를 실행하거나 차단하지 않습니다 async.

이 기사의 인용문은 다음과 같습니다.

스크립트 삽입 스크립트는 IE 및 WebKit에서 비동기 적으로 실행되지만 Opera 및 4.0 이전 Firefox에서는 동 기적으로 실행됩니다.

HTML5 사양의 관련 부분 (최신 호환 브라우저 용)은 여기에 있습니다 . 비동기 동작에 대해 많은 글이 있습니다. 분명히이 사양은 동작을 확인하기 위해 테스트해야 할 구형 브라우저 (또는 잘못된 확인 브라우저)에는 적용되지 않습니다.

HTML5 사양에서 인용 한 내용 :

그런 다음 상황을 설명하는 다음 옵션 중 첫 번째 옵션을 따라야합니다.

요소에 src 속성이 있고 요소에 지연 속성이 있고 요소에 "parser-inserted"로 플래그가 지정되고 요소에 비동기 속성없는 경우 요소는 목록의 끝에 추가되어야합니다. 문서가 요소를 만든 파서의 문서와 관련된 구문 분석을 마쳤을 때 실행될 스크립트.

페치 알고리즘이 완료되면 네트워킹 태스크 소스가 태스크 큐에 배치하는 태스크는 요소의 "구문 분석기 실행 준비"플래그를 설정해야합니다. 파서는 스크립트 실행을 처리합니다.

요소에 src 속성이 있고 요소에 "parser-inserted"로 플래그가 지정되고 요소에 비동기 속성없는 경우 요소는 요소를 작성한 구문 분석기 문서의 보류중인 구문 분석 차단 스크립트입니다. (문서 당 한 번에 하나의 스크립트 만있을 수 있습니다.)

페치 알고리즘이 완료되면 네트워킹 태스크 소스가 태스크 큐에 배치하는 태스크는 요소의 "구문 분석기 실행 준비"플래그를 설정해야합니다. 파서는 스크립트 실행을 처리합니다.

요소에 src 속성이없고 요소가 "parser-inserted"로 플래그가 지정되고 스크립트 요소를 작성한 HTML 구문 분석기 또는 XML 구문 분석기의 문서에 스크립트를 차단하는 스타일 시트 가있는 경우 요소는 요소를 만든 파서의 Document에 대한 보류중인 파싱 차단 스크립트 (문서 당 한 번에 하나의 스크립트 만있을 수 있습니다.)

요소의 "파서 실행 준비"플래그를 설정하십시오. 파서는 스크립트 실행을 처리합니다.

요소에 src 속성이 있고 async 속성이없고 "force-async"플래그가 설정되어 있지 않은 경우 가능한 빨리 연관된 순서대로 실행할 스크립트 목록 끝에 요소를 추가해야합니다. 스크립트 알고리즘 준비가 시작될 때 스크립트 요소의 문서와 함께.

페치 알고리즘이 완료되면 네트워킹 태스크 소스가 태스크 큐에 배치하는 태스크는 다음 단계를 실행해야합니다.

요소가 이제 스크립트 목록에서 첫 번째 요소가 아닌 경우 위에 추가 된 순서대로 실행되는 경우 요소를 준비된 것으로 표시하지만 아직 스크립트를 실행하지 않고이 단계를 중단하십시오.

실행 :이 스크립트 목록에서 첫 번째 스크립트 요소에 해당하는 스크립트 블록을 가능한 빨리 순서대로 실행하십시오.

이 스크립트 목록에서 가능한 빨리 순서대로 실행될 첫 번째 요소를 제거하십시오.

가능한 빨리 순서대로 실행할이 스크립트 목록이 여전히 비어 있지 않고 첫 번째 항목이 이미 준비된 것으로 표시되어 있으면 실행 레이블이 지정된 단계로 건너 뜁니다.

요소에 src 속성 이있는 경우 스크립트 알고리즘 준비가 시작될 때 스크립트 요소의 문서에서 가능한 빨리 실행되는 스크립트 세트에 요소를 추가해야합니다.

페치 알고리즘이 완료되면 네트워킹 태스크 소스가 태스크 큐에 배치하는 태스크는 스크립트 블록을 실행 한 다음 가능한 빨리 실행되는 스크립트 세트에서 요소를 제거해야합니다.

그렇지 않으면 다른 스크립트가 이미 실행중인 경우에도 사용자 에이전트가 즉시 스크립트 블록을 실행해야합니다.


Javascript 모듈 스크립트는 type="module"어떻습니까?

Javascript는 이제 다음과 같은 구문으로 모듈 로딩을 지원합니다.

<script type="module">
  import {addTextToBody} from './utils.mjs';

  addTextToBody('Modules are pretty cool.');
</script>

또는 src속성이있는 경우 :

<script type="module" src="http://somedomain.com/somescript.mjs">
</script>

모든 스크립트 type="module"에는 defer속성 이 자동으로 부여됩니다 . 그러면 페이지를로드 할 때 병렬로 (인라인이 아닌 경우) 다운로드 한 다음 파서가 완료된 후 순서대로 실행됩니다.

모듈 스크립트 async에는 파서가 완료 될 때까지 기다리지 않고 async다른 스크립트와 비교하여 특정 순서로 스크립트 를 실행하지 않고 가능한 빨리 인라인 모듈 스크립트를 실행 하는 속성이 제공 될 수 있습니다 .

이 기사의 Javascript Module Loading 에서 모듈 스크립트를 포함하여 다양한 스크립트 조합의 페치 및 실행을 보여주는 매우 유용한 타임 라인 차트가 있습니다.


브라우저는 스크립트를 찾은 순서대로 실행합니다. 외부 스크립트를 호출하면 스크립트가로드되고 실행될 때까지 페이지가 차단됩니다.

이 사실을 테스트하려면 :

// file: test.php
sleep(10);
die("alert('Done!');");

// HTML file:
<script type="text/javascript" src="test.php"></script>

동적으로 추가 된 스크립트는 문서에 추가 되 자마자 실행됩니다.

이 사실을 테스트하려면 :

<!DOCTYPE HTML>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <script type="text/javascript">
        var s = document.createElement('script');
        s.type = "text/javascript";
        s.src = "link.js"; // file contains alert("hello!");
        document.body.appendChild(s);
        alert("appended");
    </script>
    <script type="text/javascript">
        alert("final");
    </script>
</body>
</html>

경고의 순서는 "추가"-> "hello!"입니다. -> "최종"

스크립트에서 아직 도달하지 않은 요소 (예 :)에 액세스하려고 <script>do something with #blah</script><div id="blah"></div>하면 오류가 발생합니다.

전반적으로 예, 외부 스크립트를 포함시킨 다음 해당 함수 및 변수에 액세스 할 수 있지만 현재 <script>태그 를 종료하고 새 태그를 시작하는 경우에만 가능합니다 .


@addyosmani 의 훌륭한 요약

여기에 이미지 설명을 입력하십시오

https://addyosmani.com/blog/script-priorities/ 에서 뻔뻔스럽게 복사


많은 옵션을 테스트 한 후 다음과 같은 간단한 솔루션이 모든 최신 브라우저에서 추가 된 순서대로 동적으로로드 된 스크립트를로드하는 것으로 나타났습니다

loadScripts(sources) {
    sources.forEach(src => {
        var script = document.createElement('script');
        script.src = src;
        script.async = false; //<-- the important part
        document.body.appendChild( script ); //<-- make sure to append to body instead of head 
    });
}

loadScripts(['/scr/script1.js','src/script2.js'])

참고 URL : https://stackoverflow.com/questions/8996852/load-and-execute-order-of-scripts

반응형