Apakah ada sesuatu di JavaScript yang mirip dengan @import di CSS yang memungkinkan Anda memasukkan file JavaScript di dalam file JavaScript lain?

5847
Alec Smart 4 Juni 2009, 15:59

31 menjawab

Jawaban Terbaik

Versi lama JavaScript tidak mengimpor, menyertakan, atau memerlukan, sehingga banyak pendekatan berbeda untuk masalah ini telah dikembangkan.

Namun sejak 2015 (ES6), JavaScript telah memiliki modul ES6 standar untuk mengimpor modul di Node.js , yang juga didukung oleh browser paling modern.

Untuk kompatibilitas dengan browser lama, buat alat seperti Webpack dan Rollup dan/atau alat transpilasi seperti Babel dapat digunakan.

Modul ES6

Modul ECMAScript (ES6) telah didukung di Node.js sejak v8.5, dengan --experimental-modules flag, dan setidaknya Node.js v13.8.0 tanpa flag. Untuk mengaktifkan "ESM" (vs. sistem modul CommonJS-style sebelumnya dari Node.js ["CJS"]), Anda dapat menggunakan "type": "module" di package.json atau memberikan file ekstensi .mjs. (Demikian pula, modul yang ditulis dengan modul CJS Node.js sebelumnya dapat diberi nama .cjs jika default Anda adalah ESM.)

Menggunakan package.json:

{
    "type": "module"
}

Kemudian module.js:

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

Kemudian main.js:

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

Menggunakan .mjs, Anda akan memiliki module.mjs:

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

Kemudian main.mjs:

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

Modul ECMAScript di browser

Browser memiliki dukungan untuk memuat modul ECMAScript secara langsung (tidak diperlukan alat seperti Webpack) sejak Safari 10.1, Chrome 61, Firefox 60, dan Edge 16. Periksa dukungan saat ini di caniuse . Tidak perlu menggunakan ekstensi .mjs Node.js; browser sepenuhnya mengabaikan ekstensi file pada modul/skrip.

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

Baca selengkapnya di https://jakearchibald.com/2017/es-modules-in-browsers /

Impor dinamis di browser

Impor dinamis memungkinkan skrip memuat skrip lain sesuai kebutuhan:

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

Baca selengkapnya di https://developers.google.com/web/updates/ 2017/11/impor dinamis

Node.js membutuhkan

Gaya modul CJS yang lebih lama, masih banyak digunakan di Node.js, adalah module.exports/require sistem.

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

Ada cara lain untuk JavaScript untuk memasukkan konten JavaScript eksternal di browser yang tidak memerlukan pra-pemrosesan.

Memuat AJAX

Anda dapat memuat skrip tambahan dengan panggilan AJAX dan kemudian menggunakan eval untuk menjalankannya. Ini adalah cara yang paling mudah, tetapi terbatas pada domain Anda karena model keamanan kotak pasir JavaScript. Menggunakan eval juga membuka pintu bagi bug, peretasan, dan masalah keamanan.

Ambil Pemuatan

Seperti Impor Dinamis, Anda dapat memuat satu atau banyak skrip dengan panggilan fetch menggunakan janji untuk mengontrol urutan eksekusi untuk dependensi skrip menggunakan Ambil Injeksi perpustakaan:

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

Memuat jQuery

Pustaka jQuery menyediakan fungsionalitas pemuatan dalam satu baris:

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

Pemuatan Skrip Dinamis

Anda dapat menambahkan tag skrip dengan URL skrip ke dalam HTML. Untuk menghindari overhead jQuery, ini adalah solusi ideal.

Script bahkan dapat berada di server yang berbeda. Selanjutnya, browser mengevaluasi kode tersebut. Tag <script> dapat dimasukkan ke dalam halaman web <head>, atau disisipkan tepat sebelum tag </body> penutup.

Berikut adalah contoh bagaimana ini bisa bekerja:

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

Fungsi ini akan menambahkan tag <script> baru ke akhir bagian kepala halaman, di mana atribut src disetel ke URL yang diberikan ke fungsi sebagai parameter pertama.

Kedua solusi ini dibahas dan diilustrasikan dalam Kegilaan JavaScript: Pemuatan Skrip Dinamis.

Mendeteksi ketika skrip telah dieksekusi

Sekarang, ada masalah besar yang harus Anda ketahui. Melakukan hal itu menyiratkan bahwa Anda memuat kode dari jarak jauh. Peramban web modern akan memuat file dan terus menjalankan skrip Anda saat ini karena mereka memuat semuanya secara tidak sinkron untuk meningkatkan kinerja. (Ini berlaku untuk metode jQuery dan metode pemuatan skrip dinamis manual.)

Artinya, jika Anda menggunakan trik ini secara langsung, Anda tidak akan dapat menggunakan kode yang baru dimuat pada baris berikutnya setelah Anda memintanya untuk dimuat, karena kode tersebut akan tetap dimuat.

Misalnya: my_lovely_script.js berisi 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

Kemudian Anda memuat ulang halaman dengan menekan F5. Dan itu berhasil! Membingungkan...

Jadi apa yang harus dilakukan?

Nah, Anda dapat menggunakan peretasan yang disarankan penulis di tautan yang saya berikan kepada Anda. Singkatnya, untuk orang yang terburu-buru, ia menggunakan acara untuk menjalankan fungsi panggilan balik saat skrip dimuat. Jadi Anda bisa meletakkan semua kode menggunakan perpustakaan jarak jauh di fungsi panggilan balik. Sebagai contoh:

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

Kemudian Anda menulis kode yang ingin Anda gunakan SETELAH skrip dimuat dalam fungsi lambda:

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

Kemudian Anda menjalankan semua itu:

loadScript("my_lovely_script.js", myPrettyCode);

Perhatikan bahwa skrip dapat dijalankan setelah DOM dimuat, atau sebelumnya, bergantung pada browser dan apakah Anda menyertakan baris script.async = false;. Ada artikel bagus tentang pemuatan Javascript secara umum yang membahas hal ini.

Penggabungan Kode Sumber/Pemrosesan Awal

Seperti disebutkan di bagian atas jawaban ini, banyak pengembang menggunakan alat build/transpilasi seperti Parcel, Webpack, atau Babel dalam proyek mereka, memungkinkan mereka untuk menggunakan sintaks JavaScript yang akan datang, menyediakan kompatibilitas mundur untuk browser lama, menggabungkan file, mengecilkan, melakukan pemecahan kode dll.

4742
T.J. Crowder 21 Maret 2020, 12:09
Saya telah memuat div secara dinamis dengan mengklik menu tanpa memuat halaman dengan menggunakan hash URL. Masalah saya adalah ketika saya mengklik halaman yang sama 2/3 kali js memuat 2/3 kali. itu sebabnya setiap peristiwa terjadi beberapa kali. Saya ingin memeriksa file js yang sudah dimuat ke footer/head sebelum menambahkan kode itu: var js = document.createElement("script"); js.type = "teks/javascript"; js.src = jsFilePath; document.body.appendChild(js);
 – 
Alien
15 Agustus 2020, 20:33
2
Ya Tuhan, Anda baru saja menulis seluruh makalah! Terima kasih banyak! Anda seorang legenda. :)
 – 
Lathryx
26 Oktober 2020, 16:40
Terima kasih atas masukannya. Apakah ada cara untuk memasukkan skrip di awal kepala?
 – 
Glund
5 Januari 2021, 18:22
Itu pasti jawaban terpanjang yang pernah lihat.
 – 
theknightD2
24 Januari 2021, 19:00

Skrip ini akan menambahkan file JavaScript ke bagian atas tag <script> lainnya:

(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
Peter Mortensen 19 Oktober 2014, 22:14

Sebenarnya ada ada cara untuk memuat file JavaScript tidak secara asinkron, sehingga Anda dapat menggunakan fungsi yang disertakan dalam file yang baru dimuat segera setelah memuatnya, dan saya pikir itu berfungsi di semua browser.

Anda perlu menggunakan jQuery.append() pada elemen <head> halaman Anda, yaitu:

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

Namun, metode ini juga memiliki masalah: jika terjadi kesalahan pada file JavaScript yang diimpor, Firebug< /a> (dan juga Konsol Kesalahan Firefox dan Alat Pengembang Chrome juga) akan melaporkan tempatnya salah, yang merupakan masalah besar jika Anda menggunakan Firebug untuk melacak banyak kesalahan JavaScript (saya lakukan). Firebug sama sekali tidak tahu tentang file yang baru dimuat karena beberapa alasan, jadi jika terjadi kesalahan pada file itu, ia melaporkan bahwa itu terjadi di HTML, dan Anda akan kesulitan menemukan alasan sebenarnya dari kesalahan tersebut.

Tetapi jika itu bukan masalah bagi Anda, maka metode ini akan berhasil.

Saya sebenarnya telah menulis sebuah plugin jQuery bernama $.import_js() yang menggunakan metode ini:

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

Jadi yang perlu Anda lakukan untuk mengimpor JavaScript adalah:

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

Saya juga membuat tes sederhana untuk ini di Contoh.

Ini termasuk file main.js di HTML utama dan kemudian skrip di main.js menggunakan $.import_js() untuk mengimpor file tambahan bernama included.js, yang mendefinisikan fungsi ini:

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

Dan tepat setelah menyertakan included.js, fungsi hello() dipanggil, dan Anda mendapatkan peringatan.

(Jawaban ini sebagai tanggapan atas komentar e-satis).

212
31piy 21 Maret 2018, 07:29

Cara lain, yang menurut saya jauh lebih bersih, adalah dengan membuat permintaan Ajax yang sinkron daripada menggunakan tag <script>. Yang juga bagaimana Node.js menanganinya.

Berikut ini contoh menggunakan 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);
        }
    });
}

Anda kemudian dapat menggunakannya dalam kode Anda seperti biasanya menggunakan include:

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

Dan dapat memanggil fungsi dari skrip yang diperlukan di baris berikutnya:

subscript.doSomethingCool(); 
167
Peter Mortensen 28 September 2013, 16:55

Ada kabar baik untuk Anda. Segera Anda akan dapat memuat kode JavaScript dengan mudah. Ini akan menjadi cara standar untuk mengimpor modul kode JavaScript dan akan menjadi bagian dari inti JavaScript itu sendiri.

Anda cukup menulis import cond from 'cond.js'; untuk memuat makro bernama cond dari file cond.js.

Jadi, Anda tidak perlu bergantung pada kerangka kerja JavaScript apa pun dan Anda juga tidak perlu membuat panggilan Ajax secara eksplisit.

Mengacu pada:

108
Peter Mortensen 19 Oktober 2014, 22:05

Dimungkinkan untuk secara dinamis menghasilkan tag JavaScript dan menambahkannya ke dokumen HTML dari dalam kode JavaScript lainnya. Ini akan memuat file JavaScript yang ditargetkan.

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");
106
Peter Mortensen 28 September 2013, 16:44

Pernyataan import ada di ECMAScript 6.

Sintaksis

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;
78
Peter Mortensen 11 Desember 2016, 12:47

Mungkin Anda dapat menggunakan fungsi ini yang saya temukan di halaman ini Bagaimana cara memasukkan JavaScript file dalam file 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)
}
64
Ajeet Lakhani 15 November 2014, 20:01

Ini adalah versi sinkron tanpa 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);
}

Perhatikan bahwa untuk mendapatkan lintas domain yang berfungsi ini, server perlu menyetel header allow-origin dalam responsnya.

57
Flimm 18 Juni 2015, 17:44

Saya baru saja menulis kode JavaScript ini (menggunakan Prototipe untuk DOM manipulasi):

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

Pemakaian:

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

Inti: http://gist.github.com/284442.

52
Talha Awan 26 Juni 2017, 00:04

Inilah versi umum tentang bagaimana Facebook melakukannya untuk tombol Suka mereka yang ada di mana-mana:

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

Jika bekerja untuk Facebook, itu akan bekerja untuk Anda.

Alasan mengapa kami mencari elemen script pertama daripada head atau body adalah karena beberapa browser tidak membuatnya jika tidak ada, tetapi kami dijamin memiliki script elemen - yang ini. Baca lebih lanjut di http://www.jspatterns.com/the-ridiculous- case-of-adding-a-script-element/.

46
Dan Dascalescu 8 Juli 2015, 05:48

Jika Anda menginginkannya dalam JavaScript murni, Anda dapat menggunakan document.write.

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

Jika Anda menggunakan perpustakaan jQuery, Anda dapat menggunakan metode $.getScript.

$.getScript("another_script.js");
45
Peter Mortensen 3 Oktober 2020, 23:47

Anda juga dapat merakit skrip menggunakan PHP:

Berkas 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
32
Peter Mortensen 28 September 2013, 16:50

Sebagian besar solusi yang ditampilkan di sini menyiratkan pemuatan dinamis. Saya malah mencari kompiler yang merakit semua file yang bergantung menjadi satu file output. Sama seperti Kurang/Sass menangani aturan-at @import CSS. Karena saya tidak menemukan sesuatu yang layak seperti ini, saya menulis alat sederhana untuk memecahkan masalah.

Jadi inilah compilernya, https://github.com/dsheiko/jsic, yang menggantikan $import("file-path") dengan yang diminta isi file dengan aman. Berikut adalah plugin Grunt yang sesuai: https:// github.com/dsheiko/grunt-jsic.

Di cabang master jQuery, mereka hanya menggabungkan file sumber atom menjadi satu yang dimulai dengan intro.js dan diakhiri dengan outtro.js. Itu tidak cocok untuk saya karena tidak memberikan fleksibilitas pada desain kode sumber. Lihat cara kerjanya dengan jsic:

src/main.js

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

src/Form/Input/Tel.js

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

Sekarang kita dapat menjalankan kompiler:

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

Dan dapatkan file gabungan

build/main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
30
Peter Mortensen 19 Oktober 2014, 22:13

Jika niat Anda untuk memuat file JavaScript adalah menggunakan fungsi dari file yang diimpor/disertakan, Anda juga dapat mendefinisikan objek global dan mengatur fungsi sebagai item objek. Contohnya:

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

Anda hanya perlu berhati-hati saat memasukkan skrip dalam file HTML. Urutannya harus seperti di bawah ini:

<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>
27
Peter Mortensen 11 Desember 2016, 12:42

Atau alih-alih menyertakan saat run time, gunakan skrip untuk digabungkan sebelum mengunggah.

Saya menggunakan Sproket (Saya tidak tahu apakah ada yang lain). Anda membuat kode JavaScript dalam file terpisah dan menyertakan komentar yang diproses oleh mesin Sprocket sebagai penyertaan. Untuk pengembangan, Anda dapat memasukkan file secara berurutan, lalu untuk produksi menggabungkannya ...

Lihat juga:

23
Peter Mortensen 19 Oktober 2014, 22:02

Ini harus dilakukan:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
23
Peter Mortensen 2 November 2014, 16:50

Saya memiliki masalah sederhana, tetapi saya bingung dengan tanggapan atas pertanyaan ini.

Saya harus menggunakan variabel (myVar1) yang didefinisikan dalam satu file JavaScript (myvariables.js) di file JavaScript lain (main.js).

Untuk ini saya lakukan seperti di bawah ini:

Memuat kode JavaScript dalam file HTML, dalam urutan yang benar, myvariables.js terlebih dahulu, lalu main.js:

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

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

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

File: myvariables.js

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

File: main.js

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

Seperti yang Anda lihat, saya telah menggunakan variabel dalam satu file JavaScript di file JavaScript lain, tetapi saya tidak perlu memasukkannya ke dalam file lain. Saya hanya perlu memastikan bahwa file JavaScript pertama dimuat sebelum file JavaScript kedua, dan, variabel file JavaScript pertama dapat diakses di file JavaScript kedua, secara otomatis.

Ini menyelamatkan hari saya. Saya harap ini membantu.

21
Peter Mortensen 11 Desember 2016, 12:45

Dalam bahasa modern dengan pemeriksaan apakah skrip telah dimuat, itu akan menjadi:

function loadJs( url ){
  return new Promise(( resolve, reject ) => {
    if (document.querySelector( `head > script[ src = "${url}" ]`) !== null ){
        console.warn( `script already loaded: ${url}` );
        resolve();
    }
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    script.onerror = function( reason ){
        // This can be useful for your error-handling code
        reason.message = `error trying to load script ${url}`;
        reject( reason );
    };
    document.head.appendChild( script );
  });
}

Penggunaan (async/menunggu):

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

Atau

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

Penggunaan (Janji):

loadJs( "https://.../script.js" ).then( res => {} ).catch( err => {} );
18
Peter Mortensen 3 Oktober 2020, 22:47
Ini sangat bagus jika Anda ingin menghindari keterlibatan dalam modul, dan tidak ingin menggunakan fungsi panggilan balik, tetapi ingin menggunakan async / await.
 – 
mike rodent
19 Juli 2020, 10:25

Jika Anda menggunakan Web Worker dan ingin menyertakan skrip tambahan dalam lingkup pekerja, jawaban lain yang diberikan tentang menambahkan skrip ke tag head, dll. tidak akan berfungsi untuk Anda.

Untungnya, Web Worker memiliki fungsi importScripts sendiri yang merupakan fungsi global dalam lingkup Web Worker, asli dari browser itu sendiri seperti adalah bagian dari spesifikasi.

Atau, sebagai jawaban dengan suara terbanyak kedua untuk sorotan pertanyaan Anda, RequireJS juga dapat menangani penyertaan skrip di dalam Web Worker (kemungkinan memanggil importScripts itu sendiri, tetapi dengan beberapa fitur berguna lainnya).

17
Community 23 Mei 2017, 15:34

Sintaks @import untuk mencapai pengimporan JavaScript seperti CSS dimungkinkan menggunakan alat seperti Mixture melalui jenis file .mix khusus mereka (lihat di sini). Saya berasumsi aplikasi melakukan ini melalui salah satu metode yang disebutkan di atas.

Dari dokumentasi Campuran pada file .mix:

File campuran hanyalah file .js atau .css dengan .mix. dalam nama file. File campuran hanya memperluas fungsionalitas gaya normal atau file skrip dan memungkinkan Anda untuk mengimpor dan menggabungkan.

Berikut adalah contoh file .mix yang menggabungkan beberapa file .js menjadi satu:

// 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";

Campuran menghasilkan ini sebagai scripts-global.js dan juga sebagai versi yang diperkecil (scripts-global.min.js).

Catatan: Saya sama sekali tidak berafiliasi dengan Mixture, selain menggunakannya sebagai alat pengembangan front-end. Saya menemukan pertanyaan ini setelah melihat file JavaScript .mix beraksi (di salah satu boilerplate Campuran) dan menjadi sedikit bingung karenanya ("Anda dapat melakukan ini?" Saya berpikir sendiri). Kemudian saya menyadari bahwa itu adalah jenis file khusus aplikasi (agak mengecewakan, setuju). Namun demikian, pikir pengetahuan itu mungkin bermanfaat bagi orang lain.

Catatan: Campuran dihentikan pada 26/07/2016 (setelah menjadi sumber terbuka pada 2015/04/12).

16
Isaac Gregson 5 Oktober 2020, 20:34
Lebih baik menghindari "Pembaruan" (informasi meta yang termasuk dalam riwayat revisi untuk posting ini). Alih-alih menerapkannya ke konten (bukan posting ini), mis. "Campuran bersumber terbuka pada 04-12-2015, dan dihentikan pada 26-07-2016."
 – 
Peter Mortensen
3 Oktober 2020, 23:50

Meskipun jawaban ini bagus, ada "solusi" sederhana yang telah ada sejak pemuatan skrip ada, dan itu akan mencakup 99,999% kasus penggunaan kebanyakan orang. Cukup sertakan skrip yang Anda butuhkan sebelum skrip yang membutuhkannya. Untuk sebagian besar proyek, tidak perlu waktu lama untuk menentukan skrip mana yang diperlukan dan dalam urutan apa.

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

Jika script2 membutuhkan script1, ini benar-benar cara termudah mutlak untuk melakukan sesuatu seperti ini. Saya sangat terkejut tidak ada yang mengemukakan hal ini, karena ini adalah jawaban paling jelas dan paling sederhana yang akan berlaku di hampir setiap kasus.

15
KthProg 12 April 2018, 22:38
Ini adalah jawaban yang bagus. Ini mungkin terlewatkan karena tidak menjawab pertanyaan secara langsung, tetapi penting juga untuk memahami bahwa 'Anda biasanya tidak perlu melakukan itu'. Terutama karena solusi lain sangat berantakan.
 – 
Nathan Kovner
27 Juli 2020, 21:44
Tapi ini hanya berfungsi di browser web? Bagaimana dengan pengujian unit offline (misalnya, di bawah Node.js)?
 – 
Peter Mortensen
3 Oktober 2020, 23:31
var js = document.createElement("script");

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

document.body.appendChild(js);
14
Spudley 22 Agustus 2012, 10:44

Metode saya yang biasa adalah:

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

Ini berfungsi dengan baik dan tidak menggunakan pemuatan ulang halaman untuk saya. Saya sudah mencoba metode AJAX (salah satu jawaban lain) tetapi sepertinya tidak berfungsi dengan baik untuk saya.

Berikut penjelasan tentang cara kerja kode untuk mereka yang penasaran: pada dasarnya, ini membuat tag skrip baru (setelah yang pertama) dari URL. Ini mengaturnya ke mode asinkron sehingga tidak memblokir sisa kode, tetapi memanggil panggilan balik ketika readyState (keadaan konten yang akan dimuat) berubah menjadi 'dimuat'.

13
Christopher Dumas 26 Agustus 2017, 20:02

Saya menulis modul sederhana yang mengotomatiskan pekerjaan mengimpor/menyertakan skrip modul dalam JavaScript. Untuk penjelasan rinci tentang kode, lihat posting blog JavaScript memerlukan / mengimpor / menyertakan modul.

// ----- 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);
};
12
Peter Mortensen 19 Oktober 2014, 22:26

Modul ES6

Ya, gunakan type="module" dalam tag skrip (dukungan):

<script type="module" src="script.js"></script>

Dan dalam file script.js sertakan file lain seperti ini:

import { hello } from './module.js';
...
// alert(hello());

Di 'module.js' Anda harus mengekspor fungsi/ class yang akan Anda impor:

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

contoh yang berfungsi ada di sini.

11
Peter Mortensen 3 Oktober 2020, 23:06

Ada juga Head.js. Sangat mudah untuk berurusan dengan:

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

Seperti yang Anda lihat, ini lebih mudah daripada Require.js dan senyaman metode $.getScript jQuery. Ini juga memiliki beberapa fitur lanjutan, seperti pemuatan bersyarat, deteksi fitur, dan banyak lagi.

10
Peter Mortensen 19 Oktober 2014, 22:18

Ada banyak jawaban potensial untuk pertanyaan ini. Jawaban saya jelas didasarkan pada beberapa dari mereka. Inilah yang saya dapatkan setelah membaca semua jawaban.

Masalah dengan $.getScript dan benar-benar solusi lain yang memerlukan panggilan balik saat pemuatan selesai adalah jika Anda memiliki banyak file yang menggunakannya dan bergantung satu sama lain, Anda tidak lagi memiliki cara untuk mengetahui kapan semua skrip telah dimuat (setelah mereka bersarang di banyak file).

Contoh:

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

Anda benar ketika Anda mengatakan bahwa Anda dapat menentukan Ajax untuk dijalankan secara sinkron atau menggunakan XMLHttpRequest, tetapi tren saat ini tampaknya menghentikan permintaan sinkron, jadi Anda mungkin tidak mendapatkan dukungan browser penuh sekarang atau di masa mendatang.

Anda dapat mencoba menggunakan $.when untuk memeriksa larik objek yang ditangguhkan, tetapi sekarang Anda melakukan ini di setiap file dan file2 akan dianggap dimuat segera setelah $.when dijalankan bukan saat panggilan balik dijalankan , jadi file1 masih melanjutkan eksekusi sebelum file3 dimuat. Ini benar-benar masih memiliki masalah yang sama.

Saya memutuskan untuk mundur daripada maju. Terima kasih document.writeln. Saya tahu itu tabu, tetapi selama digunakan dengan benar, ini berfungsi dengan baik. Anda berakhir dengan kode yang dapat di-debug dengan mudah, ditampilkan di DOM dengan benar dan dapat memastikan urutan dependensi dimuat dengan benar.

Anda tentu saja dapat menggunakan $ ("body").append(), tetapi kemudian Anda tidak dapat lagi melakukan debug dengan benar lagi.

CATATAN: Anda harus menggunakan ini hanya saat halaman sedang dimuat, jika tidak, Anda akan mendapatkan layar kosong. Dengan kata lain, selalu letakkan ini sebelum / di luar document.ready. Saya belum menguji menggunakan ini setelah halaman dimuat dalam acara klik atau semacamnya, tetapi saya cukup yakin itu akan gagal.

Saya menyukai gagasan untuk memperluas jQuery, tetapi jelas Anda tidak perlu melakukannya.

Sebelum memanggil document.writeln, ia memeriksa untuk memastikan skrip belum dimuat dengan mengevaluasi semua elemen skrip.

Saya berasumsi bahwa skrip tidak sepenuhnya dieksekusi sampai acara document.ready-nya dieksekusi. (Saya tahu menggunakan document.ready tidak diperlukan, tetapi banyak orang menggunakannya, dan menangani ini adalah perlindungan.)

Saat file tambahan dimuat, callback document.ready akan dieksekusi dalam urutan yang salah. Untuk mengatasi ini ketika skrip benar-benar dimuat, skrip yang mengimpornya diimpor ulang sendiri dan eksekusi dihentikan. Ini menyebabkan file asal sekarang memiliki panggilan balik document.ready yang dieksekusi setelah salah satu dari skrip apa pun yang diimpornya.

Alih-alih pendekatan ini, Anda dapat mencoba memodifikasi jQuery readyList, tetapi ini sepertinya solusi yang lebih buruk.

Larutan:

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

Pemakaian:

File3:

var f3obj = "file3";

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

File2:

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

File1:

$.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"
});
10
Community 20 Juni 2020, 12:12

Saya sampai pada pertanyaan ini karena saya sedang mencari cara sederhana untuk memelihara koleksi plugin JavaScript yang berguna. Setelah melihat beberapa solusi di sini, saya menemukan ini:

  1. Siapkan file bernama "plugins.js" (atau extensions.js atau apa pun yang Anda inginkan). Simpan file plugin Anda bersama dengan satu file master itu.

  2. plugins.js akan memiliki larik bernama pluginNames[] yang akan kita ulangi lebih dari each(), lalu tambahkan tag <script> ke kepala untuk setiap plugin

//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. Panggil hanya satu file di kepala Anda secara manual:
    <script src="js/plugins/plugins.js"></script>

TAPI:

Meskipun semua plugin dimasukkan ke dalam tag kepala seperti yang seharusnya, mereka tidak selalu dijalankan oleh browser saat Anda mengklik halaman atau menyegarkan.

Saya merasa lebih dapat diandalkan untuk hanya menulis tag skrip dalam PHP termasuk. Anda hanya perlu menulisnya sekali dan itu sama pentingnya dengan memanggil plugin menggunakan JavaScript.

10
rgb_life 10 Januari 2020, 08:03

Ada beberapa cara untuk mengimplementasikan modul dalam JavaScript. Berikut adalah dua yang paling populer:

Modul ES6

Browser belum mendukung sistem modulasi ini, jadi agar Anda dapat menggunakan sintaks ini, Anda harus menggunakan bundler seperti Paket Web. Menggunakan bundler lebih baik karena ini dapat menggabungkan semua file Anda yang berbeda menjadi satu (atau beberapa file terkait). Ini akan menyajikan file dari server ke klien lebih cepat karena setiap permintaan HTTP memiliki beberapa overhead terkait yang menyertainya. Jadi dengan mengurangi keseluruhan permintaan HTTP, kami meningkatkan kinerja. Berikut adalah contoh modul 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 (digunakan di Node.js)

Sistem modulasi ini digunakan di Node.js. Anda pada dasarnya menambahkan ekspor Anda ke objek yang disebut module.exports. Anda kemudian dapat mengakses objek ini melalui require('modulePath'). Penting di sini untuk menyadari bahwa modul-modul ini sedang di-cache, jadi jika Anda require() modul tertentu dua kali akan mengembalikan modul yang sudah dibuat.

// 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
10
Peter Mortensen 3 Oktober 2020, 23:17

Jika ada yang mencari sesuatu yang lebih canggih, coba RequireJS. Anda akan mendapatkan manfaat tambahan seperti manajemen ketergantungan, konkurensi yang lebih baik, dan menghindari duplikasi (yaitu, mengambil skrip lebih dari sekali).

Anda dapat menulis file JavaScript Anda di "modul" dan kemudian mereferensikannya sebagai dependensi di skrip lain. Atau Anda dapat menggunakan RequireJS sebagai solusi sederhana "dapatkan skrip ini".

Contoh:

Tentukan dependensi sebagai modul:

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.js adalah file JavaScript "utama" Anda yang bergantung pada some-dependency.js

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

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

Kutipan dari GitHub README:

RequireJS memuat file JavaScript biasa serta modul yang lebih jelas. Ini dioptimalkan untuk penggunaan dalam browser, termasuk di Web Worker, tetapi dapat digunakan di lingkungan JavaScript lain, seperti Rhino dan Node.js. Ini mengimplementasikan API Modul Asinkron.

RequireJS menggunakan tag skrip biasa untuk memuat modul/file, jadi seharusnya memungkinkan untuk debugging mudah. Ini dapat digunakan hanya untuk memuat yang ada file JavaScript, jadi Anda dapat menambahkannya ke proyek yang ada tanpa harus menulis ulang file JavaScript Anda.

...

592
Peter Mortensen 28 September 2013, 17:11