Pytanie Jak dołączyć plik JavaScript do innego pliku JavaScript?


Czy jest coś podobnego do JavaScript? @import w CSS, który pozwala ci dołączyć plik JavaScript do innego pliku JavaScript?


4158
2018-06-04 11:59


pochodzenie


stackoverflow.com/questions/21294/... - Daniel A. White
@ Daniel, nie chcę używać wywołania AJAX. - Alec Smart
Dlaczego nie zadeklarować zaimportowanego pliku przed drugim, który tego wymaga, po prostu używając zamawianego script tagi? - falsarella
@ Claudiu To nie pomogło import wszystko, ale powinno również działać. Jeśli masz plik JS, który zależy od innego pliku JS, po prostu zadeklaruj najpierw tagi skryptów plików zależności, aby później zostały załadowane jego zależności. Jeśli masz sytuację, w której nie jest to możliwe, odpowiedzi tutaj powinny być pomocne. - falsarella
jaka jest praktyczna korzyść z tego? tak czy inaczej podstawa kodu zależna od pliku javascript nie zostanie załadowana i zacznie działać, w każdym razie nie jest załadowana! - Ciasto piekarz


Odpowiedzi:


Stare wersje JavaScriptu nie były importowane, włączane ani wymagane, więc opracowano wiele różnych podejść do tego problemu.

Ale najnowsze wersje JavaScript mają takie standardy jak Moduły ES6 do importowania modułów, chociaż nie jest to obsługiwane przez większość przeglądarek. Wykorzystuje się wiele osób korzystających z modułów z aplikacjami przeglądarki budować i / lub transpozycja narzędzia, dzięki którym praktyczne będzie korzystanie z nowej składni z funkcjami takimi jak moduły.

Moduły ES6

Zwróć uwagę, że obecnie obsługa przeglądarek dla modułów ES6 nie jest szczególnie dobra, ale jest już w drodze. Według ta odpowiedź StackOverflow, są obsługiwane w przeglądarce Chrome 61, Firefox 54 (za dom.moduleScripts.enabled ustawienie w about:config) i MS Edge 16, tylko Safari 10.1 zapewnia wsparcie bez flag.

W związku z tym nadal będziesz musiał używać narzędzi do kompilacji i / lub transpozycji do poprawnego JavaScript, który będzie działał bez żadnych wymagań, aby użytkownik mógł korzystać z tych wersji przeglądarki lub włączać dowolne flagi.

Gdy moduły ES6 są powszechne, oto jak możesz ich używać:

// module.js
export function hello() {
  return "Hello";
}
// main.js
import {hello} from 'module'; // or './module'
let val = hello(); // val is "Hello";

Node.js wymagają

Node.js używa obecnie pliku module.exports / require system. Możesz użyć babel przesuwać, jeśli chcesz import składnia.

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

Istnieją inne sposoby na to, aby JavaScript zawierał zewnętrzne treści JavaScript w przeglądarkach, które nie wymagają wstępnego przetwarzania.

Ładowanie AJAX

Możesz załadować dodatkowy skrypt za pomocą wywołania AJAX, a następnie użyć eval aby go uruchomić. Jest to najprostszy sposób, ale ogranicza się do Twojej domeny z powodu modelu zabezpieczeń piaskownicy JavaScript. Za pomocą eval otwiera także drzwi do błędów, hacków i problemów bezpieczeństwa.

Ładowanie jQuery

The jQuery biblioteka zapewnia funkcjonalność ładowania w jednej linii:

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

Dynamiczne ładowanie skryptu

Możesz dodać znacznik skryptu z adresem URL skryptu do kodu HTML. Aby uniknąć narzutów jQuery, jest to idealne rozwiązanie.

Skrypt może nawet znajdować się na innym serwerze. Ponadto przeglądarka ocenia kod. The <script> tag można wprowadzić na stronie internetowej <head>lub wstawione tuż przed zamknięciem </body> etykietka.

Oto przykład tego, jak to może działać:

function dynamicallyLoadScript(url) {
    var script = document.createElement("script"); // Make a script DOM node
    script.src = url; // Set it's 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)
}

Ta funkcja doda nowe <script> tag do końca głównej sekcji strony, gdzie src atrybut jest ustawiony na adres URL, który jest nadawana funkcji jako pierwszy parametr.

Oba te rozwiązania zostały omówione i zilustrowane w JavaScript Madness: Dynamiczne ładowanie skryptu.

Wykrywanie, kiedy skrypt został wykonany

Teraz jest duży problem, o którym musisz wiedzieć. To oznacza to zdalnie ładujesz kod. Nowoczesne przeglądarki internetowe wczytują plik i nadal wykonują bieżący skrypt, ponieważ ładują wszystko asynchronicznie, aby poprawić wydajność. (Dotyczy to zarówno metody jQuery, jak i ręcznego ładowania skryptów dynamicznych.)

Oznacza to, że jeśli użyjesz tych sztuczek bezpośrednio, nie będziesz mógł użyć nowo załadowanego kodu w następnej linii, po tym, jak poprosiłeś o załadowanie, ponieważ nadal będzie ładowany.

Na przykład: my_lovely_script.js zawiera 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

Następnie ponownie załadujesz stronę F5. I to działa! Mylące...

Więc co z tym zrobić?

Możesz użyć hacka, który autor sugeruje w linku, który ci podałem. Podsumowując, dla osób w pośpiechu używa zdarzenia do wywołania funkcji zwrotnej po załadowaniu skryptu. Możesz więc umieścić cały kod za pomocą biblioteki zdalnej w funkcji wywołania zwrotnego. Na przykład:

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

Następnie napisz kod, który chcesz użyć PO zakończeniu ładowania skryptu funkcja lambda:

var myPrettyCode = function() {
   // Here, do whatever you want
};

Następnie uruchamiasz to wszystko:

loadScript("my_lovely_script.js", myPrettyCode);

Zauważ, że skrypt może być wykonywany po wczytaniu modelu DOM lub wcześniej, zależnie od przeglądarki i od tego, czy zawierałeś wiersz script.async = false;. Jest jeden świetny artykuł na temat ładowania Javascript w ogóle który to omawia.

Source Code Merge / Preprocessing

Jak wspomniano na początku tej odpowiedzi, wielu programistów używa obecnie narzędzi do kompilacji / transpozycji takich jak WebPack, Babel lub Gulp w swoich projektach, co pozwala im lepiej wykorzystywać nowe moduły składni i obsługi, łączyć pliki, zminimalizować itd.


3586
2018-06-04 12:13



nie wszystkie pliki javascript są wykonywane w przeglądarce. - Michael Paulukonis
Nie, ale ktoś, kto używa czegoś tak zaawansowanego jak Rhino, nie zadałby tego pytania. - e-satis
Aby być kompletnym, istnieje trzecia droga: w niektórych rozwiązaniach, gdy kontrolujesz oba pliki javascript, możesz po prostu zrobić 1 gigantyczny plik javascript, który łączy zawartość obu plików. - Toad
Nie powinien "document.createElement (" my_lovely_script.js ");" w tym przykładzie należy "document.createElement (" script ")"? - Russell Silva
Jak eval otwiera drzwi do hackowania, jeśli to twój kod, który wykonujesz? - Vince Panuccio


Jeśli ktoś szuka czegoś bardziej zaawansowanego, wypróbuj Wymagaj JS. Dostaniesz dodatkowe korzyści, takie jak zarządzanie zależnościami, lepszą współbieżność i unikanie powielania (tj. Pobieranie skryptu więcej niż raz).

Możesz napisać swoje pliki JavaScript w "module", a następnie odnieść je jako zależności w innych skryptach. Lub możesz użyć RequireJS jako prostego rozwiązania "go get this script".

Przykład:

Zdefiniuj zależności jako moduły:

trochę zależny.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.js jest twoim "głównym" plikiem JavaScript, od którego zależy trochę zależny.js

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

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

Fragment z GitHub README:

RequJJS ładuje zwykłe pliki JavaScript, a także bardziej zdefiniowane   moduły. Jest zoptymalizowany do użytku w przeglądarce, w tym w sieci   Pracownik, ale może być używany w innych środowiskach JavaScript, takich jak   Rhino i węzeł. Implementuje moduł Asynchronous API.

RequireJS używa zwykłych znaczników skryptu do ładowania modułów / plików, więc powinien   pozwalają na łatwe debugowanie. Może być używany po prostu do załadowania istniejącego   Pliki JavaScript, więc możesz dodać go do istniejącego projektu bez   konieczności ponownego napisania twoich plików JavaScript.

...


514
2018-06-07 20:55



+1 za cytowanie dobrze sposób na zrobienie tego :-) Byłoby jeszcze lepiej, gdybyś wziął przykład! - Sean Vieira
@Sear na swoją sugestię - dodałem krótki przykład - John Strickler
@aaaidan: powód MattDmo plus opiera się na zewnętrznej bibliotece, która w zamian opiera się na zaakceptowanej odpowiedzi. - David Mulder
Aby pokonać require.js, najbardziej aktualny byłby kątowy JS, który jest bardziej stabilny i łatwy w użyciu wraz z innymi wiążącymi i bogatymi funkcjami HTML. - zeeshan
-1: Te abstrakcje - "pewna zależność" - są naprawdę słabe, a indeksy zwiększają zamieszanie. Próbuję zrozumieć, jak wygląda działający przykład kodu. Jeśli autor dostarczy przykład pracy, prawie każdy będzie w stanie dostosować i uogólnić go do swoich potrzeb. - Tegiri Nenashi


Tak naprawdę jest sposób na załadowanie pliku JavaScript nie asynchronicznie, więc możesz użyć funkcji zawartych w nowo załadowanym pliku zaraz po załadowaniu go i myślę, że działa we wszystkich przeglądarkach.

Musisz użyć jQuery.append()na <head> element Twojej strony, czyli:

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

Jednak ta metoda ma również problem: jeśli wystąpi błąd w importowanym pliku JavaScript, Firebug (a także Firefox Error Console i Narzędzia dla programistów Chrome również) zgłosi to miejsce niepoprawnie, co jest dużym problemem, jeśli użyjesz Firebug do śledzenia błędów JavaScript w dużej mierze (ja). Firebug po prostu nie wie o nowo załadowanym pliku z jakiegoś powodu, więc jeśli wystąpi błąd w tym pliku, zgłasza, że ​​wystąpił on w twoim głównym HTML plik, a będziesz miał problem ze znalezieniem prawdziwej przyczyny błędu.

Ale jeśli to nie jest problem dla ciebie, to ta metoda powinna zadziałać.

Właściwie napisałem wtyczkę jQuery o nazwie $ .import_js () który używa tej metody:

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

Wszystko, co musisz zrobić, aby zaimportować JavaScript, to:

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

Zrobiłem również prosty test na ten temat Przykład.

Obejmuje on main.js plik w głównym kodzie HTML, a następnie w skrypcie main.js używa $.import_js() importować dodatkowy plik o nazwie included.js, który definiuje tę funkcję:

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

I zaraz po włączeniu included.js, hello() funkcja jest wywoływana i otrzymujesz alert.

(Ta odpowiedź jest odpowiedzią na komentarz e-satis).


162
2018-04-28 15:25



Próbuję tej metody, ale nie działa dla mnie, element po prostu nie pojawia się w tagu głowy. - juanpastas
@juanpastas - użyj jQuery.getScriptw ten sposób nie musisz się martwić o pisanie wtyczki ... - MattDMo
Czy ta technika naprawdę blokuje się, dopóki zaimportowany skrypt nie zostanie załadowany i wykonany? - Flimm
Hmm, według Ten artykuł, dołączanie a script element do head spowoduje, że będzie działać asynchronicznie, chyba że async jest specjalnie ustawiony na false. - Flimm
Czy zmienna skryptu nie powinna mieć zakodowanych encji html? Jeśli link zawiera ", kod się zepsuje - Soaku


Innym sposobem, który moim zdaniem jest znacznie czystszy, jest wykonanie synchronicznego żądania Ajax zamiast używania a <script> etykietka. Tak też jest Node.js rękojeści zawierają.

Oto przykład użycia 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);
        }
    });
}

Następnie możesz użyć go w swoim kodzie, tak jak zwykle używasz include:

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

I móc wywołać funkcję z wymaganego skryptu w następnej linii:

subscript.doSomethingCool(); 

134
2017-09-08 18:22



Dobre rozwiązanie, w tym głowa jest async, niestety, działa ajax. - Matteo Conta
Jak wspomniał ktoś inny, requirejs.org to robi, a także ma pre-kompilator, który umieszcza pliki js, dzięki czemu ładują się szybciej. Możesz to sprawdzić. - Ariel
Odkryłem, że mogę to debugować, dodając tę ​​dyrektywę na dole pliku dla Chrome: // @ sourceURL = view_index.js - Todd Vance
niestety, async: false jest teraz przestarzałe w jQuery. Może pęknąć w przyszłości, więc uniknęłbym. - sqram
@katsh Nie używamy tutaj obiektów jqXHR. Twoja oferta nie zawiera kopii poprzedniego komentarza async: false podobno jest przestarzałe. Nie jest! Jak podaje twój cytat, tylko rzeczy związane z jqXHR są. - Zero3


Jest dla ciebie dobra wiadomość. Wkrótce będzie można łatwo załadować kod JavaScript. Stanie się standardowym sposobem importowania modułów kodu JavaScript i będzie częścią samego jądra JavaScript.

Musisz po prostu pisać import cond from 'cond.js'; załadować makro o nazwie cond z pliku cond.js.

Nie musisz więc opierać się na żadnym szkielecie JavaScript, ani nie musisz go jawnie tworzyć Ajax połączenia.

Odnosić się do:


86
2017-07-03 13:32



require / import na pliku jsfile było zbyt długo w nadchodzącym. (IMO). - rwheadon
@ Rwheadon tak wydaje się przerażające, że to nie jest częścią języka! Jak js ludzie robią cokolwiek jest poza mną! Jestem na to nowy i to wydaje się najgorsze (wielu) kawałków szaleństwa - Jonny Leeds
@ jonny-leeds Nawet bez wbudowanego ładowania modułów, JavaScript w przeglądarce jest na tyle elastyczny, że możemy zaimplementować bibliotekę taką jak RequireJS dla naszego zarządzania modułem. - Keen
połowa 2015 r. - Wciąż nie zaimplementowana w żadnej przeglądarce, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - scape
tak, masz rację. teraz zaczynam się źle czuć :(. Po wprowadzeniu we wszystkich przeglądarkach będzie to świetna funkcja wbudowana w javascript. - Imdad


Możliwe jest dynamiczne generowanie tagu JavaScript i dołączanie go do dokumentu HTML z poziomu innego kodu JavaScript. Spowoduje to załadowanie ukierunkowanego pliku 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");

72
2018-06-04 12:02



Działa, ale ma poważne problemy z powodu asynchronicznego ładowania. - e-satis
Um ... co dokładnie? - Svitlana Maksymchuk
@ e-satis - W rzeczywistości jest to zaleta, skrypt synchronizacji będzie blokował. Konie na kursy, ale 9 razy na 10 chcesz opcję bez blokowania. - annakata
@Svitlana - elementy skryptu utworzone w ten sposób są asynchroniczne. Obecnie można to potraktować jako wykorzystanie luki, więc może to nie być dowód na przyszłość, nie widziałem niczego w żadnym standardzie, który to wyjaśnia. - annakata
asynchroniczny @ e-satis jest dobry, ponieważ nie zawiesza twojej strony. Użyj wywołania zwrotnego, aby otrzymać powiadomienie o zakończeniu js.onload = callback; - Vitim.us


Komunikat import znajduje się w ECMAScript 6.

Składnia

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;

58
2018-04-17 01:56



... ale nie jest obsługiwana przez żadną przeglądarkę do tej pory, zgodnie z tabelą zgodności na stronie, z którą się łączyłeś. - Zero3
Możesz teraz napisać kod ES6 i skompilować go z Babel.js (babeljs.io) do dowolnego preferowanego obecnego systemu modułów (CommonJS / AMD / UMD): babeljs.io/docs/usage/modules - Jeremy Harris
@ Zero3 Podobno nowy IE (Edge) jest jedynym - Julian Avar
czy istnieje sposób, aby to zrobić bez ES6? Zgodność z przeglądarkami i te, które nie mają ES6, wymagają tego. - IamGuest


Może możesz skorzystać z tej funkcji, którą znalazłem na tej stronie Jak dołączyć plik JavaScript do pliku 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)
}

47
2018-06-04 12:04



Powinien być przydatny do dodania script.onload = callback; - Vitim.us
@SvitlanaMaksymchuk więc, jeśli nie używam var, zmienna będzie globalna? - Francisco Corrales Morales
@FranciscoCorrales tak. - Christopher Chiche
Kończy się globalnie z lub bez var :) - Vedran Maricevic.
To kończy się niepowodzeniem, jeśli strona nie ma head. - Dan Dascalescu