Jak vložím soubor JavaScript do jiného souboru JavaScript?

Existuje v JavaScriptu něco podobného jako @import v CSS, který vám umožňuje zahrnout soubor JavaScriptu do jiného souboru JavaScript?

Odpověď

Staré verze JavaScriptu neimportovaly, nezahrnovaly ani nevyžadovaly, takže bylo vyvinuto mnoho různých přístupů k tomuto problému.

Ale od roku 2015 (ES6) má JavaScript standard modulů ES6 pro import modulů do Node.js, který je také podporován většinou moderních prohlížečů.

Pro kompatibilitu se staršími prohlížeči lze použít nástroje pro vytváření, jako je Webpack a Rollup, a/nebo transpilační nástroje, jako je Babel.

Moduly ES6

Moduly ECMAScript (ES6) jsou v Node.js podporovány od verze 8.5 s --experimental-modules příznak a od minimálně Node.js v13.8.0 bez příznaku. Chcete-li povolit „ESM“ (oproti předchozímu systému modulů ve stylu CommonJS v Node.js [“CJS”]), použijte buď "type": "module" v package.json nebo dejte souborům příponu .mjs . (Podobně moduly napsané pomocí předchozího modulu CJS Node.js lze pojmenovat .cjs pokud je výchozí nastavení ESM.)

Pomocí package.json :

{
    "type": "module"
}

Poté module.js :

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

Potom main.js :

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

Pomocí .mjs , měli byste module.mjs :

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

Potom main.mjs :

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

Moduly ECMAScript v prohlížečích

Prohlížeče mají podporu pro přímé načítání modulů ECMAScript (nevyžadují se žádné nástroje jako Webpack) od Safari 10.1, Chrome 61, Firefox 60 a Edge 16. Zkontrolujte aktuální podporu na caniuse. Není třeba používat .mjs Node.js rozšíření; prohlížeče zcela ignorují přípony souborů v modulech/skriptech.

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

Přečtěte si více na https://jakearchibald.com/2017/es-modules-in-browsers/

Dynamické importy v prohlížečích

Dynamické importy umožňují skriptu načíst další skripty podle potřeby:

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

Přečtěte si více na https://developers.google.com/web/updates/2017/11/dynamic-import

Vyžaduje soubor Node.js

Starší styl modulu CJS, stále široce používaný v Node.js, je module.exports /require systém.

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

Existují další způsoby, jak JavaScript zahrnout externí obsah JavaScriptu do prohlížečů, které nevyžadují předběžné zpracování.

Načítání AJAX

Můžete načíst další skript pomocí volání AJAX a poté použít eval spustit to. Toto je nejpřímější způsob, ale je omezen na vaši doménu kvůli bezpečnostnímu modelu JavaScript sandbox. Pomocí eval také otevírá dveře k chybám, hackům a bezpečnostním problémům.

Načítání načítání

Stejně jako dynamické importy můžete načíst jeden nebo více skriptů s fetch volání pomocí slibů k řízení pořadí provádění pro závislosti skriptů pomocí knihovny 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)}`)
})

Načítání jQuery

Knihovna jQuery poskytuje funkci načítání na jednom řádku:

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

Dynamické načítání skriptu

Do HTML můžete přidat značku skriptu s adresou URL skriptu. Abyste se vyhnuli režii jQuery, je to ideální řešení.

Skript může být dokonce umístěn na jiném serveru. Dále prohlížeč vyhodnocuje kód. <script> tag lze vložit do webové stránky <head> , nebo vložen těsně před koncovku </body> tag.

Zde je příklad, jak by to mohlo fungovat:

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

Tato funkce přidá nový <script> tag na konec hlavičky stránky, kde je src atribut je nastaven na URL, které je dané funkci jako první parametr.

Obě tato řešení jsou diskutována a ilustrována v JavaScript Madness:Dynamic Script Loading.

Zjištění, kdy byl skript spuštěn

Nyní je tu velký problém, o kterém musíte vědět. To znamená, že načtete kód vzdáleně . Moderní webové prohlížeče načtou soubor a budou nadále provádět váš aktuální skript, protože vše načítají asynchronně, aby se zlepšil výkon. (To platí jak pro metodu jQuery, tak pro metodu ručního dynamického načítání skriptů.)

To znamená, že pokud použijete tyto triky přímo, nebudete moci nově načtený kód použít na dalším řádku poté, co jste jej požádali o načtení , protože se bude stále načítat.

Například:my_lovely_script.js obsahuje 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

Poté znovu načtete stránku stisknutím F5 . A funguje to! Matoucí…

Co s tím tedy dělat?

Můžete použít hack, který autor navrhuje v odkazu, který jsem vám dal. Stručně řečeno, pro lidi, kteří spěchají, používá událost ke spuštění funkce zpětného volání při načtení skriptu. Takže můžete vložit veškerý kód pomocí vzdálené knihovny do funkce zpětného volání. Například:

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

Poté napíšete kód, který chcete použít PO načtení skriptu do funkce lambda:

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

Pak to všechno spustíte:

loadScript("my_lovely_script.js", myPrettyCode);

Upozorňujeme, že skript se může spustit po načtení modelu DOM nebo dříve, v závislosti na prohlížeči a na tom, zda jste zahrnuli řádek script.async = false; . Existuje skvělý článek o načítání Javascriptu obecně, který o tom pojednává.

Sloučení/předzpracování zdrojového kódu

Jak je uvedeno v horní části této odpovědi, mnoho vývojářů používá ve svých projektech nástroje pro vytváření/transpilaci jako Parcel, Webpack nebo Babel, což jim umožňuje používat nadcházející syntaxi JavaScriptu, poskytovat zpětnou kompatibilitu pro starší prohlížeče, kombinovat soubory, minifikovat, provádět rozdělení kódu atd.