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


167

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

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


답변:


84

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

교차 도메인에서 작동하도록하려면 어떻게해야합니까? (에서 스크립트로드 http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js)
user2284570


@Ciastopiekarz : 나는 통제하지 않는다 web.archive.org.
user2284570

그럼 당신은 다른 프로그램을 사용하여 액세스 원하는 데이터를 긁어해야하고 자신에게 제공
데이비드 슈만

Ajax.Request 란 무엇입니까?
bluejayke

72

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

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

11
이 답변이 얼마나 과소 평가되었는지 믿을 수 없습니다. 감사합니다.
naftalimich

2
사람들이 첫 번째 행을 지나쳐 읽는 것을 좋아하지 않기 때문에 "만약이 세 가지 비밀 단계를 따라 성공하면 부자가 될 것"이라고 약속하지 않는 한 내기이다.
Costa

작동합니다. 여기에 내 경험을 공유하면 많은 시간을 보냈기 때문에 시간이 절약되기를 바랍니다. Angular 6과 적용된 템플릿 (html, css, jquery)을 사용하고 있습니다. 문제는 템플릿에 리스너 이벤트를 첨부하기 위해 html 요소가로드 된 후로드되는 js 파일이 있다는 것입니다. 각도 앱이로드 된 후 그 js 파일을 실행하기가 어려웠습니다. angular app (angular.json) 스크립트 태그에 추가하면 번들로 묶이지 만로드 후 해당 js 파일은 실행되지 않습니다. typescript로 다시 작성하기에는 너무 많은 코드이므로 큰 도움이되었습니다. 다음 의견 저는 댓글 길이 때문에 예제를
하겠습니다

이 코드를 다음과 같이 간단하게 사용했습니다. ngAfterViewInit () {debugger; $ .getScript ( "/ assets / js / jquery.app.js", function () {alert ( "스크립트가로드되어 실행되었습니다."); // 여기서로드 된 스크립트에 정의한 모든 것을 사용할 수 있습니다}); }
Nour Lababidi

각도에서 '$'에 대해 나는 이것을 따랐다 : stackoverflow.com/questions/32050645/…
Nour Lababidi

28

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

25
jquery를로드하려고하지 않는 한 훌륭합니다.

1
jQuery가 향후 릴리스를 위해 Require plugin을 jQuery Core로 롤링 할 것 같습니다 : plugins.jquery.com/project/require
Adam

1
jQuery를 사용하는 더 좋은 방법은을 사용하는 것 $.getScript입니다. 내 대답을 참조하십시오.
Muhd

1
Modernizr (yepnope.js) 또는 lab.js가 이에 적합한 솔루션입니다. 무거운 스크립트 라이브러리 (먼저로드해야 함)를 사용하는 것은 모바일 또는 기타 여러 상황에 가장 적합한 답변이 아닙니다.
1nfiniti

2
@MaulikGangani 이전 브라우저 및 html 유효성 검사기는이를 스크립트를 종료하는 토큰으로 해석합니다.
travis

20

나는 기본적으로 당신이 Adam과했던 것과 똑같은 일을했지만, 일을 끝내기 위해 head 태그에 추가되도록 약간 수정했습니다. 스크립트와 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 );
}

그 피클보다 더 많은 맥락이 없으면 제안이 없을 것 같습니다. 위의 코드는 그대로 작동하며 작동하는 프로젝트에서 직접 가져 왔습니다.
palehorse

5
@palehorse, Mike 및 Muhd는 옳습니다. 프로젝트에서 작동 할 수 있지만 프로젝트의 다른 곳에 "includedFile"및 "Array"변수를 정의해야하기 때문에이 코드는 실행되지 않습니다. 프로젝트의 컨텍스트 밖에서 작동하거나 적어도 정의되지 않은 변수 (유형 등)를 설명하는 주석을 추가하는 것이
좋습니다.

14

또 다른 멋진 답변

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


2
교차 도메인에서 작동하도록하려면 어떻게해야합니까? (에서 스크립트로드 http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js)
user2284570

9

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

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

교차 도메인에서 작동하도록하려면 어떻게해야합니까? (에서 스크립트로드 http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js)
user2284570

6

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

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


4

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

3

더 나은 방법이 있습니까?

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

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

교차 도메인에서 작동하도록하려면 어떻게해야합니까? (에서 스크립트로드 http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js)
user2284570

3

나는 그물에서 찾은 또 다른 솔루션을 사용했습니다 ...이 솔루션은 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);
    }
  }   
} 

교차 도메인에서 작동하도록하려면 어떻게해야합니까? (에서 스크립트로드 http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStu‌​ff/userjs/aagmfunctions.js)
user2284570

3

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

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

예:

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 설명서를 참조하십시오 .


YUI가이 기능만으로 외설스럽게 커지는 것을 제외하고는 아마도 이상적 일 것입니다.
Muhd

3

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

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

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

2

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


2

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>

2

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

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

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


2

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

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

오류 처리 :

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

또한 모든 종류의 비 모듈 라이브러리에서 작동합니다.이 경우 lib는 창 객체에서 구식으로 사용할 수 있지만 요청시에만 가능합니다.

suncalc.js를 사용하는 예제 에서 서버는 이런 방식으로 작동 하도록 CORS를 활성화 해야합니다 !

(async () => {
 await import('https://cdnjs.cloudflare.com/ajax/libs/suncalc/1.8.0/suncalc.min.js')
 .then(function(){
   let times = SunCalc.getTimes(new Date(), 51.5,-0.1);
   console.log("Golden Hour today in London: " + times.goldenHour.getHours() + ':' + times.sunrise.getMinutes() + ". Take your pics!")
  })
})()

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


1

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

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

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


1

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(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.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(script_name, uri, callback, prepare) {

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

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

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };

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

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

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = 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(script_name) {
    var np = script_name.split('.');
    if (np[np.length-1] === '*') {
        np.pop();
        np.push('_all');
    }

    script_name = np.join('.');
    var uri = _rmod.libpath + np.join('/')+'.js';
    if (!_rmod.loading.scripts.hasOwnProperty(script_name) 
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, 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
});

1

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

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

당신은 링크를 볼 수 있습니다 : 답변
asmmahmud

1

다음 은 콜백 및 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');

});

1

여기에 좋은 기사입니다, 내 대답은 조금 늦게이 질문에 대한 알지만, 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"
])

나는 크롬 및 파이어 폭스에서 잘 작동하지만 IE 브라우저에서 문제에 직면의 접근 방식보다 사용하고
씨의 Roshan

1

이 같은...

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

1

다음은 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");

1

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(...)기능을 사용할 수 있습니다 .


1

Promises를 사용하면 이와 같이 단순화 할 수 있습니다. 로더 기능 :

  const loadCDN = src =>
    new Promise((resolve, reject) => {
      if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
      const script = document.createElement("script")
      script.src = src
      script.async = true
      document.head.appendChild(script)
      script.onload = resolve
      script.onerror = reject
    })

사용법 (비동기 / 대기) :

await loadCDN("https://.../script.js")

사용법 (약속) :

loadCDN("https://.../script.js").then(res => {}).catch(err => {})

참고 : 비슷한 솔루션이 있지만 스크립트가 이미로드되어 있고 매번 스크립트를로드하는지 확인하지 않습니다. 이것은 src 속성을 확인합니다.


0

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

당신은 링크를 볼 수 있습니다 : 답변
asmmahmud

0

위의 게시물 중 일부를 실제 예제로 조정했습니다. 여기에 css와 js를 같은 배열로 줄 수 있습니다.

$(document).ready(function(){

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 jsScriptCssLoader = {

jsExpr : new RegExp( "js$", "i" ),
cssExpr : new RegExp( "css$", "i" ),
loadedFiles: [],

loadFile: function (cssJsFileArray) {
    var self = this;
    // remove duplicates with in array
    cssJsFileArray.filter((item,index)=>cssJsFileArray.indexOf(item)==index)
    var loadedFileArray = this.loadedFiles;
    $.each(cssJsFileArray, function( index, url ) {
            // if multiple arrays are loaded the check the uniqueness
            if (loadedFileArray.contains(url)) return;
            if( self.jsExpr.test( url ) ){
                $.get(url, function(data) {
                    self.addScript(data);
                });

            }else if( self.cssExpr.test( url ) ){
                $.get(url, function(data) {
                    self.addCss(data);
                });
            }

            self.loadedFiles.push(url);
    });

    // don't load twice accross different arrays

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

};


//jsScriptCssLoader.loadFile(["css/1.css","css/2.css","css/3.css"]);
jsScriptCssLoader.loadFile(["js/common/1.js","js/2.js","js/common/file/fileReader.js"]);
});

0

원 라이너를 좋아하는 분들을 위해 :

import('./myscript.js');

다음과 같은 오류가 발생할 수 있습니다.

CORS 정책에 의해 원점 ' http://127.0.0.1 ' 에서 ' http : //..../myscript.js '의 스크립트에 대한 액세스 가 CORS 정책에 의해 차단되었습니다. 'Access-Control-Allow-Origin'헤더가 없습니다. 요청 된 자원

이 경우 다음으로 대체 할 수 있습니다.

fetch('myscript.js').then(r => r.text()).then(t => new Function(t)());
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.