IT

자바 스크립트 파일을 동적으로로드

lottoking 2020. 6. 5. 08:14
반응형

자바 스크립트 파일을 동적으로로드


JavaScript 파일을 어떻게 안정적으로 동적으로로드 할 수 있습니까? 이것은 '초기화'될 때 컴포넌트가 필요할 때 필요한 모든 JavaScript 라이브러리 스크립트를 동적으로로드하는 모듈 또는 컴포넌트를 구현하는 데 사용될 수 있습니다.

구성 요소를 사용하는 클라이언트는이 구성 요소 <script>를 구현하는 모든 라이브러리 스크립트 파일을로드 하거나 웹 페이지에 수동으로 태그를 삽입 할 필요가 없습니다. 단지 '기본'구성 요소 스크립트 파일입니다.

주류 JavaScript 라이브러리는 어떻게 이것을 수행합니까 (시제품, jQuery 등)? 이러한 도구는 여러 JavaScript 파일을 재배포 가능한 단일 '빌드'버전의 스크립트 파일로 병합합니까? 아니면 보조 '라이브러리'스크립트를 동적으로로드합니까?

이 질문에 추가 : 동적으로 포함 된 JavaScript 파일이로드 된 후 이벤트를 처리하는 방법이 있습니까? 프로토 타입은 document.observe문서 전체 이벤트에 사용됩니다. 예:

document.observe("dom:loaded", function() {
  // initially hide all containers for tab content
  $$('div.tabcontent').invoke('hide');
});

스크립트 요소에 사용 가능한 이벤트는 무엇입니까?


Prototype을 사용하여 동적 스크립트 태그를 작성할 수 있습니다 .

new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});

여기서 문제 는 외부 스크립트 파일이 언제 완전히로드 되는지 알 수 없다는 것 입니다.

우리는 종종 다음 줄에 종속 코드를 원하고 다음과 같이 작성하려고합니다.

if (iNeedSomeMore) {
    Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
    myFancyMethod(); // cool, no need for callbacks!
}

콜백없이 스크립트 종속성을 주입하는 현명한 방법이 있습니다. 동기식 AJAX 요청을 통해 스크립트를 가져 와서 글로벌 수준에서 스크립트를 평가하면됩니다.

프로토 타입을 사용하는 경우 Script.load 메소드는 다음과 같습니다.

var Script = {
    _loadedScripts: [],
    include: function(script) {
        // include script only once
        if (this._loadedScripts.include(script)) {
            return false;
        }
        // request file synchronous
        var code = new Ajax.Request(script, {
            asynchronous: false,
            method: "GET",
            evalJS: false,
            evalJSON: false
        }).transport.responseText;
        // eval code on global level
        if (Prototype.Browser.IE) {
            window.execScript(code);
        } else if (Prototype.Browser.WebKit) {
            $$("head").first().insert(Object.extend(
                new Element("script", {
                    type: "text/javascript"
                }), {
                    text: code
                }
            ));
        } else {
            window.eval(code);
        }
        // remember included script
        this._loadedScripts.push(script);
    }
};

자바 스크립트에는 가져 오기 / 포함 / 요구 사항이 없지만 원하는 것을 달성하는 두 가지 주요 방법이 있습니다.

1-AJAX 호출로로드 한 다음 eval을 사용할 수 있습니다.

이것은 가장 간단한 방법이지만 Javascript 안전 설정으로 인해 도메인으로 제한되며 eval을 사용하면 버그와 해킹의 문이 열립니다.

2-HTML에서 스크립트 URL로 스크립트 태그를 추가하십시오.

확실히 가장 좋은 방법입니다. 외부 서버에서도 스크립트를로드 할 수 있으며 브라우저 파서를 사용하여 코드를 평가할 때 깔끔합니다. 웹 페이지의 헤드 또는 바디의 하단에 태그를 넣을 수 있습니다.

이 두 솔루션 모두 여기에서 설명하고 설명합니다.

이제 알아야 할 큰 문제가 있습니다. 그렇게하면 원격으로 코드를로드 할 수 있습니다. 최신 웹 브라우저는 성능을 향상시키기 위해 모든 것을 비동기식으로로드하기 때문에 파일을로드하고 현재 스크립트를 계속 실행합니다.

즉, 이러한 트릭을 직접 사용하는 경우 새로로드 된 코드를로드 요청 후 다음 줄에서 사용할 수 없습니다.로드가 계속 진행 중이기 때문입니다.

EG : my_lovely_script.js에 MySuperObject가 포함되어 있습니다

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

그런 다음 F5를 치는 페이지를 다시로드하십시오. 그리고 작동합니다! 혼란스러운 ...

그래서 어떻게해야합니까?

글쎄, 당신은 내가 준 링크에서 저자가 제안한 해킹을 사용할 수 있습니다. 요약하자면, 급한 사람들을 위해, 그는 en 이벤트를 사용하여 스크립트가로드 될 때 콜백 함수를 실행합니다. 따라서 콜백 함수에서 원격 라이브러리를 사용하여 모든 코드를 넣을 수 있습니다. EG :

function loadScript(url, callback)
{
    // adding the script tag to the head as suggested before
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = url;

   // then bind the event to the callback function 
   // there are several events for cross browser compatibility
   script.onreadystatechange = callback;
   script.onload = callback;

   // fire the loading
   head.appendChild(script);
}

그런 다음 스크립트가 람다 함수에로드 된 후 사용하려는 코드를 작성하십시오.

var myPrettyCode = function() {
    // here, do what ever you want
};

그런 다음 모든 것을 실행하십시오.

loadScript("my_lovely_script.js", myPrettyCode);

알았어 그러나이 모든 것을 쓰는 것은 고통입니다.

이 경우 항상 환상적인 무료 jQuery 프레임 워크로 사용할 수 있으므로 한 줄에서 동일한 작업을 수행 할 수 있습니다.

$.getScript("my_lovely_script.js", function() {
    alert("Script loaded and executed.");
    // here you can use anything you defined in the loaded script
});

jQuery 와 함께 훨씬 덜 복잡한 버전을 최근에 사용했습니다 .

<script src="scripts/jquery.js"></script>
<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  var $head = $("head");
  for (var i = 0; i < js.length; i++) {
    $head.append("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

IE6 / 7, Firefox, Safari, Opera에서 테스트 한 모든 브라우저에서 훌륭하게 작동했습니다.

업데이트 : jQuery가없는 버전 :

<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  for (var i = 0, l = js.length; i < l; i++) {
    document.getElementsByTagName("head")[0].innerHTML += ("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

나는 기본적으로 당신이 아담과했던 것과 똑같은 일을했지만, 일을 끝내기 위해 헤드 태그에 추가되도록 약간 수정했습니다. 스크립트와 CSS 파일을 모두 처리하기 위해 include 함수 (아래 코드)를 만들었습니다.

이 함수는 또한 스크립트 또는 CSS 파일이 이미 동적으로로드되지 않았는지 확인합니다. 수작업으로 코딩 된 값을 확인하지 않으며 더 나은 방법이 있었지만 그 목적을 달성했습니다.

function include( url, type ){
    // First make sure it hasn't been loaded by something else.
    if( Array.contains( includedFile, url ) )
        return;

    // Determine the MIME-type
    var jsExpr = new RegExp( "js$", "i" );
    var cssExpr = new RegExp( "css$", "i" );
    if( type == null )
        if( jsExpr.test( url ) )
            type = 'text/javascript';
        else if( cssExpr.test( url ) )
            type = 'text/css';

    // Create the appropriate element.
    var tag = null;
    switch( type ){
        case 'text/javascript' :
            tag = document.createElement( 'script' );
            tag.type = type;
            tag.src = url;
            break;
        case 'text/css' :
            tag = document.createElement( 'link' );
            tag.rel = 'stylesheet';
            tag.type = type;
            tag.href = url;
            break;
    }

    // Insert it to the <head> and the array to ensure it is not
    // loaded again.
    document.getElementsByTagName("head")[0].appendChild( tag );
    Array.add( includedFile, url );
}

또 다른 멋진 답변

$.getScript("my_lovely_script.js", function(){


   alert("Script loaded and executed.");
  // here you can use anything you defined in the loaded script

 });

https://stackoverflow.com/a/950146/671046


여기 내가 찾은 예제 코드가 있습니다 ... 누군가 더 나은 방법이 있습니까?

  function include(url)
  {
    var s = document.createElement("script");
    s.setAttribute("type", "text/javascript");
    s.setAttribute("src", url);
    var nodes = document.getElementsByTagName("*");
    var node = nodes[nodes.length -1].parentNode;
    node.appendChild(s);
  }

jQuery를 이미로드 한 경우 $ .getScript 를 사용해야합니다 .

이것은 (여러 코드가 실행되기 전에 스크립트가로드되도록 보장하기 위해) 내장 된 콜백 함수를 가지고 있으며 캐싱을 제어 할 수 있다는 점에서 다른 답변보다 이점이 있습니다.


더 나은 방법이 있습니까?

본문에 스크립트를 추가하는 것이 페이지의 마지막 노드에 추가하는 것이 더 쉽다고 생각합니다. 이건 어때요:

function include(url) {
  var s = document.createElement("script");
  s.setAttribute("type", "text/javascript");
  s.setAttribute("src", url);
  document.body.appendChild(s);
}

나는 그물에서 찾은 또 다른 솔루션을 사용했습니다 ...이 솔루션은 creativecommons에 있으며 함수를 호출하기 전에 소스가 포함되어 있는지 확인합니다 ...

여기에서 파일을 찾을 수 있습니다 : include.js

/** include - including .js files from JS - bfults@gmail.com - 2005-02-09
 ** Code licensed under Creative Commons Attribution-ShareAlike License 
 ** http://creativecommons.org/licenses/by-sa/2.0/
 **/              
var hIncludes = null;
function include(sURI)
{   
  if (document.getElementsByTagName)
  {   
    if (!hIncludes)
    {
      hIncludes = {}; 
      var cScripts = document.getElementsByTagName("script");
      for (var i=0,len=cScripts.length; i < len; i++)
        if (cScripts[i].src) hIncludes[cScripts[i].src] = true;
    }
    if (!hIncludes[sURI])
    {
      var oNew = document.createElement("script");
      oNew.type = "text/javascript";
      oNew.src = sURI;
      hIncludes[sURI]=true;
      document.getElementsByTagName("head")[0].appendChild(oNew);
    }
  }   
} 

YUI 3 의 훌륭한 기능에 대해 알게되었습니다 (작성 시점에 미리보기 릴리스에서 사용 가능). 너무 많은 코드없이 YUI 라이브러리 및 "외부"모듈 (원하는 것)에 대한 종속성을 쉽게 삽입 할 수 있습니다 : YUI Loader .

또한 외부 모듈이로드 되 자마자 호출되는 함수에 관한 두 번째 질문에 답변합니다.

예:

YUI({
    modules: {
        'simple': {
            fullpath: "http://example.com/public/js/simple.js"
        },
        'complicated': {
            fullpath: "http://example.com/public/js/complicated.js"
            requires: ['simple']  // <-- dependency to 'simple' module
        }
    },
    timeout: 10000
}).use('complicated', function(Y, result) {
    // called as soon as 'complicated' is loaded
    if (!result.success) {
        // loading failed, or timeout
        handleError(result.msg);
    } else {
        // call a function that needs 'complicated'
        doSomethingComplicated(...);
    }
});

나를 위해 완벽하게 일했으며 종속성 관리의 이점이 있습니다. YUI 2 일정표가 있는 는 YUI 설명서를 참조하십시오 .


SYNC 스크립트로드 를 원하면 HTML HEAD 태그에 스크립트 텍스트를 직접 추가해야합니다. 그대로 추가하면 ASYNC 로드 가 트리거됩니다 . 외부 파일에서 스크립트 텍스트를 동 기적으로로드하려면 XHR을 사용하십시오. 빠른 샘플 아래 (이 게시물 및 다른 게시물에서 다른 답변의 일부를 사용하고 있음) :

/*sample requires an additional method for array prototype:*/

if (Array.prototype.contains === undefined) {
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) { if (this[i] === obj) return true; }
    return false;
};
};

/*define object that will wrap our logic*/
var ScriptLoader = {
LoadedFiles: [],

LoadFile: function (url) {
    var self = this;
    if (this.LoadedFiles.contains(url)) return;

    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                self.LoadedFiles.push(url);
                self.AddScript(xhr.responseText);
            } else {
                if (console) console.error(xhr.statusText);
            }
        }
    };
    xhr.open("GET", url, false);/*last parameter defines if call is async or not*/
    xhr.send(null);
},

AddScript: function (code) {
    var oNew = document.createElement("script");
    oNew.type = "text/javascript";
    oNew.textContent = code;
    document.getElementsByTagName("head")[0].appendChild(oNew);
}
};

/*Load script file. ScriptLoader will check if you try to load a file that has already been loaded (this check might be better, but I'm lazy).*/

ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
/*this will be executed right after upper lines. It requires jquery to execute. It requires a HTML input with id "tb1"*/
$(function () { alert($('#tb1').val()); });

최근 Chrome 및 Safari에 통합 된 dynamic import 라는 새로운 제안 된 ECMA 표준이 있습니다.

const moduleSpecifier = './dir/someModule.js';

import(moduleSpecifier)
   .then(someModule => someModule.foo()); // executes foo method in someModule

직장에서 사용하는 기술은 AJAX 요청을 사용하여 javascript 파일을 요청한 다음 eval () 반환하는 것입니다. 프로토 타입 라이브러리를 사용하는 경우 Ajax.Request 호출에서이 기능을 지원합니다.


jquery는 .append () 함수 로이 문제를 해결했습니다 . 전체 jquery UI 패키지를로드하는 데 사용되었습니다.

/*
 * FILENAME : project.library.js
 * USAGE    : loads any javascript library
 */
    var dirPath = "../js/";
    var library = ["functions.js","swfobject.js","jquery.jeditable.mini.js","jquery-ui-1.8.8.custom.min.js","ui/jquery.ui.core.min.js","ui/jquery.ui.widget.min.js","ui/jquery.ui.position.min.js","ui/jquery.ui.button.min.js","ui/jquery.ui.mouse.min.js","ui/jquery.ui.dialog.min.js","ui/jquery.effects.core.min.js","ui/jquery.effects.blind.min.js","ui/jquery.effects.fade.min.js","ui/jquery.effects.slide.min.js","ui/jquery.effects.transfer.min.js"];

    for(var script in library){
        $('head').append('<script type="text/javascript" src="' + dirPath + library[script] + '"></script>');
    }

jquery.js를 가져온 후 html / php / etc의 헤드에서 사용하려면 이 파일을 포함시켜 라이브러리 전체에로드하여 헤드에 추가하십시오 ...

<script type="text/javascript" src="project.library.js"></script>

멋지고 짧고 간단하며 유지 관리가 가능합니다! :]

// 3rd party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
    FULL_PATH + 'plugins/script.js'      // Script example
    FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library 
    FULL_PATH + 'plugins/crypto-js/hmac-sha1.js',      // CryptoJS
    FULL_PATH + 'plugins/crypto-js/enc-base64-min.js'  // CryptoJS
];

function load(url)
{
    var ajax = new XMLHttpRequest();
    ajax.open('GET', url, false);
    ajax.onreadystatechange = function ()
    {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4)
        {
            switch(ajax.status)
            {
                case 200:
                    eval.apply( window, [script] );
                    console.log("library loaded: ", url);
                    break;
                default:
                    console.log("ERROR: library not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

 // initialize a single load 
load('plugins/script.js');

// initialize a full load of scripts
if (s.length > 0)
{
    for (i = 0; i < s.length; i++)
    {
        load(s[i]);
    }
}

이 코드는 간단한 기능의 예일 뿐이며 모든 플랫폼에서 완벽하게 지원하기 위해 추가 기능 기능 필요할 있습니다.


이 목적을 위해 특별히 설계된 스크립트가 있습니다.

yepnope.js 는 Modernizr에 내장되어 있으며 lab.js 는보다 최적화 된 버전이지만 사용자 친화적 인 버전은 아닙니다 .

jquery 나 프로토 타입과 같은 큰 라이브러리를 통해이 작업을 수행하지 않는 것이 좋습니다. 스크립트 로더의 주요 이점 중 하나는 스크립트를 일찍로드 할 수 있다는 것입니다 .jquery 및 모든 DOM 요소가로드 될 때까지 기다릴 필요가 없습니다. 검사를 실행하여 스크립트를 동적으로로드할지 확인하십시오.


JavaScript로 모듈 스크립트 가져 오기 / 포함 작업을 자동화하는 간단한 모듈을 작성했습니다. 시도해보고 피드백을 남겨주세요! :) 코드에 대한 자세한 설명은 다음 블로그 게시물을 참조하십시오 : http://stamat.wordpress.com/2013/04/12/javascript-require-import-include-modules/

var _rmod = _rmod || {}; //require module namespace
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(scriptname) {
    var scriptelems = document.getElementsByTagName('script');
    for (var i = 0; i < scriptelems.length; i++) {
        if (scriptelems[i].src.endsWith(scriptname)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = scriptelems[i].src.substring(0, scriptelems[i].length - scriptname.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark the root directory of your library, any library


_rmod.injectScript = function(scriptname, uri, callback, prepare) {

    if(!prepare)
        prepare(scriptname, uri);

    var scriptelem = document.createElement('script');
    scriptelem.type = 'text/javascript';
    scriptelem.title = scriptname;
    scriptelem.src = uri;
    scriptelem.async = true;
    scriptelem.defer = false;

    if(!callback)
        scriptelem.onload = function() {
            callback(scriptname, uri);
        };

    document.getElementsByTagName('head')[0].appendChild(scriptelem);
};

_rmod.requirePrepare = function(scriptname, uri) {
    _rmod.loading.scripts[scriptname] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(scriptname, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[scriptname];
    _rmod.imported[scriptname] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

//you can rename based on your liking. I chose require, but it can be called include or anything else that is easy for you to remember or write, except import because it is reserved for future use.
var require = function(scriptname) {
    var np = scriptname.split('.');
    if (np[np.length-1] === '*') {
        np.pop();
        np.push('_all');
    }

    scriptname = np.join('.');
    var uri = _rmod.libpath + np.join('/')+'.js';
    if (!_rmod.loading.scripts.hasOwnProperty(scriptname) 
     && !_rmod.imported.hasOwnProperty(scriptname)) {
        _rmod.injectScript(scriptname, uri, 
            _rmod.requireCallback, 
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};

// ----- USAGE -----

require('ivar.util.array');
require('ivar.util.string');
require('ivar.net.*');

ready(function(){
    //do something when required scripts are loaded
});

이 모든 샘플에서 잃어 버렸지 만 오늘은 기본 .js에서 외부 .js를로드해야했으며 다음과 같이했습니다.

document.write("<script src='https://www.google.com/recaptcha/api.js'></script>");

다음 은 콜백 및 IE를 지원하는 간단한 것입니다.

function loadScript(url, callback) {

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState) { //IE
        script.onreadystatechange = function () {
            if (script.readyState == "loaded" || script.readyState == "complete") {
                script.onreadystatechange = null;
                callback();
            }
        };
    } else { //Others
        script.onload = function () {
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

loadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {

     //jQuery loaded
     console.log('jquery loaded');

});

여기에 좋은 기사입니다, 내 대답은 조금 늦게이 질문에 대한 알지만, www.html5rocks.com - 딥 다이빙 스크립트로드의 어두운 바다에가 .

이 기사에서는 브라우저 지원과 관련하여 컨텐츠 렌더링을 차단하지 않고 JavaScript 파일을 동적으로로드하는 가장 좋은 방법은 다음과 같습니다.

네 개의 스크립트 이름 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') {
    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>');
  }
}

몇 가지 트릭과 축소는 나중에 362 바이트입니다.

!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
  "//other-domain.com/1.js",
  "2.js"
])

이 같은...

<script>
     $(document).ready(function() {
          $('body').append('<script src="https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places&callback=getCurrentPickupLocation" async defer><\/script>');
     });
</script>

다음은 JS 파일을로드하는 함수의 간단한 예입니다. 관련 포인트 :

  • jQuery가 필요하지 않으므로 처음에 jQuery.js 파일을로드하는 데 사용할 수 있습니다
  • 콜백과 비동기입니다.
  • 로드 된 URL 레코드가있는 엔클로저를 유지하여 네트워크 사용을 피하므로 한 번만로드되도록합니다.
  • jQuery $.ajax반대로 또는 $.getScriptnonces를 사용하여 CSP 문제를 해결할 수 있습니다 unsafe-inline. 그냥 속성을 사용하십시오script.nonce
var getScriptOnce = function() {

    var scriptArray = []; //array of urls (closure)

    //function to defer loading of script
    return function (url, callback){
        //the array doesn't have such url
        if (scriptArray.indexOf(url) === -1){

            var script=document.createElement('script');
            script.src=url;
            var head=document.getElementsByTagName('head')[0],
                done=false;

            script.onload=script.onreadystatechange = function(){
                if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
                    done=true;
                    if (typeof callback === 'function') {
                        callback();
                    }
                    script.onload = script.onreadystatechange = null;
                    head.removeChild(script);

                    scriptArray.push(url);
                }
            };

            head.appendChild(script);
        }
    };
}();

이제는 간단히

getScriptOnce("url_of_your_JS_file.js");

js 라이브러리를로드하는 데 두 줄 이상의 코드가 필요하다고 생각하는 사람들을위한 터무니없는 한 줄짜리 : P

await new Promise((resolve, reject) => {let js = document.createElement("script"); js.src="mylibrary.js"; js.onload=resolve; js.onerror=reject; document.body.appendChild(js)});

가져 오려는 스크립트가 모듈 인 경우이 import(...)기능을 사용할 수 있습니다 .


Firefox 67 이상에서 동적 모듈 가져 오기가 시작되었습니다 .

(async () => {
   await import('./synth/BubbleSynth.js')
})()

오류 처리 :

(async () => {
    await import('./synth/BubbleSynth.js').catch((error) => console.log('Loading failed' + error))
})()

https://caniuse.com/#feat=es6-module-dynamic-import


jscript, prototype, YUI와 같은 모든 주요 자바 스크립트 라이브러리는 스크립트 파일로드를 지원합니다. 예를 들어 YUI에서 코어를로드 한 후 다음을 수행하여 캘린더 컨트롤을로드 할 수 있습니다.

var loader = new YAHOO.util.YUILoader({

    require: ['calendar'], // what components?

    base: '../../build/',//where do they live?

    //filter: "DEBUG",  //use debug versions (or apply some
                        //some other filter?

    //loadOptional: true, //load all optional dependencies?

    //onSuccess is the function that YUI Loader
    //should call when all components are successfully loaded.
    onSuccess: function() {
        //Once the YUI Calendar Control and dependencies are on
        //the page, we'll verify that our target container is 
        //available in the DOM and then instantiate a default
        //calendar into it:
        YAHOO.util.Event.onAvailable("calendar_container", function() {
            var myCal = new YAHOO.widget.Calendar("mycal_id", "calendar_container");
            myCal.render();
        })
     },

    // should a failure occur, the onFailure function will be executed
    onFailure: function(o) {
        alert("error: " + YAHOO.lang.dump(o));
    }

 });

// Calculate the dependency and insert the required scripts and css resources
// into the document
loader.insert();

참고 URL : https://stackoverflow.com/questions/21294/dynamically-load-a-javascript-file

반응형