Programing

스크립트를 비동기 적으로로드

lottogame 2020. 7. 17. 08:13
반응형

스크립트를 비동기 적으로로드


JQuery의 여러 플러그인, 사용자 정의 위젯 및 기타 라이브러리를 사용하고 있습니다. 결과적으로 여러 개의 .js 및 .css 파일이 있습니다. 로드하는 데 시간이 걸리기 때문에 내 사이트의 로더를 만들어야합니다. 모든 것을 가져 오기 전에 로더를 표시 할 수 있다면 좋을 것입니다.

<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
... 
....
 etc

JavaScript 라이브러리를 비동기식으로 가져올 수있는 몇 가지 자습서를 찾았습니다. 예를 들어 다음과 같이 할 수 있습니다.

  (function () {
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.async = true;
        s.src = 'js/jquery-ui-1.8.16.custom.min.js';
        var x = document.getElementsByTagName('script')[0];
        x.parentNode.insertBefore(s, x);
    })();

어떤 이유로 든 모든 파일에 대해 동일한 작업을 수행하면 페이지가 작동하지 않습니다. 문제가있는 곳을 찾으려고 오랫동안 노력했지만 그 문제를 찾을 수 없습니다. 먼저 일부 JavaScript 기능이 다른 기능에 의존하기 때문이라고 생각했습니다. 그러나 하나를 완료했을 때 타임 아웃 기능을 사용하여 올바른 순서로로드하고 다음을 계속 진행했지만 페이지가 여전히 이상하게 작동합니다. 예를 들어 링크 등을 클릭 할 수 없습니다. 애니메이션은 여전히 ​​작동합니다 ..

어쨌든

여기에 내가 생각한 것이 있습니다 ... 브라우저에 캐시가 있다고 생각하여 처음으로 페이지를로드하는 데 시간이 오래 걸리고 다음에는 빠릅니다. 그래서 내가 생각하는 것은 내 index.html 페이지를이 모든 파일을 비동기 적으로로드하는 페이지로 바꾸는 것입니다. ajax가 완료되면 모든 파일을로드하려고합니다. 사용하려는 페이지로 리디렉션됩니다. 해당 페이지를 사용할 때 파일이 브라우저의 캐시에 이미 포함되어 있어야로드하는 데 시간이 오래 걸리지 않습니다. 내 색인 페이지 (.js 및 .css 파일이 비동기 적으로로드되는 페이지)에서 오류가 발생하지 않습니다. 로더를 표시하고 완료되면 페이지를 리디렉션합니다.

이 아이디어가 좋은 대안입니까? 아니면 비동기 방식으로 구현을 계속해야합니까?


편집하다

모든 것을 비동기식으로로드하는 방법은 다음과 같습니다.

importScripts();

function importScripts()
{
    //import: jquery-ui-1.8.16.custom.min.js
    getContent("js/jquery-1.6.2.min.js",function (code) {
                var s = document.createElement('script');
                s.type = 'text/javascript';
                //s.async = true;
                s.innerHTML=code;
                var x = document.getElementsByTagName('script')[0];
                x.parentNode.insertBefore(s, x);
                setTimeout(insertNext1,1);
            });


    //import: jquery-ui-1.8.16.custom.min.js
    function insertNext1()
    {
        getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext2,1);
                });
    }

    //import: jquery-ui-1.8.16.custom.css
    function insertNext2()
    {

        getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext3,1);
                });
    }

    //import: main.css
    function insertNext3()
    {

        getContent("css/main.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext4,1);
                });
    }

    //import: jquery.imgpreload.min.js
    function insertNext4()
    {
        getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext5,1);
                });
    }


    //import: marquee.js
    function insertNext5()
    {
        getContent("js/marquee.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext6,1);
                });
    }


    //import: marquee.css
    function insertNext6()
    {

        getContent("css/marquee.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext,1);
                });
    }



    function insertNext()
    {
        setTimeout(pageReadyMan,10);        
    }
}


// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
     // attempt to create the XMLHttpRequest and make the request
     try
     {
        var asyncRequest; // variable to hold XMLHttpRequest object
        asyncRequest = new XMLHttpRequest(); // create request object

        // register event handler
        asyncRequest.onreadystatechange = function(){
            stateChange(asyncRequest, callBackFunction);
        } 
        asyncRequest.open( 'GET', url, true ); // prepare the request
        asyncRequest.send( null ); // send the request
     } // end try
     catch ( exception )
     {
        alert( 'Request failed.' );
     } // end catch
} // end function getContent

// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
     if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
     {
           callBackFunction(asyncRequest.responseText);
     } // end if
} // end function stateChange

이상한 부분은 모든 스타일의 작업과 모든 자바 스크립트 기능입니다. 그래도 페이지가 멈췄습니다 ...


비동기 로딩을위한 몇 가지 솔루션 :

//this function will work cross-browser for loading scripts asynchronously
function loadScript(src, callback)
{
  var s,
      r,
      t;
  r = false;
  s = document.createElement('script');
  s.type = 'text/javascript';
  s.src = src;
  s.onload = s.onreadystatechange = function() {
    //console.log( this.readyState ); //uncomment this line to see which ready states are called.
    if ( !r && (!this.readyState || this.readyState == 'complete') )
    {
      r = true;
      callback();
    }
  };
  t = document.getElementsByTagName('script')[0];
  t.parentNode.insertBefore(s, t);
}

페이지에 jQuery가 이미 있다면 다음을 사용하십시오.

$.getScript(url, successCallback)*

또한 문서로드가 완료되기 전에 스크립트가로드 / 실행될 document.ready수 있습니다. 즉, 이벤트가 요소에 바인딩되기 전에 기다려야합니다 .

코드를 보지 않고 문제가 무엇인지 구체적으로 말할 수는 없습니다.

가장 간단한 해결책은 페이지 하단에 모든 스크립트를 인라인으로 유지하여 실행 중에 HTML 내용로드를 차단하지 않는 것입니다. 또한 필요한 각 스크립트를 비동기 적으로로드해야하는 문제를 방지합니다.

항상 사용되지 않는 멋진 상호 작용이있는 경우 일종의 더 큰 스크립트가 필요하면 특정 스크립트가 필요할 때까지로드하지 않는 것이 좋습니다 (지연 로딩).

* 로드 된 스크립트 $.getScript는 캐시되지 않을 것입니다


Promise객체 와 같은 최신 기능을 사용할 수있는 사람이라면 누구나 loadScript기능이 훨씬 간단 해졌습니다.

function loadScript(src) {
    return new Promise(function (resolve, reject) {
        var s;
        s = document.createElement('script');
        s.src = src;
        s.onload = resolve;
        s.onerror = reject;
        document.head.appendChild(s);
    });
}

callback반환 된 약속이 콜백을 처리하므로이 버전은 더 이상 인수를 허용하지 않습니다 . 이전에 있었던 loadScript(src, callback)것은 이제 되었을 loadScript(src).then(callback)입니다.

이것은 실패를 감지하고 처리 할 수있는 추가 보너스를 가지고 있습니다.

loadScript(cdnSource)
    .catch(loadScript.bind(null, localSource))
    .then(successCallback, failureCallback);

... 그리고 CDN 중단을 정상적으로 처리합니다.


HTML5의 새로운 '비동기'속성이 트릭을 수행합니다. IE에 관심이 있다면 대부분의 브라우저에서 '지연'도 지원됩니다.

async-HTML

<script async src="siteScript.js" onload="myInit()"></script>

연기-HTML

<script defer src="siteScript.js" onload="myInit()"></script>

새로운 애드 센스 광고 단위 코드를 분석하는 동안 속성 및 검색으로 나를 발견했습니다. http://davidwalsh.name/html5-async


로드가 완료된 모든 스크립트가 페이지를 index2.html로 리디렉션 한 경우 index2.html이 동일한 라이브러리를 사용하는 경우 스크립트를 비동기식으로로드했습니다 (html 5에 해당 기능이 있음). 페이지가 index2.html로 리디렉션되면 브라우저에 캐시가 있기 때문에 index2.html은 페이지를로드하는 데 필요한 모든 것을 갖추고 있기 때문에 1 초 이내에로드됩니다. index.html 페이지에서 브라우저가 해당 이미지를 캐시에 배치하도록 사용하려는 이미지도로드합니다. 그래서 내 index.html은 다음과 같습니다

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Project Management</title>

    <!-- the purpose of this page is to load all the scripts on the browsers cache so that pages can load fast from now on -->

    <script type="text/javascript">

        function stylesheet(url) {
            var s = document.createElement('link');
            s.type = 'text/css';
            s.async = true;
            s.src = url;
            var x = document.getElementsByTagName('head')[0];
            x.appendChild(s);
        }

        function script(url) {
            var s = document.createElement('script');
            s.type = 'text/javascript';
            s.async = true;
            s.src = url;
            var x = document.getElementsByTagName('head')[0];
            x.appendChild(s);
        }

        //load scritps to the catche of browser
        (function () {            
                stylesheet('css/custom-theme/jquery-ui-1.8.16.custom.css');
                stylesheet('css/main.css');
                stylesheet('css/marquee.css');
                stylesheet('css/mainTable.css');

                script('js/jquery-ui-1.8.16.custom.min.js');
                script('js/jquery-1.6.2.min.js');
                script('js/myFunctions.js');
                script('js/farinspace/jquery.imgpreload.min.js');
                script('js/marquee.js');            
        })();

    </script>

    <script type="text/javascript">
       // once the page is loaded go to index2.html
        window.onload = function () {
            document.location = "index2.html";
        }
    </script>

</head>
<body>

<div id="cover" style="position:fixed; left:0px; top:0px; width:100%; height:100%; background-color:Black; z-index:100;">Loading</div>

<img src="images/home/background.png" />
<img src="images/home/3.png"/>
<img src="images/home/6.jpg"/>
<img src="images/home/4.png"/>
<img src="images/home/5.png"/>
<img src="images/home/8.jpg"/>
<img src="images/home/9.jpg"/>
<img src="images/logo.png"/>
<img src="images/logo.png"/>
<img src="images/theme/contentBorder.png"/>

</body>
</html>

이것에 대한 또 다른 좋은 점은 페이지에 로더를 배치 할 수 있고 페이지가로드되면 로더가 사라지고 밀리 초 단위로 새 페이지가 실행된다는 것입니다.


구글의 예

<script type="text/javascript">
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js?onload=onLoadCallback';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script>

몇 가지 메모 :

  • s.async = true하지 HTML5의 doctype이 매우 정확, 올바른이다 s.async = 'async'(실제로는 사용이 true 올바른지 , 감사는 AMN 에서 그것을 지적하는 사람들 주석 바로 아래)
  • 시간 초과를 사용하여 주문을 제어하는 ​​것은 매우 안전하지 않으며 모든 시간 초과의 합과 동일하도록 로딩 시간을 훨씬 크게 만듭니다!

최근에 파일을 비동기 적으로로드 해야하는 이유가 있지만 순서대로 예제보다 약간 더 기능 중심적인 방법을 권장합니다 ( console.log생산 용도로 제거 :)).

(function() {
    var prot = ("https:"===document.location.protocol?"https://":"http://");

    var scripts = [
        "path/to/first.js",
        "path/to/second.js",
        "path/to/third.js"
    ];

    function completed() { console.log('completed'); }  // FIXME: remove logs

    function checkStateAndCall(path, callback) {
        var _success = false;
        return function() {
            if (!_success && (!this.readyState || (this.readyState == 'complete'))) {
                _success = true;
                console.log(path, 'is ready'); // FIXME: remove logs
                callback();
            }
        };
    }

    function asyncLoadScripts(files) {
        function loadNext() { // chain element
            if (!files.length) completed();
            var path = files.shift();
            var scriptElm = document.createElement('script');
            scriptElm.type = 'text/javascript';
            scriptElm.async = true;
            scriptElm.src = prot+path;
            scriptElm.onload = scriptElm.onreadystatechange = \
                checkStateAndCall(path, loadNext); // load next file in chain when
                                                   // this one will be ready 
            var headElm = document.head || document.getElementsByTagName('head')[0];
            headElm.appendChild(scriptElm);
        }
        loadNext(); // start a chain
    }

    asyncLoadScripts(scripts);
})();

HTML5 덕분에 이제 태그에 "async"를 추가하여 비동기 적으로로드 할 스크립트를 선언 할 수 있습니다.

<script async>...</script>

참고 : async 속성은 외부 스크립트 전용이며 src 속성이있는 경우에만 사용해야합니다.

참고 : 외부 스크립트를 실행할 수있는 몇 가지 방법이 있습니다.

  • 비동기가있는 경우 : 스크립트가 나머지 페이지와 비동기 적으로 실행됩니다 (페이지가 구문 분석을 계속하는 동안 스크립트가 실행 됨)
  • 비동기가없고 지연이있는 경우 : 페이지 구문 분석이 완료되면 스크립트가 실행됩니다.
  • 비동기 또는 지연이없는 경우 : 브라우저가 페이지 구문 분석을 계속하기 전에 스크립트를 즉시 가져 와서 실행합니다.

이것을보십시오 : http://www.w3schools.com/tags/att_script_async.asp


콜백이 있는지 확인하고 인수 전달을 허용하여 zzzzBov의 답변을 완료합니다.

    function loadScript(src, callback, args) {
      var s, r, t;
      r = false;
      s = document.createElement('script');
      s.type = 'text/javascript';
      s.src = src;
      if (typeof(callback) === 'function') {
        s.onload = s.onreadystatechange = function() {
          if (!r && (!this.readyState || this.readyState === 'complete')) {
            r = true;
            callback.apply(args);
          }
        };
      };
      t = document.getElementsByTagName('script')[0];
      t.parent.insertBefore(s, t);
    }

다음은 비동기 스크립트로드에 대한 훌륭한 현대 솔루션입니다 .async false로 js 스크립트 만 처리합니다 .

작성된 훌륭한 기사가 www.html5rocks.com - 딥 다이빙 스크립트로드의 어두운 바다에가 .

가능한 많은 솔루션을 고려한 후 저자는 js 스크립트를 body 요소 끝에 추가하는 것이 js 스크립트에 의한 페이지 렌더링을 막는 가장 좋은 방법이라고 결론지었습니다.

그 동안 필자는 필사적으로 스크립트를로드하고 실행하는 데 필사적 인 사람들을위한 또 다른 훌륭한 대안 솔루션을 추가했습니다.

네 개의 스크립트 이름 script1.js, script2.js, script3.js, script4.js이 있다고 가정 하면 async = false적용하여 수행 할 수 있습니다 .

[
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

이제 Spec이라고 말합니다 : 모든 다운로드가 완료되는 즉시 함께 다운로드하여 실행하십시오.

Firefox <3.6, Opera의 말 : 이“비동기”가 무엇인지 전혀 모르겠지만 JS를 통해 추가 된 스크립트를 추가 된 순서대로 실행합니다.

Safari 5.0의 말 : “비동기”를 이해하지만 JS에서“거짓”으로 설정하는 것을 이해하지 못합니다. 어떤 순서로든 착륙하자마자 스크립트를 실행하겠습니다.

IE <10의 말 : “비동기”에 대한 아이디어는 없지만“onreadystatechange”를 사용하는 해결 방법이 있습니다.

그 밖의 모든 것 : 나는 당신의 친구입니다, 우리는 책으로 이것을 할 것입니다.

이제 IE <10 해결 방법의 전체 코드 :

var scripts = [
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && ( pendingScripts[0].readyState == 'loaded' || pendingScripts[0].readyState == 'complete' ) ) {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we’ll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}

스크립트가 너무 느리게로드 될 수있는 한 가지 이유는 다음과 같이 페이지를로드하는 동안 모든 스크립트를 실행하는 것입니다.

callMyFunctions();

대신에:

$(window).load(function() {
      callMyFunctions();
});

이 두 번째 스크립트는 브라우저가 모든 Javascript 코드를 완전히로드 할 때까지 기다렸다가 스크립트 실행을 시작하여 페이지가 더 빨리로드 된 것으로 사용자에게 표시합니다.

로딩 시간을 줄여서 사용자 경험을 향상 시키려면 "로드 화면"옵션을 사용하지 않겠습니다. 제 생각에는 페이지를 더 느리게로드하는 것보다 훨씬 성 가실 것입니다.


Modernizr을 살펴 보시기 바랍니다 . 파일이로드되었는지 확인하고 지정한 다른 스크립트를 실행할 수있는 기능으로 자바 스크립트를 비동기 적으로로드 할 수있는 작은 경량 라이브러리입니다.

다음은 jquery를로드하는 예입니다.

Modernizr.load([
  {
    load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js',
    complete: function () {
      if ( !window.jQuery ) {
            Modernizr.load('js/libs/jquery-1.6.1.min.js');
      }
    }
  },
  {
    // This will wait for the fallback to load and
    // execute if it needs to.
    load: 'needs-jQuery.js'
  }
]);

난 당신이 더 여기 읽을 수 있습니다,이 함께 도와 약간의 게시물을 작성한 https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript/ ,하지만 난 첨부했습니다 아래의 도우미 클래스. 스크립트가로드되면 지정된 창 속성이로드 될 때까지 자동으로 기다립니다.

export default class ScriptLoader {
  constructor (options) {
    const { src, global, protocol = document.location.protocol } = options
    this.src = src
    this.global = global
    this.protocol = protocol
    this.isLoaded = false
  }

  loadScript () {
    return new Promise((resolve, reject) => {
      // Create script element and set attributes
      const script = document.createElement('script')
      script.type = 'text/javascript'
      script.async = true
      script.src = `${this.protocol}//${this.src}`

      // Append the script to the DOM
      const el = document.getElementsByTagName('script')[0]
      el.parentNode.insertBefore(script, el)

      // Resolve the promise once the script is loaded
      script.addEventListener('load', () => {
        this.isLoaded = true
        resolve(script)
      })

      // Catch any errors while loading the script
      script.addEventListener('error', () => {
        reject(new Error(`${this.src} failed to load.`))
      })
    })
  }

  load () {
    return new Promise(async (resolve, reject) => {
      if (!this.isLoaded) {
        try {
          await this.loadScript()
          resolve(window[this.global])
        } catch (e) {
          reject(e)
        }
      } else {
        resolve(window[this.global])
      }
    })
  }
}

사용법은 다음과 같습니다.

const loader = new Loader({
    src: 'cdn.segment.com/analytics.js',
    global: 'Segment',
})

// scriptToLoad will now be a reference to `window.Segment`
const scriptToLoad = await loader.load()

이 위키 기사가 흥미로울 것입니다 : http://ajaxpatterns.org/On-Demand_Javascript

그러한 기술을 언제 어떻게 사용하는지 설명합니다.


음, x.parentNode그냥 머리 태그 전에 스크립트를 삽입 있도록 HEAD 요소를 반환합니다. 아마도 그게 문제 일 것입니다.

x.parentNode.appendChild()대신 시도하십시오 .


https://github.com/stephen-lazarionok/async-resource-loader를 확인 하십시오 . 한 번의 샷으로 JS, CSS 및 여러 파일을로드하는 방법을 보여주는 예제가 있습니다.


LABJS 또는 RequreJS를 사용할 수 있습니다

스크립트 로더 좋아 LABJS, RequireJS코드의 속도와 품질이 향상됩니다.


Fetch Injection 사용을 고려 했습니까? 필자 는 이와 같은 경우를 처리하기 위해 fetch-inject 라는 오픈 소스 라이브러리를 굴 렸습니다 . 다음은 lib를 사용하는 로더의 모습입니다.

fetcInject([
  'js/jquery-1.6.2.min.js',
  'js/marquee.js',
  'css/marquee.css',
  'css/custom-theme/jquery-ui-1.8.16.custom.css',
  'css/main.css'
]).then(() => {
  'js/jquery-ui-1.8.16.custom.min.js',
  'js/farinspace/jquery.imgpreload.min.js'
})

이전 버전과의 호환성을 위해 기능 감지 및 XHR 주입 또는 스크립트 DOM 요소로 대체를 사용하거나을 사용하여 태그를 페이지에 인라인하십시오 document.write.


렌더링 차단 JavaScript를 제거하는 사용자 지정 솔루션은 다음과 같습니다.

// put all your JS files here, in correct order
const libs = {
  "jquery": "https://code.jquery.com/jquery-2.1.4.min.js",
  "bxSlider": "https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.5/jquery.bxslider.min.js",
  "angular": "https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.2/angular.min.js",
  "ngAnimate": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular-animate.min.js"
}
const loadedLibs = {}
let counter = 0

const loadAsync = function(lib) {
  var http = new XMLHttpRequest()
  http.open("GET", libs[lib], true)
  http.onload = () => {
    loadedLibs[lib] = http.responseText
    if (++counter == Object.keys(libs).length) startScripts()
  }
  http.send()
}

const startScripts = function() {
  for (var lib in libs) eval(loadedLibs[lib])
  console.log("allLoaded")
}

for (var lib in libs) loadAsync(lib)

즉, 모든 스크립트를 비동기 적으로로드 한 다음 결과적으로 실행합니다.

Github 저장소 : https://github.com/mudroljub/js-async-loader


누군가가 예를 들어 React에서 사용하려면 약간의 ES6 함수가 있습니다.

import {uniqueId} from 'lodash' // optional
/**
 * @param {String} file The path of the file you want to load.
 * @param {Function} callback (optional) The function to call when the script loads.
 * @param {String} id (optional) The unique id of the file you want to load.
 */
export const loadAsyncScript = (file, callback, id) => {
  const d = document
  if (!id) { id = uniqueId('async_script') } // optional
  if (!d.getElementById(id)) {
    const tag = 'script'
    let newScript = d.createElement(tag)
    let firstScript = d.getElementsByTagName(tag)[0]
    newScript.id = id
    newScript.async = true
    newScript.src = file
    if (callback) {
      // IE support
      newScript.onreadystatechange = () => {
        if (newScript.readyState === 'loaded' || newScript.readyState === 'complete') {
          newScript.onreadystatechange = null
          callback(file)
        }
      }
      // Other (non-IE) browsers support
      newScript.onload = () => {
        callback(file)
      }
    }
    firstScript.parentNode.insertBefore(newScript, firstScript)
  } else {
    console.error(`The script with id ${id} is already loaded`)
  }
}


먼저 파일을 축소하는 것이 좋습니다. 그러면 속도가 충분히 크게 향상되는지 확인하십시오. 호스트가 느리면 정적 컨텐츠를 CDN에 넣을 수 있습니다.

참고 URL : https://stackoverflow.com/questions/7718935/load-scripts-asynchronously

반응형