スクリプトを非同期にロードする


125

いくつかのプラグイン、カスタムウィジェット、および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関数が他の関数に依存しているためだと思いました。しかし、タイムアウト関数を使用してそれらを正しい順序でロードし、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

そして奇妙な部分は、すべてのスタイルの作業とすべてのJavaScript関数です。ページが何らかの理由でフリーズしています...

回答:


176

非同期読み込みのいくつかのソリューション:

//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返されたpromiseがコールバックを処理するため、このバージョンは引数を受け入れないことに注意してください。以前はあったはずだったものloadScript(src, callback)が今ではloadScript(src).then(callback)

これには、障害を検出して処理できるという追加のボーナスがあります。たとえば、...

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

...そして、CDNの停止を適切に処理します。


私はそれを試し始めようとしています。しかし、ページを別のページにリダイレクトしたときにそれらのスクリプトを別のページにロードし、そのページに同じスクリプトが含まれている場合、ロードに時間がかかりません。彼らは正しいキャッシュにあるべきですか?代わりにその手法を実装する必要はありませんか?
遠野ナム

1
子を変更して、本文ではなくheadタグに追加しました... ..var x = document.getElementsByTagName( 'head')[0]; x.appendChild(s);
Tono Nam

1
@TonoNam、あなたは単に使用することができますがdocument.head.appendChild、スクリプトをに追加することでいくつかのニッチな問題があり<head>ます。スクリプトの読み込みと実行を妨げるものはありません。
zzzzBov 2011年

1
(t.parentではなく)t.parentNode.insertBeforeを使用する必要がありました。
Phil LaNasa

1
@MuhammadUmer、document.writeドキュメントが読み込まれる前に追加のスクリプトタグを記述している場合、スクリプトはページの読み込みの一部として同期的に実行され、独自の非同期コールバック動作は含まれません。スクリプト要素を作成してページに追加する場合は、非同期にトリガーするイベントリスナーを追加するアクセス権があります。tl; dr: JSでスクリプトをロードする方法に依存します。
zzzzBov 2014年

33

HTML5の新しい 'async'属性がそのトリックを行うことになっています。IEに関心がある場合は、ほとんどのブラウザでも「defer」がサポートされています。

async-HTML

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

defer-HTML

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

新しいAdSense広告ユニットコードを分析していると、属性に気づき、検索がここに導いてくれました:http : //davidwalsh.name/html5-async


stackoverflow.com/questions/2774373/…を読んだ後の私の理解から、asynはロード用ではなく、含まれているjavascriptをいつ実行するかを決定するためのものです。
JackDev 2013

9
defer属性を使用すると、ドキュメントが読み込まれて解析され、操作できるようになるまで、ブラウザはスクリプトの実行を延期します。async属性を使用すると、ブラウザはスクリプトをできるだけ早く実行しますが、スクリプトのダウンロード中にドキュメントの解析をブロックしません
shuseel

1
「asynはロード用ではなく、含まれるJavaScriptをいつ実行するかを決定するためのものです」これは矛盾しません。すべての場合において、ブラウザはスクリプトをできるだけ早くロードし始めます。しかし、なし asyncdefer、それはそれロード中にレンダリングをブロックします。設定asyncは、スクリプトをできるだけ早くブロックして実行しないように指示します。設定deferはブロックしないように指示しますが、ページが完了するまでスクリプトの実行を待機します。通常、スクリプトに依存関係(jQueryなど)がない限り、スクリプトをできるだけ早く実行しても問題ありません。1つのスクリプトが別のスクリプトに依存している場合はonLoad、それを待つために使用します。
Stijn de Witt

@StijndeWitt非同期も据え置きも指定されていない場合はどうなりますか?
Mohammed Shareef C

@MohammedShareefCどちらも指定しない場合、同期動作によく似たものになります。ブラウザは、スクリプトをダウンロードして実行している間、それ以降の処理をブロックします。つまり、デフォルトの動作は同期です。ただし、これはパフォーマンスに悪影響を与えるため、ブラウザはできる限り回避します。CSSの解析、読み込み、適用などを続行できます。ただし、次のスクリプトフラグメントの実行を開始することはできません。だからものはブロックします。asyncを設定することで、ブラウザに問題がないことを伝え、自分で動作させることができます。
Stijn de Witt

8

スクリプトを非同期にロードしました(html 5にはその機能があります)。ロードが完了したすべてのスクリプトがページをindex2.htmlにリダイレクトし、index2.htmlは同じライブラリを使用しています。ページが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>

これに関するもう1つの良い点は、ローダーをページに配置し、ページの読み込みが完了するとローダーが消え、ミリ秒単位で新しいページが実行されることです。


1
@MohammedShareefC皮肉です。ものをプリロードするだけの特別なページは、SEOの賢明なアイデアのようには思えません。プリロードは素晴らしいですが、それを達成するためにリダイレクトする必要はありません。非表示のdivにリンクを貼り付けるだけで、ブラウザーが自動的に処理します。次にリダイレクトせずに、実際のページをレンダリングします。COPY-PASTERS READ THIS:このHTMLを使用する前に、ISO-88591エンコーディングをUTF-8に変更してください。そうすれば、残りのメンバーがすぐにエンコーディングの問題から抜け出すことができます。ありがとう!
Stijn de Witt


8

グーグルからの例

<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>

8

いくつかのメモ:

  • s.async = trueHTML5 doctypeにはあまり適切ではありません、正しいですs.async = 'async'コメントで指摘したamnのおかげで、実際に使用するのtrue は正しいですのすぐ下)
  • タイムアウトを使用して順序を制御することはあまり良くなく、安全ではありません。また、すべてのタイムアウトの合計と等しくなるように、ロード時間をはるかに長くします!

ファイルを非同期でロードする最近の理由があるので、順番に、例よりも機能主導の方法をお勧めします(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);
})();

4
s.async = trueある正しいです。プロパティasyncは、w3.org / TR / html5 / scripting-1.html#attr-script-asyncにあるW3CのHTML 5勧告でブール値として明示的に指定されています。async 属性asyncHTMLScriptElementDOMインターフェースを実装するオブジェクトによって公開されるプロパティを混同しています。実際、のような要素を介して要素の対応する属性を操作するElement.setAttribute場合はelement.setAttribute("async", "async")、すべてのHTML属性が何よりもまずテキストであるため、使用する必要があります。
午前

「ファイルを非同期でロードする最近の理由があるので、順番に、例よりも少し機能主導の方法をお勧めします[...]」。通常、非同期の方が「良い」ことはわかっていますが、「最近」の理由は何ですか。
BluE 2018

'if(!files.length)completed();'を変更しました 'return'を追加: 'if(!files.length){completed(); return;} '
フィル

4

HTML5のおかげで、タグに「async」を追加することで、非同期でロードするスクリプトを宣言できるようになりました。

<script async>...</script>

注:async属性は外部スクリプト専用です(src属性が存在する場合にのみ使用してください)。

注:外部スクリプトを実行するにはいくつかの方法があります。

  • 非同期が存在する場合:スクリプトはページの残りの部分と非同期で実行されます(ページが解析を続行している間、スクリプトが実行されます)
  • asyncが存在せず、deferが存在する場合:スクリプトは、ページの解析が終了したときに実行されます
  • 非同期も遅延も存在しない場合:ブラウザがページの解析を続ける前に、スクリプトがフェッチされてすぐに実行されます。

これを参照してください:http : //www.w3schools.com/tags/att_script_async.asp


2

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

2

これは非同期スクリプトの読み込みに対する現代的な優れたソリューションですが、それはasync falseで jsスクリプトに対処するだけですです。

www.html5rocks.comに書かれた素晴らしい記事があります - スクリプトロードのあいまいな水域の詳細

多くの可能な解決策を検討した後、著者は、jsスクリプトをbody要素の最後に追加することが、jsスクリプトによるページレンダリングのブロックを回避する最良の方法であると結論付けました。

それまでの間、著者はスクリプトを非同期でロードして実行することを切望している人々のために、別の良い代替ソリューションを追加しました。

4つの名前のスクリプトがあることを考える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でそれを「false」に設定することを理解していません。スクリプトが到着したらすぐに、任意の順序で実行します。

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

1

スクリプトの読み込みが非常に遅い理由の1つは、次のように、ページの読み込み中にすべてのスクリプトを実行している場合です。

callMyFunctions();

の代わりに:

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

このスクリプトの2番目のビットは、ブラウザーがすべてのJavaScriptコードを完全にロードするまで待機してから、スクリプトの実行を開始し、ページがより速くロードされたようにユーザーに見せます。

読み込み時間を短縮してユーザーエクスペリエンスを向上させたい場合は、「読み込み画面」オプションは使用しません。私の意見では、ページの読み込みが遅くなるよりもずっと面倒です。


1

Modernizrをご覧になることをお勧めします。ファイルがロードされているかどうかを確認し、指定した他のスクリプトを実行できる機能を備えた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'
  }
]);

1

私はこれを助けるために小さな投稿を書きました、あなたはここでもっと読むことができます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()


0

まあ、x.parentNodeHEAD要素を返すので、headタグの直前にスクリプトを挿入しています。多分それが問題です。

x.parentNode.appendChild()代わりに試してください。



0

LABJSまたはRequreJSを使用できます

以下のようなスクリプトローダはLABJSRequireJSあなたのコードの速度と品質を向上します。


0

フェッチインジェクションの使用を検討しましたか?このようなケースを処理するために、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


0

これが、レンダリングをブロックする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


1
機能しませんNo 'Access-Control-Allow-Origin' header is present on the requested resource
Abram


0

たとえば、誰かが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`)
  }
}


-3

最初にファイルを縮小することを検討し、それによって十分な速度向上が得られるかどうかを確認することをお勧めします。ホストが遅い場合は、静的コンテンツをCDNに配置してみてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.