Czy jest coś w JavaScript podobnego do @import
w CSS, co pozwala na umieszczenie pliku JavaScript wewnątrz innego pliku JavaScript?
Stare wersje JavaScript nie miały importu, include, ani require, więc opracowano wiele różnych podejść do tego problemu. Ale od 2015 roku (ES6), JavaScript ma standard ES6 modules do importowania modułów w Node.js, który jest również obsługiwany przez większość nowoczesnych przeglądarek. Dla kompatybilności ze starszymi przeglądarkami, można użyć narzędzi build i/lub transpilation.
Moduły ECMAScript (ES6) są obsługiwane w Node.js od v8.5, z flagą --experimental-modules
. Wszystkie zaangażowane pliki muszą mieć rozszerzenie .mjs
.
// module.mjs
export function hello() {
return "Hello";
}
// main.mjs
import { hello } from 'module'; // or './module'
let val = hello(); // val is "Hello";
Przeglądarki mają wsparcie dla ładowania modułów ECMAScript bezpośrednio (nie są wymagane narzędzia takie jak Webpack) od Safari 10.1, Chrome 61, Firefox 60 i Edge 16. Sprawdź aktualne wsparcie na stronie caniuse.
<script type="module">
import { hello } from './hello.mjs';
hello('world');
</script>
// hello.mjs
export function hello(text) {
const div = document.createElement('div');
div.textContent = `Hello ${text}`;
document.body.appendChild(div);
}
Czytaj więcej na https://jakearchibald.com/2017/es-modules-in-browsers/
Dynamiczny import pozwala skryptowi załadować inne skrypty w razie potrzeby:
<script type="module">
import('hello.mjs').then(module => {
module.hello('world');
});
</script>
Czytaj więcej na https://developers.google.com/web/updates/2017/11/dynamic-import
Starym stylem importowania modułów, wciąż szeroko stosowanym w Node.js, jest system module.exports/require.
// mymodule.js
module.exports = {
hello: function() {
return "Hello";
}
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"
Istnieją inne sposoby, aby JavaScript mógł dołączać zewnętrzne treści JavaScript w przeglądarkach, które nie wymagają wstępnego przetwarzania.
Można załadować dodatkowy skrypt za pomocą wywołania AJAX, a następnie użyć eval
do jego uruchomienia. Jest to najprostszy sposób, ale jest ograniczony do twojej domeny z powodu modelu bezpieczeństwa piaskownicy JavaScript. Użycie eval
również otwiera drzwi do błędów, hacków i problemów bezpieczeństwa.
Podobnie jak w przypadku dynamicznego importu, możesz załadować jeden lub wiele skryptów za pomocą wywołania fetch
, używając obietnic do kontrolowania kolejności wykonywania dla zależności skryptów za pomocą biblioteki Fetch Inject:
fetchInject([
'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})
Biblioteka jQuery zapewnia funkcjonalność ładowania w jednej linii:
$.getScript("my_lovely_script.js", function() {
alert("Script loaded but not necessarily executed.");
});
Możesz dodać znacznik skryptu z adresem URL skryptu do HTML. Aby uniknąć narzutu jQuery, jest to idealne rozwiązanie.
Skrypt może nawet rezydować na innym serwerze. Co więcej, przeglądarka ocenia kod. Znacznik <script>
może być wstrzyknięty zarówno do strony <head>
, jak i wstawiony tuż przed zamykającym znacznikiem </body>
.
Oto przykład, jak to może działać:
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)
}
Funkcja ta doda nowy znacznik <script>
na końcu sekcji head strony, gdzie atrybut src
jest ustawiony na adres URL, który jest podany funkcji jako pierwszy parametr.
Oba te rozwiązania są omówione i zilustrowane w JavaScript Madness: Dynamic Script Loading.
Teraz, jest pewien duży problem, o którym musisz wiedzieć. Robienie tego oznacza, że zdalnie ładujesz kod. Nowoczesne przeglądarki internetowe będą ładować plik i kontynuować wykonywanie twojego bieżącego skryptu, ponieważ ładują wszystko asynchronicznie, aby poprawić wydajność. (Dotyczy to zarówno metody jQuery, jak i ręcznego dynamicznego ładowania skryptu).
Oznacza to, że jeśli użyjesz tych sztuczek bezpośrednio, nie będziesz w stanie użyć swojego nowo załadowanego kodu w następnej linii po tym, jak poprosiłeś o jego załadowanie, ponieważ nadal będzie się ładował.
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 przeładowujesz stronę uderzając F5. I to działa! Mylące... **Więc co z tym zrobić? Cóż, można użyć hacka, który proponuje autor w linku, który podałem. Podsumowując, dla ludzi w pośpiechu, używa on zdarzenia do uruchomienia funkcji callback, gdy skrypt jest ładowany. Możesz więc umieścić cały kod korzystający ze zdalnej biblioteki 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.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);
}
Następnie piszesz kod, którego chcesz użyć PO załadowaniu skryptu w funkcji 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 wykonać się po załadowaniu DOM lub przed, w zależności od przeglądarki i tego, czy uwzględniłeś linię script.async = false;
. Istnieje świetny artykuł na temat ładowania Javascript w ogóle, który omawia tę kwestię.
Jak wspomniano na górze tej odpowiedzi, wielu programistów używa w swoich projektach narzędzi do budowania/transpilacji, takich jak Parcel, Webpack lub Babel, co pozwala im używać nadchodzącej składni JavaScript, zapewniać kompatybilność wsteczną dla starszych przeglądarek, łączyć pliki, minify, wykonywać podział kodu itp.
Możliwe jest dynamiczne wygenerowanie tagu JavaScript i dołączenie go do dokumentu HTML z wnętrza innego kodu JavaScript. Spowoduje to załadowanie docelowego 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");
Może możesz użyć 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)
}