programing

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

minimums 2023. 2. 27. 23:03
반응형

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

JQuery의 여러 플러그인, 커스텀 위젯 및 기타 라이브러리를 사용하고 있습니다.그 결과 .js와 .css 파일이 몇 개 있습니다.로딩에 시간이 걸리기 때문에 사이트에 로더를 작성해야 합니다.모든 것을 Import하기 전에 로더를 표시할 수 있으면 좋겠습니다.

<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의 일부 기능이 다른 기능에 의존하기 때문일 것이라고 생각했지만, 1개의 기능이 완료되었을 때 타임아웃 기능을 사용하여 올바른 순서로 로드했더니 다음 페이지로 넘어갔는데 페이지가 여전히 이상합니다.예를 들어 링크 등을 클릭할 수 없습니다.애니메이션은 아직 작동하지만..

어쨌거나

이게 내가 생각한 거야...브라우저에는 캐시가 있기 때문에 첫 페이지와 다음 페이지 로딩에 시간이 오래 걸리는 것 같습니다.그래서 저는 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 콘텐츠 로드를 차단하지 않습니다.또한 필요한 각 스크립트를 비동기적으로 로드해야 하는 문제도 피할 수 있습니다.

특히 사용하지 않는 대화 방식이 더 큰 스크립트를 필요로 하는 경우에는 필요할 때까지 특정 스크립트를 로드하지 않는 것이 도움이 될 수 있습니다(느긋하게 로드).

* 로 로드된 스크립트는 캐시되지 않을 수 있습니다.


오브젝트 등 최신 기능을 사용할 수 있는 사용자에게는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);
    });
}

더 이전음음음음음음음음음음 a a a a a a a a를 사용할 수 .callback반환된 약속이 콜백을 처리하므로 인수를 지정합니다.까지의 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★loadScript(src, callback)지금이라면loadScript(src).then(callback).

이것에 의해, 예를 들면, 다음과 같은 장해를 검출해 처리할 수 있다는 이점이 있습니다.

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

CDN의 정지를 적절히 처리할 수 있습니다.

HTML5의 새로운 'async' 속성이 효과가 있을 것입니다.IE를 고려하는 경우 대부분의 브라우저에서 'defer'도 지원됩니다.

async - HTML

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

delfer - HTML

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

새로운 애드센스 광고 유닛 코드를 분석하던 중 속성 및 검색을 통해 http://davidwalsh.name/html5-async를 확인할 수 있었습니다.

로딩이 완료된 모든 스크립트가 동일한 라이브러리를 사용하는 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 doctpe입니다. 을 사용하다s.async = 'async' 사용)true 바로 아래 댓글에서 지적해 주신 am님 덕분에 정답입니다.)
  • 타임아웃을 사용하여 순서를 제어하는 것은 매우 적절하지 않고 안전하지 않으며, 모든 타임아웃의 합계와 동일한 로딩 시간을 훨씬 더 크게 만들 수 있습니다.

하는 최근 을 로드하는 경우,이 예보다 더 인 방법을 remove 최파 way 、 since since since 、 way since since since since 。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>

주의: 비동기 애트리뷰트는 외부 스크립트 전용입니다(src 애트리뷰트가 존재하는 경우에만 사용합니다).

주의: 외부 스크립트를 실행하는 방법은 다음과 같습니다.

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

참조: http://www.w3schools.com/tags/att_script_async.asp

이 문제를 해결하기 위해 작은 글을 썼는데, 자세한 내용은 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()

zzzBov의 답변에 콜백이 있는지 확인하고 인수 전달을 허용합니다.

    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);
    }

다음은 비동기 스크립트 로딩에 대한 훌륭한 최신 솔루션입니다.단, js 스크립트는 비동기 false로 처리됩니다.

www.html5rocks.com에 "스크립트 로딩의 탁한 물에 깊이 잠입하라"는 훌륭한 기사가 있습니다.

여러 가지 가능한 해결책을 검토한 후, 저자는 js 스크립트를 본문 끝에 추가하는 것이 js 스크립트에 의한 페이지 렌더링을 차단하지 않는 최선의 방법이라고 결론지었다.

한편 필자는 스크립트를 비동기적으로 로드하고 실행하는 데 급급한 사람들을 위해 또 다른 좋은 대체 솔루션을 추가했다.

네 개의 스크립트가 있는 걸 고려하면script1.js, script2.js, script3.js, script4.js그런 다음 비동기 = 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);
});

스펙은 다음과 같이 말합니다.함께 다운로드하여 모두 다운로드하는 즉시 순서대로 실행합니다.

Firefox < 3 . 6 、 Opera :이 "비동기"가 무엇인지 모르겠지만 JS를 통해 추가된 스크립트를 추가된 순서대로 실행합니다.

Safari 5.0의 특징:"async"는 이해하지만 JS에서 "false"로 설정하는 것은 이해할 수 없습니다.대본이 도착하는 대로 순서대로 실행하겠습니다.

IE < 10은 다음과 같습니다."async"에 대해서는 알 수 없지만 "onready state change"를 사용한 회피책이 있습니다.

그 외는 모두 다음과 같습니다.난 네 친구니까 원칙대로 할 거야

여기서 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>');
  }
}

HTML5 의 경우는, 「프리페치」를 사용할 수 있습니다.

<link rel="prefetch" href="/style.css" as="style" />

js의 '프리로드'를 확인합니다.

<link rel="preload" href="used-later.js" as="script">

스크립트의 로드가 느린 이유 중 하나는 페이지를 로드하는 동안 모든 스크립트를 실행하고 있을 때 다음과 같이 됩니다.

callMyFunctions();

다음 대신:

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

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

로딩 시간을 줄여 사용자 경험을 향상시키려면 "화면 로딩" 옵션을 선택하지 않습니다.내 생각에 그것은 단순히 페이지를 더 느리게 로딩하는 것보다 훨씬 더 짜증날 것 같아.

모더니즈를 한번 봐주셨으면 합니다.이것은 작은 경량 라이브러리입니다.파일이 로딩되어 있는지 확인하고 지정한 다른 쪽 스크립트로 스크립트를 실행할 수 있는 기능을 사용하여 Javascript를 비동기적으로 로드할 수 있습니다.

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'
  }
]);

다음 Wiki 기사가 흥미롭습니다.http://ajaxpatterns.org/On-Demand_Javascript

그런 기술을 언제 어떻게 사용해야 하는지에 대해 설명하고 있습니다.

음.x.parentNodeHEAD 요소가 반환되므로 헤드 태그 바로 앞에 스크립트를 삽입합니다.어쩌면 그것이 문제일 수도 있어.

해라x.parentNode.appendChild()대신.

이 https://github.com/stephen-lazarionok/async-resource-loader 를 확인해 주세요.JS, CSS 및 여러 파일을 원샷으로 로드하는 예를 보여줍니다.

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'
})

Elements로의 을 활용하거나 "XHR Injection" "Script DOM Elements" 를 사용하여 태그를 .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 repo : https://github.com/mudroljub/js-async-loader

예를 들어 Respect에서 사용하는 경우 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`)
  }
}

간결한 답변, 코드의 설명

function loadScript(src) {
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
//
// script.async = false; // uncomment this line and scripts will be executed in the document order, like 'defer' option
//
// script.defer = true; // uncomment this line when scripts need whole DOM and/or relative order execution is important
//
// the script starts loading as it's append to the document and dynamic script behave as “async” by default
// other scripts don’t wait for 'async' scripts, and 'async' scripts don’t wait for them
// scripts that loads first – runs first (“load-first” order)
document.body.append(script); 
}

loadScript('js/example01.js');
loadScript('js/example02.js');

/* 
the 'defer' attribute tells the browser not to wait for the script
the 'async' attribute make script to load in the background and run when ready
the 'async' and 'defer' attribute are only for external scripts
'defer' is used for scripts that need the whole DOM and/or their relative execution order is important
'async' is used for independent scripts, like counters or ads, when their relative execution order does not matter
More: https://javascript.info/script-async-defer
*/

LABJS 또는 Requere를 사용할 수 있습니다.JS

(「」등)LABJS,RequireJS코드 속도와 품질이 향상됩니다.

const dynamicScriptLoading = async (src) =>
{
    const response = await fetch(src);
    const dataResponse = await response.text();
    eval.apply(null, [dataResponse]);
}

먼저 파일 최소화를 검토하여 속도를 크게 높일 수 있는지 알아보는 것이 좋습니다.호스트의 속도가 느린 경우는, 그 스태틱한 컨텐츠를 CDN 에 보존해 보겠습니다.

언급URL : https://stackoverflow.com/questions/7718935/load-scripts-asynchronously

반응형