다른 JavaScript 파일에 JavaScript 파일을 포함 시키려면 어떻게합니까?


5193

@import다른 JavaScript 파일에 JavaScript 파일을 포함시킬 수있는 CSS 와 유사한 JavaScript가 있습니까?



82
@Daniel, 나는 AJAX 호출을 사용하고 싶지 않습니다.
Alec Smart

13
가져온 파일을 필요로하는 다른 파일보다 먼저 주문 된 script태그 를 사용하여 선언하지 않겠습니까?
falsarella

6
@Claudiu 그것은 아무것도 가져 오는 데 도움이되지 않지만 잘 작동합니다. 다른 JS 파일에 종속 된 JS 파일이있는 경우 먼저 종속 파일의 스크립트 태그를 선언하면 나중에 종속 파일이 이미로드됩니다. 가능한 접근 방식이 아닌 상황이 있다면 여기에 대한 답변이 도움이 될 것입니다.
falsarella

1
이 작업의 실질적인 이점은 무엇입니까? 어느 쪽이든 자바 스크립트 파일에 의존하는 코드베이스는로드되지 않으며 어떤 경우에도로드되지 않습니다!
Ciasto piekarz

답변:


4470

이전 버전의 JavaScript에는 가져 오기, 포함 또는 필요가 없었으므로이 문제에 대한 다양한 접근 방식이 개발되었습니다.

그러나 2015 년 (ES6) 이후 JavaScript는 Node.js에서 모듈을 가져 오기 위한 ES6 모듈 표준을 가지고 있으며 대부분의 최신 브라우저 에서도 지원됩니다 .

구형 브라우저와의 호환성을 위해 WebpackRollup 과 같은 빌드 도구 및 / 또는 Babel 과 같은 변환 툴을 사용할 수 있습니다.

ES6 모듈

ECMAScript (ES6) 모듈은 플래그 가있는 v8.5 이후 및 플래그가없는 Node.js v13.8.0 이상부터 Node.js 에서 지원 되었습니다 --experimental-modules. "ESM"(Node.js를의 이전 CommonJS 스타일의 모듈 시스템 대 [ "CJS"]) 당신이 중 하나를 사용하도록 설정하려면 "type": "module"에서를 package.json하거나 파일 확장자를 제공합니다 .mjs. ( .cjs기본적으로 ESM이면 Node.js의 이전 CJS 모듈로 작성된 모듈의 이름을 지정할 수 있습니다 .)

사용 package.json:

{
    "type": "module"
}

그런 다음 module.js:

export function hello() {
  return "Hello";
}

그런 다음 main.js:

import { hello } from './module.js';
let val = hello();  // val is "Hello";

를 사용 .mjs하면 다음이 가능합니다 module.mjs.

export function hello() {
  return "Hello";
}

그런 다음 main.mjs:

import { hello } from './module.mjs';
let val = hello();  // val is "Hello";

브라우저의 ECMAScript 모듈

브라우저는 Safari 10.1, Chrome 61, Firefox 60 및 Edge 16 이후 ECMAScript 모듈을 직접로드 할 수 있습니다 (웹팩과 같은 도구는 필요 없음) . caniuse 에서 현재 지원을 확인하십시오 . Node.js의 .mjs확장명 을 사용할 필요는 없습니다 . 브라우저는 모듈 / 스크립트의 파일 확장자를 완전히 무시합니다.

<script type="module">
  import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
  hello('world');
</script>
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}

https://jakearchibald.com/2017/es-modules-in-browsers/ 에서 자세한 내용을 확인하십시오.

브라우저에서 동적 가져 오기

동적 가져 오기를 통해 스크립트가 필요에 따라 다른 스크립트를로드 할 수 있습니다.

<script type="module">
  import('hello.mjs').then(module => {
      module.hello('world');
    });
</script>

https://developers.google.com/web/updates/2017/11/dynamic-import 에서 자세히 알아 보십시오.

Node.js가 필요합니다

Node.js에서 여전히 널리 사용되는 이전 CJS 모듈 스타일은 module.exports/require 시스템입니다.

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"   

JavaScript가 전처리를 요구하지 않는 브라우저에 외부 JavaScript 컨텐츠를 포함시키는 다른 방법이 있습니다.

AJAX 로딩

AJAX 호출로 추가 스크립트를로드 한 다음이를 사용 eval하여 실행할 수 있습니다. 가장 간단한 방법이지만 JavaScript 샌드 박스 보안 모델로 인해 도메인으로 제한됩니다. 를 사용하면 eval버그, 해킹 및 보안 문제가 발생할 수 있습니다.

페치 로딩

동적 가져 오기와 마찬가지로 Fetch Inject 라이브러리를 fetch사용하여 스크립트 종속성에 대한 실행 순서를 제어하는 ​​약속을 사용하여 하나 이상의 스크립트를 호출하여 로드 할 수 있습니다 .

fetchInject([
  'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
  console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})

jQuery 로딩

의 jQuery 라이브러리 로딩 기능을 제공 한 줄에 :

$.getScript("my_lovely_script.js", function() {
   alert("Script loaded but not necessarily executed.");
});

동적 스크립트 로딩

스크립트 URL이있는 스크립트 태그를 HTML에 추가 할 수 있습니다. jQuery의 오버 헤드를 피하기 위해 이상적인 솔루션입니다.

스크립트는 다른 서버에 상주 할 수도 있습니다. 또한 브라우저는 코드를 평가합니다. <script>태그 중 하나의 웹 페이지로 주입 될 수있는 <head>, 혹은 그저 폐쇄 전에 삽입 </body>태그.

이것이 어떻게 작동하는지에 대한 예는 다음과 같습니다.

function dynamicallyLoadScript(url) {
    var script = document.createElement("script");  // create a script DOM node
    script.src = url;  // set its src to the provided URL

    document.head.appendChild(script);  // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}

이 함수는 <script>페이지의 헤드 섹션 끝에 새 태그를 추가합니다 . 여기서 src속성은 함수에 첫 번째 매개 변수로 제공되는 URL로 설정됩니다.

이러한 솔루션은 모두 JavaScript Madness : Dynamic Script Loading에 설명되어 있습니다.

스크립트가 언제 실행되었는지 감지

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

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

예를 들면 다음과 같습니다. my_lovely_script.jscontains 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. 그리고 작동합니다! 혼란스러운 ...

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

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

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.head;
    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 whatever you want
};

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

loadScript("my_lovely_script.js", myPrettyCode);

스크립트는 브라우저가로드 된 후 또는 라인 포함 여부에 따라 DOM이로드 된 후 또는 이전에 실행될 수 있습니다 script.async = false;. Javascript 로딩에 대한 훌륭한 기사 가 있습니다 .

소스 코드 병합 / 전처리

이 답변의 맨 위에 언급했듯이 많은 개발자는 프로젝트에서 Parcel, Webpack 또는 Babel과 같은 빌드 / 번역 도구를 사용하여 향후 JavaScript 구문을 사용하고, 이전 브라우저에 대한 하위 호환성을 제공하고, 파일을 결합하고, 축소하고, 코드 분할 등을 수행하십시오.


130
하지만 Rhino와 같은 고급 기능을 사용하는 사람은이 질문을하지 않을 것입니다.
e-satis

192
두 가지 자바 스크립트 파일을 모두 제어 할 때 특정 솔루션에서 두 파일의 내용을 결합한 하나의 거대한 자바 스크립트 파일을 만들 수 있습니다.
Toad

20
"document.createElement ("my_lovely_script.js ");"해서는 안됩니다. 예에서 "document.createElement ("script ")"?
Russell Silva

14
eval이 실행중인 코드라면 어떻게 해킹의 문을 열 수 있습니까?
Vince Panuccio

6
귀하의 답변은 IE ( onreadystatechange이벤트 및 readyState속성)를 약간 수정해야합니다 . 또한 동적 스크립트 로딩은 브라우저의 사전로드 스캐너에서 도움이되지 않습니다. 이 HTML5Rocks 기사를 추천하십시오 : html5rocks.com/en/tutorials/speed/script-loading
ruhong

570

더 진보 된 것을 찾는 사람이라면 RequireJS를 사용해보십시오 . 종속성 관리, 동시성 향상 및 복제 방지 (스크립트를 두 번 이상 검색)와 같은 추가 이점을 얻을 수 있습니다.

"모듈"로 JavaScript 파일을 작성한 다음 다른 스크립트에서 종속성으로 참조 할 수 있습니다. 또는 RequireJS를 간단한 "이 스크립트 가져 오기"솔루션으로 사용할 수 있습니다.

예:

종속성을 모듈로 정의하십시오.

some-dependency.js

define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {

     //Your actual script goes here.   
     //The dependent scripts will be fetched if necessary.

     return libraryObject;  //For example, jQuery object
});

implementation.jssome-dependency.js에 의존 하는 "기본"JavaScript 파일입니다.

require(['some-dependency'], function(dependency) {

    //Your script goes here
    //some-dependency.js is fetched.   
    //Then your script is executed
});

GitHub 읽어보기 에서 발췌 :

RequireJS는 일반 JavaScript 파일과 더 정의 된 모듈을로드합니다. 웹 워커를 포함하여 브라우저 내 사용에 최적화되어 있지만 Rhino 및 Node와 같은 다른 JavaScript 환경에서 사용할 수 있습니다. 비동기 모듈 API를 구현합니다.

RequireJS는 일반 스크립트 태그를 사용하여 모듈 / 파일을로드하므로 쉽게 디버깅 할 수 있습니다. 기존 JavaScript 파일을로드하는 데 간단히 사용할 수 있으므로 JavaScript 파일 을 다시 쓰지 않고도 기존 프로젝트에 파일 을 추가 할 수 있습니다.

...


1
@ aaaidan : MattDmo의 이유와 함께 외부 라이브러리에 의존하여 그 대답에 의존합니다.
David Mulder

1
require.js를 극복하기 위해 가장 최신의 앵귤러 j는 다른 바인딩 및 풍부한 HTML 기능과 함께보다 안정적이고 사용하기 쉽습니다.
zeeshan

5
-1 : 이러한 추상화 ( "some_dependency")는 인덱스가 혼란스러워서 실제로 열악합니다. 작동 코드 예제가 어떻게 보이는지 이해하기가 어렵습니다. 저자가 실제 사례를 제공하면 거의 모든 사람이 자신의 필요에 맞게이를 조정하고 일반화 할 수 있습니다.
Tegiri Nenashi

1
MVC 및 자동 축소 기능이 포함 된 스크립트 번들링에서 제대로 작동하지 않음
Triynko

1
'add .. JavaScript 파일을 다시 쓰지 않아도됩니다'; 근사하지만 정확히 어떻게? 똥개. 대답은 주 스크립트에 '필수'( 'requirejs'가 아닌?)를 추가하고 모든 종속 파일에 '정의'를 추가하는 것이 좋습니다. 그러나 그것은 다시 작성되었으므로 다시 작성하지 않은 것은 무엇입니까? RequireJS를 사용하면 파일을 전역 정의를 정상적으로 만들 수 있기 때문에 나머지 코드는 무엇입니까? -그래요? 방금 시도해 보았습니다. <script src = " requirejs.org/docs/release/2.2.0/comments/require.js "> </ script>, 그런 다음 'requirejs ([' GoogleDrive.com/host / .. ', ..], 함수 (a, b) {mycode}) ': Firebug는 모든 종속로드 된 BUT에 mycode & after에 정의되지 않은 defs를 말합니다.
Destiny Architect

195

실제로이 있다 자바 스크립트 파일을로드 할 수있는 방법 하지 당신이 그것을로드 한 후 새로로드 된 파일 오른쪽에 포함 된 기능을 사용할 수 있도록, 비동기, 그리고 나는 그것이 모든 브라우저에서 작동합니다 생각합니다.

페이지 요소에서 다음 을 사용해야 jQuery.append()합니다 <head>.

$("head").append('<script type="text/javascript" src="' + script + '"></script>');

그러나이 방법에도 문제가 있습니다. 가져온 JavaScript 파일에서 오류가 발생하면 Firebug (및 Firefox 오류 콘솔 및 Chrome 개발자 도구 )도 잘못된 위치를보고하므로 Firebug를 사용하여 추적하는 경우 큰 문제입니다 JavaScript 오류가 많이 발생합니다 (그렇습니다). Firebug는 어떤 이유로 새로로드 된 파일에 대해 단순히 알지 못하므로 해당 파일에서 오류가 발생하면 기본 HTML 파일 에서 발생한 것으로보고 하여 오류의 실제 원인을 찾는 데 어려움을 겪습니다.

그러나 이것이 문제가되지 않으면이 방법이 효과적입니다.

실제로이 방법을 사용하는 $ .import_js () 라는 jQuery 플러그인을 작성했습니다 .

(function($)
{
    /*
     * $.import_js() helper (for JavaScript importing within JavaScript code).
     */
    var import_js_imported = [];

    $.extend(true,
    {
        import_js : function(script)
        {
            var found = false;
            for (var i = 0; i < import_js_imported.length; i++)
                if (import_js_imported[i] == script) {
                    found = true;
                    break;
                }

            if (found == false) {
                $("head").append('<script type="text/javascript" src="' + script + '"></script>');
                import_js_imported.push(script);
            }
        }
    });

})(jQuery);

따라서 JavaScript를 가져 오려면 다음을 수행하십시오.

$.import_js('/path_to_project/scripts/somefunctions.js');

또한 Example 에서 간단한 테스트를 수행했습니다 .

main.js기본 HTML에 파일 이 포함 된 다음 스크립트 가 추가 파일을 가져 오는 main.js데 사용 $.import_js()합니다.included.js 합니다.이 은이 함수를 정의합니다.

function hello()
{
    alert("Hello world!");
}

그리고 포함 직후 included.jshello()함수가 호출되고 경고가 표시됩니다.

(이 답변은 e-satis의 의견에 대한 답변입니다).


이 방법을 시도하고 있지만 작동하지 않습니다. 요소가 머리 태그에 나타나지 않습니다.
사이트

16
@juanpastas-사용 jQuery.getScript하면 플러그인 작성에 대해 걱정할 필요가 없습니다.
MattDMo

6
흠, 이 기사 에 따르면 특별히로 설정 되지 않은 한 script요소를 추가하면 head비동기식으로 실행 async됩니다 false.
Flimm

1
스크립트 변수에 html 엔티티가 인코딩되어서는 안됩니까? 링크에가 포함되어 있으면 "코드가 작동하지 않습니다
RedClover

1
@Flimm 친애하는 선생님, 저와 제 팀은 귀하의 의견에 감사드립니다 그리고 우리가 직접 만나면 개인적으로 당신에게도 돈을 맥주를 빚진
Alex

155

내 의견으로는 훨씬 깨끗하다는 또 다른 방법은 <script>태그 를 사용하는 대신 동기 Ajax 요청을하는 것입니다 . 또한 어떻게Node.js 가 include를 처리 있습니다.

다음은 jQuery를 사용하는 예입니다.

function require(script) {
    $.ajax({
        url: script,
        dataType: "script",
        async: false,           // <-- This is the key
        success: function () {
            // all good...
        },
        error: function () {
            throw new Error("Could not load script " + script);
        }
    });
}

그런 다음 일반적으로 include를 사용할 때 코드에서 사용할 수 있습니다.

require("/scripts/subscript.js");

다음 줄에서 필요한 스크립트에서 함수를 호출 할 수 있습니다.

subscript.doSomethingCool(); 

1
좋은 해결책, 헤드 포함은 불행히도 비동기 적이며, 아약스 솔루션이 작동합니다.
Matteo Conta

17
다른 사람이 언급했듯이 requirejs.org는이 작업을 수행하며 js 파일을 하나로 묶어 더 빨리로드하는 사전 컴파일러도 있습니다. 확인하고 싶을 수도 있습니다.
Ariel

2
Chrome의 파일 하단에 다음 지시문을 추가하여 디버깅 할 수 있음을 발견했습니다. // @ sourceURL = view_index.js
Todd Vance

11
불행히도, jQuery에서는 async : false가 더 이상 사용되지 않습니다. 앞으로는 깨질 수 있으므로 피하십시오.
sqram

3
@katsh 여기서는 jqXHR 객체를 사용하지 않습니다. 귀하의 인용문은 이전의 의견을 뒷받침하지 않는 것으로 보입니다 async: false. 그렇지 않습니다! 귀하의 견적에 따르면 jqXHR 관련 항목 만 있습니다.
Zero3

101

좋은 소식이 있습니다. 곧 JavaScript 코드를 쉽게로드 할 수 있습니다. JavaScript 코드 모듈을 가져 오는 표준 방법이되고 핵심 JavaScript 자체의 일부가됩니다.

파일에서 import cond from 'cond.js';이름이 지정된 매크로를로드 하기 만하면 cond됩니다 cond.js.

따라서 JavaScript 프레임 워크에 의존하거나 Ajax 호출 을 명시 적으로 지정할 필요가 없습니다 .

인용하다:


12
jsfile의 require / import가 너무 오래되었습니다. (IMO).
rwheadon

6
@ rwheadon 네, 이것이 언어의 일부가 아니라는 것을 두려워하는 것 같습니다! js 사람들이 어떤 일을 처리하는 방법은 저 너머입니다! 그것에 새로운 Im 그리고 이것은 최악의 광기의 많은 것 같다
JonnyRaa

@ jonny-leeds 내장 된 모듈 로딩 없이도 브라우저의 JavaScript는 모듈 관리를 위해 RequireJS와 같은 라이브러리를 구현할 수있을 정도로 유연합니다.
Keen

8
2015 년 중반 – 여전히 어떤 브라우저에서도 구현되지 않습니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
scape

그래 니가 맞아. 이제 나는 이것에 대해 기분이 나 빠지기 시작했다. (. 너, 일단 모든 브라우저에서 구현되면 이것은 자바 스크립트에 내장 된 훌륭한 기능이 될 것이다.
Imdad

96

JavaScript 태그를 동적으로 생성하여 다른 JavaScript 코드 내부에서 HTML 문서에 추가 할 수 있습니다. 타겟 JavaScript 파일이로드됩니다.

function includeJs(jsFilePath) {
    var js = document.createElement("script");

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

    document.body.appendChild(js);
}

includeJs("/path/to/some/file.js");

8
@ e-satis-사실, 이것은 동기 스크립트가 차단하는 이점입니다. 코스는 말이지 만 10 명 중 9 번은 비 차단 옵션을 원합니다.
annakata 2016 년

@Svitlana-이와 같이 작성된 스크립트 요소는 비동기입니다. 현재 이것은 허점을 악용하는 것으로 볼 수 있으므로 미래의 증거가 될 수는 없습니다.이를 분명히하는 표준은 없습니다.
annakata 2016 년

사실 나는 그것을 다시 가져 갔고, 당신이 머리가 아닌 몸에 추가하고 있음을 알았습니다.
annakata 2016 년

@ annakata : 차이점은 무엇입니까? BTW, yahoo는 본문 끝에 스크립트 태그를 추가 할 것을 제안하므로 동적으로 추가 할 때 아무런 문제가 없습니다.
Svitlana Maksymchuk 2016 년

7
@ e-satis 비동기는 페이지가 고정되지 않기 때문에 좋습니다. 콜백을 사용하여 알림을 js.onload = callback;
받음

74

명령문 import은 ECMAScript 6에 있습니다.

통사론

import name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import name , { member [ , [...] ] } from "module-name";
import "module-name" as name;

...하지만 연결된 페이지의 호환성 표에 따라 현재까지는 어떤 브라우저에서도 지원되지 않습니다.
Zero3

6
이제 ES6 코드를 작성하고 선호하는 현재 모듈 시스템 (CommonJS / AMD / UMD)에 맞게 Babel.js ( babeljs.io )로 컴파일 할 수 있습니다 . babeljs.io/docs/usage/modules
Jeremy Harris

@ Zero3 분명히 새로운 IE (Edge)는 유일한 것입니다
Julian Avar

2019 년 IE는 여전히 어떤 형태로도 이것을 지원하지 않습니다. Microsoft가 왜 유용성에 반대해야합니까?
GreySage

61

이 페이지에서 찾은이 기능을 사용할 수 있습니다 . JavaScript 파일에 JavaScript 파일을 어떻게 포함 시키나요? :

function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';

    head.appendChild(script)
}

5
추가해야합니다script.onload = callback;
Vitim.us

@SvitlanaMaksymchuk 그래서, 내가 사용하지 않으면 var변수는 전역입니까?
Francisco Corrales Morales

@FranciscoCorrales 예.
Christopher Chiche



54

다음은 jQuery 가없는 동기 버전입니다 .

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

이 작동하는 도메인 간을 가져 오려면 서버가 allow-origin응답에 헤더 를 설정해야합니다 .


뛰어난 기능! 본문 뒤에 추가 JS가 작성되기 전에 JavaScript를로드합니다. 여러 스크립트를로드 할 때 매우 중요합니다.
tfont

3
@heinob : 도메인 간 작업을하려면 어떻게해야합니까? (에서 스크립트로드 http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570

@ user2284570 : 당신이 외국 도메인의 소유자 인 경우 : 서버 응답에서`allow-origin '헤더를 설정하십시오. 당신이 소유자가 아닌 경우 : 아무것도. 죄송합니다! 그것은 교차 출처 정책입니다.
heinob

2
@ user2284570 : 귀하가 스크립트를로드하려는 도메인의 소유자가 아니라는 귀하의 의견을 이해합니다. 이 경우 via가 아닌 삽입 된 <script>태그 를 통해서만 스크립트를로드 할 수 있습니다 XMLHttpRequest.
heinob

2
Firefox에서 이것을 사용하려는 경우 (예 : imacros 스크립팅) 다음 줄을 파일 맨 위에 추가하십시오.const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
Kwestion

49

난 그냥 (사용하여이 자바 스크립트 코드 작성 프로토 타입을 위한 DOM의 조작을) :

var require = (function() {
    var _required = {};
    return (function(url, callback) {
        if (typeof url == 'object') {
            // We've (hopefully) got an array: time to chain!
            if (url.length > 1) {
                // Load the nth file as soon as everything up to the
                // n-1th one is done.
                require(url.slice(0, url.length - 1), function() {
                    require(url[url.length - 1], callback);
                });
            } else if (url.length == 1) {
                require(url[0], callback);
            }
            return;
        }
        if (typeof _required[url] == 'undefined') {
            // Haven't loaded this URL yet; gogogo!
            _required[url] = [];

            var script = new Element('script', {
                src: url,
                type: 'text/javascript'
            });
            script.observe('load', function() {
                console.log("script " + url + " loaded.");
                _required[url].each(function(cb) {
                    cb.call(); // TODO: does this execute in the right context?
                });
                _required[url] = true;
            });

            $$('head')[0].insert(script);
        } else if (typeof _required[url] == 'boolean') {
            // We already loaded the thing, so go ahead.
            if (callback) {
                callback.call();
            }
            return;
        }

        if (callback) {
            _required[url].push(callback);
        }
    });
})();

용법:

<script src="prototype.js"></script>
<script src="require.js"></script>
<script>
    require(['foo.js','bar.js'], function () {
        /* Use foo.js and bar.js here */
    });
</script>

요점 : http://gist.github.com/284442 .


7
jrburke는 이것을 RequireJS로 썼습니다. Github : requirejs.org/docs/requirements.html
Mike Caron

로드 된 스크립트를 require ()가 호출되는 범위 밖에 두지 않습니까? 범위 내에서 eval ()이 유일한 방법 인 것 같습니다. 아니면 다른 방법이 있습니까?
trusktr

44

다음은 Facebook의 유비쿼터스 좋아요 버튼에 대해 Facebook이 수행하는 방식에 대한 일반화 된 버전입니다.

<script>
  var firstScript = document.getElementsByTagName('script')[0],
      js = document.createElement('script');
  js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
  js.onload = function () {
    // do stuff with your dynamically loaded script
    snowStorm.snowColor = '#99ccff';
  };
  firstScript.parentNode.insertBefore(js, firstScript);
</script>

Facebook에서 작동하면 효과가 있습니다.

우리 scripthead또는 대신에 첫 번째 요소를 찾는 이유는 body일부 브라우저가 누락 된 경우 하나를 만들지 않지만 script이 요소를 보장하기 때문 입니다. http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ 에서 자세히 알아보십시오 .


3
젠장! 여기의 일부 방법도 작동하지만 동적 설정에서는 이것이 가장 효과적입니다.
tfont

중복을 제거하기 위해 스크립트를 확장했습니다
Kamil Dąbrowski

39

순수한 JavaScript로 원한다면을 사용할 수 있습니다 document.write.

document.write('<script src="myscript.js" type="text/javascript"></script>');

jQuery 라이브러리를 사용하는 경우 $.getScript메소드를 사용할 수 있습니다 .

$.getScript("another_script.js");

8
document.write가 다른 모든 것을 제거하지 않습니까?
Eisa Adil

30

PHP 를 사용하여 스크립트를 어셈블 할 수도 있습니다 .

파일 main.js.php:

<?php
    header('Content-type:text/javascript; charset=utf-8');
    include_once("foo.js.php");
    include_once("bar.js.php");
?>

// Main JavaScript code goes here

16
요점은이 모든 것을 프론트 엔드에서 자바 스크립트로 유지하는 것입니다
Ariel

1
상기시켜 주셔서 감사합니다. PHP가 HTML 헤더에 <script> 태그를 작성하여 필요한 js 파일 (및 그 파일 만)이로드되도록 할 수도 있습니다.
Rolf

29

여기에 표시된 대부분의 솔루션은 동적 로딩을 의미합니다. 대신 모든 종속 파일을 단일 출력 파일로 어셈블하는 컴파일러를 찾고있었습니다. 과 동일한 이하 / 말대꾸의 는 CSS와 전처리 거래@import 에서 규칙. 나는 이런 종류의 적절한 것을 찾지 못했기 때문에 문제를 해결하는 간단한 도구를 작성했습니다.

따라서 https://github.com/dsheiko/jsic 컴파일러 $import("file-path")는 요청 된 파일 내용으로 안전하게 대체 됩니다. 해당 Grunt 플러그인 은 다음과 같습니다 . https://github.com/dsheiko/grunt-jsic .

jQuery 마스터 브랜치에서는 원자 소스 파일을로 시작 intro.js하고 끝나는 단일 소스 파일로 간단히 연결합니다 outtro.js. 소스 코드 디자인에 유연성이 없기 때문에 나에게 적합하지 않습니다. jsic과의 작동 방식을 확인하십시오.

src / main.js

var foo = $import("./Form/Input/Tel");

src / 양식 / 입력 /Tel.js

function() {
    return {
          prop: "",
          method: function(){}
    }
}

이제 컴파일러를 실행할 수 있습니다 :

node jsic.js src/main.js build/mail.js

그리고 결합 된 파일을 얻으십시오

빌드 / 메인 .js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};

2
이 게시물 이후 나는 훨씬 더 나은 솔루션 -CommonJS 모듈 컴파일러 -github.com/dsheiko/cjsc를 생각해 냈습니다. 그래서 당신은 단순히 CommonJs 또는 NodeJs 모듈을 작성하고 서로 액세스하면서 격리 된 범위로 유지할 수 있습니다. 장점 : 성능에 영향을주는 여러 HTTP 요청이 필요 없음 모듈 코드를 수동으로 래핑 할 필요가 없습니다. 컴파일러의 책임 (소스 코드 가독성 향상) 외부 라이브러리가 필요하지 않습니다. UMD와 호환됩니다. 및 NodeJs 모듈 (예 : 코드를 건드리지 않고 jQuery, Backbone을 모듈로 지정할 수 있음)
Dmitry Sheiko

26

JavaScript 파일을로드하려는 의도가 가져 오거나 포함 된 파일의 함수를 사용하는 경우 경우 전역 오브젝트를 정의하고 함수를 오브젝트 항목으로 설정할 수도 있습니다. 예를 들어 :

global.js

A = {};

file1.js

A.func1 = function() {
  console.log("func1");
}

file2.js

A.func2 = function() {
  console.log("func2");
}

main.js

A.func1();
A.func2();

HTML 파일에 스크립트를 포함시킬 때주의해야합니다. 순서는 다음과 같아야합니다.

<head>
  <script type="text/javascript" src="global.js"></script>
  <script type="text/javascript" src="file1.js"></script>
  <script type="text/javascript" src="file2.js"></script>
  <script type="text/javascript" src="main.js"></script>
</head>

22

이것은해야합니다 :

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);

5
eval그것이 뭐가 잘못이다. 에서 크록 포드 , " eval악은.입니다 eval. 그것을 피하십시오. 기능은 자바 스크립트의 가장 잘못 사용 기능입니다 eval별명이 있습니다. 사용하지 마십시오 Function. 생성자에 문자열을 전달하지 않습니다 setTimeoutsetInterval." "자바 스크립트 : 좋은 부분"을 읽지 않았다면 지금 나가십시오. 당신은 것입니다 그것을 후회하지.
MattDMo 2016 년

13
@MattDMo "누군가 그 말이 나쁘다"는 말은 사실이 아닙니다.
케이시

4
더글러스 크로포드 가 누군지 몰라요 .
MattDMo

13
@MattDMo 나는 그가 누구인지 완전히 알고 있지만, 그는 신이 아니라 인간입니다.
케이시

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

21

또는 런타임에 포함하는 대신 스크립트를 사용하여 업로드하기 전에 연결하십시오.

나는 스프로킷을 사용한다 (다른 것이 있는지 모르겠습니다). 별도의 파일로 JavaScript 코드를 작성하고 Sprockets 엔진에서 처리 한 주석을 포함으로 포함시킵니다. 개발을 위해 파일을 순차적으로 포함시킨 다음 프로덕션 환경에서 파일을 병합 할 수 있습니다.

또한보십시오:


Browserify 는 Sprockets보다 훨씬 인기가 있습니다.
Dan Dascalescu

18

나는 간단한 문제가 있었지만이 질문에 대한 답변으로 당황했다.

한 JavaScript 파일 (myvariables.js)에 정의 된 변수 (myVar1)를 다른 JavaScript 파일 (main.js)을 사용해야했습니다.

이를 위해 다음과 같이했습니다.

HTML 파일에서 JavaScript 코드를 올바른 순서로 myvariables.js에 이어 main.js에로드했습니다.

<html>
    <body onload="bodyReady();" >

        <script src="myvariables.js" > </script>
        <script src="main.js" > </script>

        <!-- Some other code -->
    </body>
</html>

파일 : myvariables.js

var myVar1 = "I am variable from myvariables.js";

파일 : main.js

// ...
function bodyReady() {
    // ...
    alert (myVar1);    // This shows "I am variable from myvariables.js", which I needed
    // ...
}
// ...

보시다시피 한 JavaScript 파일의 변수를 다른 JavaScript 파일의 변수를 사용했지만 다른 변수를 포함 할 필요는 없었습니다. 방금 첫 번째 JavaScript 파일이 두 번째 JavaScript 파일보다 먼저로드되고 첫 번째 JavaScript 파일의 변수에 두 번째 JavaScript 파일에서 자동으로 액세스 할 수 있는지 확인해야했습니다.

이것은 나의 하루를 구했다. 이게 도움이 되길 바란다.


이 답변의 문제점은와 같지 않다는 것 import입니다. 한 js 파일에서 다른 js 파일로 물건을 가져 오려면 HTML 파일이 필요합니다.
Cannicide

매우 사실입니다. 그것은 다른 답변이 솔루션으로 가지고있는 것입니다. 그러나 두 개의 JS 파일이 있었는데 하나는 다른 JS 변수를 사용해야합니다. node.js, next.js, express.js 등이 없으므로 가져 오기 또는 필요가 작동하지 않고 일반 .js 파일 만 있습니다.
Manohar Reddy Poreddy

그러나 이해할 수있는 것은 실제로 HTML 파일을 사용하여 변수에 액세스하는 것이 아니라 다른 파일 자체 내에서 자바 스크립트 파일을 가져 오도록 요청하는 것입니다. 예를 들어, 버튼의 기능을 만들고 있고, 하나는 클릭 처리, 다른 하나는 호버 처리, 다른 하나는 콜백을위한 세 가지 js 파일을 사용한다고 가정합니다. 세 번째 js 자체에서 다른 두 개의 j를 가져오고 하나의 <script>태그 만 갖는 것이 도움이됩니다 . 이것은 조직에 도움이 될 수 있습니다. 이 답변은 단순히 질문이 요구 한 것이 아니며,이 맥락에서 이상적이지 않습니다.
Cannicide

내 문제에 대한 해결책을 검색했을 때 올바른 방법으로 검색했지만 Google은 이것이 올바른 페이지라고 생각하여 여기에 착륙했습니다. 그래서 나는 여기에 내 대답을 썼습니다. 위의 15 upvotes로 인해 내가 옳은 것처럼 보입니다. 다른 사람들의 시간을 낭비하지 않기 위해 HTML 시나리오를 먼저 시작했습니다. HTML 코드를 먼저 입력했습니다. 그 희망이 명확 해졌다.
Manohar Reddy Poreddy 8

그렇습니다. 실제로 일부 사람들이 약간 다른 문제를 찾은 것처럼 보입니다. 이것은 해결책입니다. 이것이 반드시이 질문에 대한 답은 아니지만 가장 유사한 또 다른 질문에 대한 답입니다. 따라서이 답변을 찾는 사람들에게 도움이되므로 여기에이 답변을 갖는 것이 좋습니다. 답장을 보내 주셔서 감사합니다.
Cannicide

16

웹 워커를 사용 중이고 워커 범위에 추가 스크립트를 포함하려는 경우 head태그에 스크립트를 추가하는 등의 다른 답변 은 작동하지 않습니다.

다행히도 웹 워커 는 사양의 일부인 브라우저 자체에 고유 한 웹 워커 범위의 글로벌 기능인 자체 importScripts기능가지고 있습니다 .

또는 (가) 두 번째로 높은 질문 하이라이트에 대답을 투표로 , RequireJS는 또한 웹 노동자 (가능성이 호출 내부에 스크립트를 포함하여 처리 할 수 importScripts있지만, 몇 가지 다른 유용한 기능으로, 자신을).


16

스크립트가 이미로드되어 있는지 확인하는 현대 언어에서는 다음과 같습니다.

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

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

try { await loadJs("https://.../script.js") } 
catch(error) {console.log(error)}

또는

await loadJs("https://.../script.js").catch(err => {})

사용법 (약속) :

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

좋은. 좋은 해결책입니다.
Naftali 일명 Neal

간결하고 ES5 만 필요하며 정식으로 콜백하지 않아도됩니다. Dmitry 감사합니다!
Eureka

와우, 서버없이 브라우저에서 작동합니다. pi.js = 간단히 var pi = 3.14. 경유 () 함수를 호출 loadJSloadJs("pi.js").then(function(){ console.log(pi); });
zipzit

14

@import자바 스크립트 가져 오기는 그들의 특별한 통해 혼합물 같은 도구를 사용하여 가능처럼 CSS는-달성하기위한 구문 .mix파일 형식 (참조 여기 ). 나는 응용 프로그램이 단순히 위에서 언급 한 방법 중 하나를 내부적으로 사용한다고 생각합니다.

.mix파일 의 혼합물 설명서에서 :

믹스 파일은 단순히 .js가 포함 된 .js 또는 .css 파일입니다. 파일 이름에. 믹스 파일은 단순히 일반 스타일 또는 스크립트 파일의 기능을 확장하여 가져오고 결합 할 수있게합니다.

다음 .mix은 여러 .js파일을 하나로 결합 하는 예제 파일입니다 .

// scripts-global.mix.js
// Plugins - Global

@import "global-plugins/headroom.js";
@import "global-plugins/retina-1.1.0.js";
@import "global-plugins/isotope.js";
@import "global-plugins/jquery.fitvids.js";

혼합물 scripts-global.js은 이것을 축소 버전으로도 출력합니다 (scripts-global.min.js ).

참고 : 저는 Mixture를 프론트 엔드 개발 도구로 사용하는 것 외에는 어떤 방식으로도 Mixture와 제휴하지 않습니다. .mixJavaScript 파일이 (Mixture 상용구 중 하나에서) 작동하고 약간 혼란스러워 보이는 것을보고이 질문에 부딪 쳤습니다 ( "당신은 이것을 할 수 있습니까?"라고 생각했습니다). 그런 다음 응용 프로그램 별 파일 형식이라는 것을 깨달았습니다 (약간 실망스럽고 동의했습니다). 그럼에도 불구하고 지식이 다른 사람들에게 도움이 될 것이라고 생각했습니다.

업데이트 : 혼합물은 이제 무료입니다 (오프라인).

업데이트 : 혼합물이 중단되었습니다. 오래된 혼합물 방출 은 여전히 ​​유효합니다


노드 모듈이라면 정말 좋을 것입니다.
b01

@ b01 챌린지처럼 들린다;) 만약 내가 시간을 가졌다면 ... 아마도 다른 누군가가?
Isaac Gregson


13

내 일반적인 방법은 다음과 같습니다

var require = function (src, cb) {
    cb = cb || function () {};

    var newScriptTag = document.createElement('script'),
        firstScriptTag = document.getElementsByTagName('script')[0];
    newScriptTag.src = src;
    newScriptTag.async = true;
    newScriptTag.onload = newScriptTag.onreadystatechange = function () {
        (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());
    };
    firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
}

그것은 훌륭하게 작동하며 페이지 다시로드를 사용하지 않습니다. AJAX 방법 (다른 답변 중 하나)을 시도했지만 나에게 잘 작동하지 않는 것 같습니다.

호기심이 많은 사람들의 코드 작동 방식에 대한 설명은 다음과 같습니다. 기본적으로 URL의 첫 스크립트 태그 뒤에 새 스크립트 태그를 만듭니다. 비동기 코드로 설정하여 나머지 코드를 차단하지 않지만 readyState (로드 할 내용의 상태)가 'loaded'로 변경되면 콜백을 호출합니다.


13

이러한 답변은 훌륭하지만 스크립트로드가 존재 한 이후로 존재하는 간단한 "솔루션"이 있으며 대부분의 사람들이 사용하는 사례의 99.999 %를 차지합니다. 필요한 스크립트 앞에 필요한 스크립트를 포함시키기 만하면됩니다. 대부분의 프로젝트에서 필요한 스크립트와 순서를 결정하는 데 시간이 오래 걸리지 않습니다.

<!DOCTYPE HTML>
<html>
    <head>
        <script src="script1.js"></script>
        <script src="script2.js"></script>
    </head>
    <body></body>
</html>

script2에 script1이 필요한 경우 실제로 이와 같은 작업을 수행하는 가장 쉬운 방법입니다. 거의 모든 경우에 적용되는 가장 분명하고 간단한 답변이기 때문에 아무도 이것을 제기하지 않은 것에 매우 놀랐습니다.


1
나는 내 자신을 포함한 많은 사람들에게 역동적 인 파일 이름이 필요하다고 생각합니다.
Stuart McIntyre

1
이 경우 @StuartMcIntyre, 런타임에 스크립트 태그의 src 속성을 설정하고 onload 이벤트를 기다리십시오 (물론 2019의 경우 더 나은 솔루션이 있습니다).
KthProg

12

JavaScript로 모듈 스크립트 가져 오기 / 포함 작업을 자동화하는 간단한 모듈을 작성했습니다. 코드에 대한 자세한 설명은 블로그 게시물 JavaScript require / import / include 모듈을 참조하십시오 .

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

require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');

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

    //--------------------

var _rmod = _rmod || {}; //Require module namespace
_rmod.LOADED = false;
_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;
    }
};

_.rmod = namespaceToUri = function(script_name, url) {
    var np = script_name.split('.');
    if (np.getLast() === '*') {
        np.pop();
        np.push('_all');
    }

    if(!url)
        url = '';

    script_name = np.join('.');
    return  url + np.join('/')+'.js';
};

//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 uri = '';
    if (script_name.indexOf('/') > -1) {
        uri = script_name;
        var lastSlash = uri.lastIndexOf('/');
        script_name = uri.substring(lastSlash+1, uri.length);
    } 
    else {
        uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
    }

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

10

이 스크립트는 다른 <script>태그 의 맨 위에 JavaScript 파일을 추가합니다 .

(function () {
    var li = document.createElement('script'); 
    li.type = 'text/javascript'; 
    li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"; 
    li.async=true; 
    var s = document.getElementsByTagName('script')[0]; 
    s.parentNode.insertBefore(li, s);
})();

10

Head.js있습니다 . 다루기가 매우 쉽습니다.

head.load("js/jquery.min.js",
          "js/jquery.someplugin.js",
          "js/jquery.someplugin.css", function() {
  alert("Everything is ok!");
});

보시다시피 Require.js보다 쉽고 jQuery의 $.getScript메소드 만큼 편리합니다 . 또한 조건부로드, 특징 검출과 같은 몇 가지 고급 기능이 훨씬 더 .


10

이 질문에 대한 많은 잠재적 인 답변이 있습니다. 내 대답은 분명히 여러 가지를 기반으로합니다. 이것이 모든 답변을 읽은 후에 끝내는 것입니다.

$.getScript로딩이 완료되었을 때 콜백이 필요한 다른 해결책 의 문제 는 파일을 사용하고 서로 의존하는 여러 파일이 있으면 더 이상 모든 스크립트가로드 된 시점을 알 수있는 방법이 없다는 것입니다. 여러 파일로).

예:

file3.js

var f3obj = "file3";

// Define other stuff

file2.js :

var f2obj = "file2";
$.getScript("file3.js", function(){

    alert(f3obj);

    // Use anything defined in file3.
});

file1.js :

$.getScript("file2.js", function(){
    alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.
    alert(f2obj);

    // Use anything defined in the loaded script...
});

Ajax를 지정하여 동기식으로 실행하거나 XMLHttpRequest를 사용할 수 있다고 말할 때 . 그러나 현재 추세는 동기식 요청을 더 이상 사용하지 않는 것으로 보이므로 현재 또는 미래에 전체 브라우저를 지원하지 않을 수 있습니다.

$.when지연 된 객체의 배열을 확인하는 데 사용할 수는 있지만 이제는 모든 파일 에서이 작업을 수행 $.when하고 콜백이 실행될 때가 아닌 즉시 실행되는 file2 가로 드 된 것으로 간주 되므로 file3 이로 드되기 전에 file1이 계속 실행됩니다. . 이것은 여전히 ​​똑같은 문제가 있습니다.

나는 대신에 뒤로 가기로 결정했습니다. 감사합니다 document.writeln. 나는 그것이 금기임을 알고 있지만 올바르게 사용되는 한 잘 작동합니다. 결국 쉽게 디버깅 할 수 있고 DOM에 올바르게 표시되고 종속성이 올바르게로드되는 순서를 보장 할 수있는 코드로 끝납니다.

물론 $ ( "body"). append ()를 사용할 수 있지만 더 이상 더 이상 올바르게 디버깅 할 수 없습니다.

참고 :이 페이지를로드하는 동안에 만 사용해야합니다. 그렇지 않으면 빈 화면이 나타납니다. 즉, 항상 document.ready 앞 / 뒤에 배치하십시오 . 페이지가 클릭 이벤트 또는 이와 유사한 것으로로드 된 후에 이것을 사용하여 테스트하지는 않았지만 실패 할 것이라고 확신합니다.

jQuery를 확장한다는 아이디어가 마음에 들었지만 반드시 그럴 필요는 없습니다.

를 호출하기 전에 document.writeln모든 스크립트 요소를 평가하여 스크립트가 이미로드되지 않았는지 확인합니다.

document.ready이벤트가 실행될 때까지 스크립트가 완전히 실행되지 않았다고 가정합니다 . (사용 document.ready이 필요하지는 않지만 많은 사람들이 사용하는 것을 알고 있으며 이것을 처리하는 것이 안전합니다.)

추가 파일이로드되면 document.ready콜백이 잘못된 순서로 실행됩니다. 스크립트가 실제로로드 될 때이 문제를 해결하기 위해 스크립트를 가져온 스크립트는 다시 가져 오기되고 실행이 중지됩니다. 이로 인해 원래 파일 document.ready이 가져 오는 스크립트에서 콜백이 실행됩니다.

이 접근법 대신 jQuery를 수정하려고 시도 할 수는 readyList있지만 더 나쁜 해결책 인 것 같습니다.

해결책:

$.extend(true,
{
    import_js : function(scriptpath, reAddLast)
    {
        if (typeof reAddLast === "undefined" || reAddLast === null)
        {
            reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
        }

        var found = false;
        if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
        {
            found = $('script').filter(function () {
                return ($(this).attr('src') == scriptpath);
            }).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
        }

        if (found == false) {

            var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.

            document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln

            if (reAddLast)
            {
                $.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
                throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
            }
            return true;
        }
        return false;
    }
});

용법:

파일 3 :

var f3obj = "file3";

// Define other stuff
$(function(){
    f3obj = "file3docready";
});

파일 2 :

$.import_js('js/file3.js');
var f2obj = "file2";
$(function(){
    f2obj = "file2docready";
});

파일 1 :

$.import_js('js/file2.js');

// Use objects from file2 or file3
alert(f3obj); // "file3"
alert(f2obj); // "file2"

$(function(){
    // Use objects from file2 or file3 some more.
    alert(f3obj); //"file3docready"
    alert(f2obj); //"file2docready"
});

이것은 현재 허용되는 답변의 상태입니다. 충분하지 않습니다.
Cannicide

가장 큰 차이점은 누락 된 종속성이있는 경우 종속성에 대한 스크립트 태그를 추가 한 다음 호출 파일에 대한 스크립트 태그를 추가하고 실행을 중지시키는 오류를 발생시키는 것입니다. 이로 인해 스크립트가 올바른 순서로 처리되고 실행되며 콜백이 필요하지 않습니다. 따라서 중첩을 지원하는 동안 호출 스크립트 전에 종속 스크립트가로드되고 실행됩니다.
curlyhairedgenius

"현재의 추세는 동기식 요청을 더 이상 사용하지 않는 것 같습니다."이는 많은 개발자가이를 잘못 사용하여 사용자가 불필요하게 기다리게했기 때문에 사실입니다. 그러나 요청이 Include 문과 같이 자연스럽게 동기식이면 간단한 동기식 Ajax가 적합합니다. PHP "server"파일을 실행하여 JavaScript의 일부가 아닌 파일을 읽는 것과 같은 기능을 동 기적으로 실행하는 일반적인 JavaScript 확장 기능을 만들었으며 JavaScript를 사용하여 앱을 작성할 때 매우 유용합니다. 이러한 Ajax에는 로컬 웹 서버가 필요하지 않습니다.
David Spector

10

Javascript에서 모듈을 구현하는 방법에는 여러 가지가 있습니다. 가장 인기있는 두 가지 방법은 다음과 같습니다.

ES6 모듈

브라우저는 아직이 변조 시스템을 지원하지 않으므로이 구문을 사용하려면 webpack과 같은 번 들러를 사용해야합니다. 번 들러를 사용하면 다른 모든 파일을 단일 (또는 커플 관련) 파일로 결합 할 수 있으므로 더 좋습니다. 각 HTTP 요청에는 이와 관련된 일부 오버 헤드가 있으므로 서버에서 클라이언트로 파일을 더 빨리 제공합니다. 따라서 전체 HTTP 요청을 줄임으로써 성능을 향상시킵니다. ES6 모듈의 예는 다음과 같습니다.

// main.js file

export function add (a, b) {
  return a + b;
}

export default function multiply (a, b) {
  return a * b;
}


// test.js file

import {add}, multiply from './main';   // for named exports between curly braces {export1, export2}
                                        // for default exports without {}

console.log(multiply(2, 2));  // logs 4

console.log(add(1, 2));  // logs 3

CommonJS (NodeJS에서 사용)

이 변조 시스템은 NodeJS에서 사용됩니다. 기본적으로라는 객체에 내보내기를 추가합니다 module.exports. 그런 다음를 통해이 개체에 액세스 할 수 있습니다 require('modulePath'). 여기서 중요한 것은 이러한 모듈이 캐시되고 있다는 것을 인식하는 것이므로 require()특정 모듈을 두 번 사용하면 이미 생성 된 모듈을 반환합니다.

// main.js file

function add (a, b) {
  return a + b;
}

module.exports = add;  // here we add our add function to the exports object


// test.js file

const add = require('./main'); 

console.log(add(1,2));  // logs 3

9

유용한 JavaScript 플러그인 모음을 유지 관리하는 간단한 방법을 찾고 있었기 때문에이 질문에 왔습니다. 여기에 몇 가지 해결책을 본 후에 나는 이것을 생각해 냈습니다.

  1. "plugins.js"(또는 extensions.js 또는 원하는 파일)라는 파일을 설정하십시오. 하나의 마스터 파일과 함께 플러그인 파일을 유지하십시오.

  2. plugins.js에는 pluginNames[]반복 하는 배열이 있으며 각 플러그인의 머리에 태그를 each()추가합니다.<script>

//set array to be updated when we add or remove plugin files
var pluginNames = ["lettering", "fittext", "butterjam", etc.];

//one script tag for each plugin
$.each(pluginNames, function(){
    $('head').append('<script src="js/plugins/' + this + '.js"></script>');
});
  1. 머리에있는 파일 하나만 수동으로 호출하십시오.
    <script src="js/plugins/plugins.js"></script>

그러나:

모든 플러그인이 원하는 방식으로 헤드 태그에 들어가더라도 페이지를 클릭하거나 새로 고칠 때 항상 브라우저에서 실행되는 것은 아닙니다.

PHP include에 스크립트 태그를 작성하는 것이 더 안정적이라는 것을 알았습니다. 한 번만 작성하면 JavaScript를 사용하여 플러그인을 호출하는 것만큼이나 효과적입니다.


@ will, 귀하의 솔루션은 내 것보다 훨씬 깨끗해 보입니다. 이것을 사용하려면 포함하려는 각 플러그인 파일마다 해당 함수를 한 번만 호출하면됩니까?
rgb_life
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.