By Alec Smart


2009-06-04 11:59:50 8 Comments

Is there something in JavaScript similar to @import in CSS that allows you to include a JavaScript file inside another JavaScript file?

30 comments

@Torxed 2019-10-09 19:29:56

So this is a edge case. But if you need to load the JavaScript from a remote source, most modern browsers might block your cross-site requests due to CORS or something similar. So normal

<script src="https://another-domain.com/example.js"></script>

Won't work. And doing the document.createElement('script').src = '...' won't cut it either. Instead, what you could do is load the java-script as a resource via standard GET request, and do this:

<script type="text/javascript">
    var script = document.createElement('script');
    script.type = 'text/javascript';

    let xhr = new XMLHttpRequest();
    xhr.open("GET", 'https://raw.githubusercontent.com/Torxed/slimWebSocket/master/slimWebSocket.js', true);
    xhr.onreadystatechange = function() {
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
            script.innerHTML = this.responseText; // <-- This one
            document.head.appendChild(script);
        }
    }
    xhr.send();
</script>

By grabbing the content yourself, the browser won't notice malicious intents and allow you go do the request. Then you add it in <script>'s innerHTML instead. This still causes the browser (at least tested in Chrome) to parse/execute the script.

Again, this is a edge case use case. And you'll have no backwards compatibility or browser compliance probably. But fun/useful thing to know about.

@Kamil Kiełczewski 2019-07-10 16:12:09

ES6: YES use type="module" in script tag (support)

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

And in script.js file include another file like that:

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

In 'module.js' you must export function/class that you will import

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

Working example here.

@Kamil Dąbrowski 2019-07-03 15:43:49

Little Extend to lib from answer @Dan Dascalescu taken from facebook idea.

(function() {   
var __ = {};
this._ = function(name, callback) {
    if(__[name]==undefined) {
        __[name] = true;
        var firstScript = document.getElementsByTagName('script')[0],
          js = document.createElement('script');
          js.src =  name;
          js.onload = callback;
          firstScript.parentNode.insertBefore(js, firstScript);
    }
}
})();

(new _('https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js', function() {
 snowStorm.snowColor = '#99ccff';
}));

@Yairopro 2017-05-04 15:16:36

Here's a workaround for browsers (not Node.js) using HTML imports.

First, all JavaScript classes and scripts are not in .js files, but in .js.html files (the .js.html is just to recognize between HTML pages and complete JavaScript script/classes), inside <script> tags, like this:

MyClass.js.html:

<script>
   class MyClass {

      // Your code here..

   }

</script>

Then if you wish to import your class, you just need to use HTML imports:

<link rel="import" href="relative/path/to/MyClass.js.html"/>

<script>
   var myClass = new MyClass();
   // Your code here..
</script>

EDIT : HTML imports will be dropped

HTML imports are dropped, in favor of ES6 modules. You should use ES6 modules.

@Dan Dascalescu 2018-08-16 05:46:42

@Isaac Pak 2019-08-25 18:35:40

The question is not how to include a javascript file to an html file. It's how to include a javascript file to another javascript file.

@Andrej 2019-06-01 03:21:38

You can use my loadScript ES module for loading of the javaScript files.

Usage:

In your head tag, include the following code:

<script src="https://raw.githack.com/anhr/loadScriptNodeJS/master/build/loadScript.js"></script>

or

<script src="https://raw.githack.com/anhr/loadScriptNodeJS/master/build/loadScript.min.js"></script>

Now you can use window.loadScript for loading of your JavaScript files.

loadScript.async( src, [options] )

Asynchronous load JavaScript file.

src: URL of an external script file or array of the script file names.

options: followed options is available

onload: function () The onload event occurs when a script has been loaded. Default is undefined.

onerror: function ( str, e ) The onerror event occurs when an error has been occured. Default is undefined.

    str: error details

    e: event

appendTo: The node to which the new script will be append. Default is head node.

For example

loadScript.async( "JavaScript.js",
        {
            onload: function () {

                var str = 'file has been loaded successfully';
                console.log( str );

            },
            onerror: function ( str, e ) {

                console.error( str );

            },

        } );

Example of usage

@AlienKevin 2019-03-04 15:47:08

Dynamically Loading Multiple Scripts In Order

The above function works fine if you are loading only one script or you don't care about the loading order of multiple scripts. If you have some scripts that depends on others, you need to use Promise to specify the order of loading. The reason behind this is Javascript loads resources like scripts and images asynchronously. The loading sequence does not depends on the sequence of asynchronous calls, meaning script1 will not be guaranteed to load before script2 even if you call dynamicallyLoadScript("scrip1") before calling dynamicallyLoadScript("scrip2")

So here's another version of dynamicallyLoadScript that guarantees loading order:

// Based on: https://javascript.info/promise-basics#example-loadscript
function dynamicallyLoadScript(url) {
        return new Promise(function(resolve, reject) {
        var script = document.createElement("script");
        script.src = url;
        script.onload = resolve;
        script.onerror = () => reject(new Error(`Error when loading ${url}!`));
        document.body.appendChild(script);
    });

For more on Promises, see this excellent page.

The usage of this new dynamicallyLoadScript is very simple:

dynamicallyLoadScript("script1.js")
.then(() => dynamicallyLoadScript("script2.js"))
.then(() => dynamicallyLoadScript("script3.js"))
.then(() => dynamicallyLoadScript("script4.js"))
.then(() => dynamicallyLoadScript("script5.js"))
//...

Now the scripts are loaded in the order of script1.js, script2.js, script3.js, etc.

Run dependent code after script loads

In addition, you can immediately run code that uses the scripts after they are loaded. Just add another .then after the loading the script:

dynamicallyLoadScript("script1.js")
.then(() => dynamicallyLoadScript("script2.js"))
.then(() => foo()) // foo can be a function defined in either script1, script2
.then(() => dynamicallyLoadScript("script3.js"))
.then(() => {
     if (var1){ // var1 can be a global variable defined in either script1, script2, or script3
          bar(var1); // bar can be a function defined in either script1, script2, or script3
     } else {
          foo(var1);
     }
})
//more .then chains...

Handle loading errors

To display unhandled promise rejections (errors loading scripts, etc), put this unhandledrejection event listener at the top of your code:

// Based on: https://javascript.info/promise-error-handling#unhandled-rejections
window.addEventListener('unhandledrejection', function(event) {
     // the event object has two special properties:
     console.error(event.promise);// the promise that generated the error
     console.error(event.reason); // the unhandled error object
});

Now you will be notified of any script loading errors.


Shortcut Function

If you are loading a lot of scripts without executing code immediately after loading, this shorthand function may come in handy:

function dynamicallyLoadScripts(urls){
        if (urls.length === 0){
            return;
        }
        let promise = dynamicallyLoadScript(urls[0]);
        urls.slice(1).forEach(url => {
            promise = promise.then(() => dynamicallyLoadScript(url));
        });
    }

To use it, just pass in an array of script urls like this:

const scriptURLs = ["dist/script1.js", "dist/script2.js", "dist/script3.js"];
dynamicallyLoadScripts(scriptURLs);

The scripts will be loaded in the order they appear in the array.

@AlienKevin 2019-03-14 23:27:14

@johnktejik sorry for the mistake, I just fixed the url.

@Alireza 2018-05-22 12:41:21

Yes, there is...

Keep reading, in ES6, we can export and import part or whole javascript file into another one...

But wait, ES6 is not supported in all the browsers, so what you need is transpile it using babel.js for example...

So you create a class like below:

class Person {
  constructor(name) {
    this.name = name;
  }

  build() {
    return new Person(this);
  }
}

module.exports = Person;

in Another JavaScript file, do the import like:

import { Person } from 'Person';

You also can require the file like:

const Person = require('./Person');

If you are using older JavaScript version you can use requirejs:

requirejs(["helper/util"], function(util) {
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
});

If you want to stick to older version of stuffs, like jQuery, you can also use something like getScript:

jQuery.getScript('./another-script.js', function() {
    // Call back after another-script loaded
});

Last but not the least, don't forget you can do the traditional way of putting script together using <script> tag...

<script src="./first-script.js"></script>
<script src="./second-script.js"></script>
<script src="./third-script.js"></script>

There are also async and defer attribute which I should mention them here...

Note: There are several ways an external script can be executed:

  • If async is present: The script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing)
  • If async is not present and defer is present: The script is executed when the page has finished parsing
  • If neither async or defer is present: The script is fetched and executed immediately, before the browser continues parsing the page

@Milton Ain 2019-01-17 10:46:40

I tried this problem with another approach,

Ordering of script importing, has no effect in here.

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Trials</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="main.js"></script>
    <script src="scriptA.js"></script>
</head>

<body>
<h3>testing js in js (check console logs)</h3>
<button onclick="fnClick()">TEST</button>
</body>

</html>

main.js

function fnClick() {
  console.log('From\tAAAAA');
  var pro = myExpo.hello();
  console.log(pro);
}

scriptA.js

myExpo = {
    hello: function () {
        console.log('From\tBBBBB');
        return "Hello";
    }
}

and the result is

From    AAAAA
From    BBBBB
Hello

@e-satis 2009-06-04 12:13:28

The old versions of JavaScript had no import, include, or require, so many different approaches to this problem have been developed.

But since 2015 (ES6), JavaScript has had the ES6 modules standard to import modules in Node.js, which is also supported by most modern browsers.

For compatibility with older browsers, build and/or transpilation tools can be used.

ES6 Modules

ECMAScript (ES6) modules have been supported in Node.js since v8.5, with the --experimental-modules flag. All files involved must have the .mjs extension.

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

ECMAScript modules in browsers

Browsers have had support for loading ECMAScript modules directly (no tools like Webpack required) since Safari 10.1, Chrome 61, Firefox 60, and Edge 16. Check the current support at 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);
}

Read more at https://jakearchibald.com/2017/es-modules-in-browsers/

Dynamic imports in browsers

Dynamic imports let the script load other scripts as needed:

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

Read more at https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js require

The old style of importing modules, still widely used in Node.js, is the module.exports/require system.

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

There are other ways for JavaScript to include external JavaScript contents in browsers that do not require preprocessing.

AJAX Loading

You could load an additional script with an AJAX call and then use eval to run it. This is the most straightforward way, but it is limited to your domain because of the JavaScript sandbox security model. Using eval also opens the door to bugs, hacks and security issues.

Fetch Loading

Like Dynamic Imports you can load one or many scripts with a fetch call using promises to control order of execution for script dependencies using the Fetch Inject library:

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 Loading

The jQuery library provides loading functionality in one line:

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

Dynamic Script Loading

You could add a script tag with the script URL into the HTML. To avoid the overhead of jQuery, this is an ideal solution.

The script can even reside on a different server. Furthermore, the browser evaluates the code. The <script> tag can be injected into either the web page <head>, or inserted just before the closing </body> tag.

Here is an example of how this could work:

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

This function will add a new <script> tag to the end of the head section of the page, where the src attribute is set to the URL which is given to the function as the first parameter.

Both of these solutions are discussed and illustrated in JavaScript Madness: Dynamic Script Loading.

Detecting when the script has been executed

Now, there is a big issue you must know about. Doing that implies that you remotely load the code. Modern web browsers will load the file and keep executing your current script because they load everything asynchronously to improve performance. (This applies to both the jQuery method and the manual dynamic script loading method.)

It means that if you use these tricks directly, you won't be able to use your newly loaded code the next line after you asked it to be loaded, because it will be still loading.

For example: my_lovely_script.js contains 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

Then you reload the page hitting F5. And it works! Confusing...

So what to do about it ?

Well, you can use the hack the author suggests in the link I gave you. In summary, for people in a hurry, he uses an event to run a callback function when the script is loaded. So you can put all the code using the remote library in the callback function. For example:

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

Then you write the code you want to use AFTER the script is loaded in a lambda function:

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

Then you run all that:

loadScript("my_lovely_script.js", myPrettyCode);

Note that the script may execute after the DOM has loaded, or before, depending on the browser and whether you included the line script.async = false;. There's a great article on Javascript loading in general which discusses this.

Source Code Merge/Preprocessing

As mentioned at the top of this answer, many developers use build/transpilation tool(s) like Parcel, Webpack, or Babel in their projects, allowing them to use upcoming JavaScript syntax, provide backward compatibility for older browsers, combine files, minify, perform code splitting etc.

@e-satis 2010-07-15 03:53:21

Nope but somebody that uses something as advanced as Rhino or else wouldn't ask this question.

@Toad 2012-09-07 08:36:00

Just to be complete, there is a third way: In certain solutions when you control both javascript files, you can just make 1 giant javascript file which combines the content of both files.

@Michael Shopsin 2012-09-21 15:45:09

Loading scripts and posting forms through ajax are where jQuery shows its strength.

@Russell Silva 2012-12-14 23:28:54

Shouldn't "document.createElement("my_lovely_script.js");" in the example be "document.createElement("script")" ?

@Vince Panuccio 2013-01-06 09:39:09

How does eval open the door to hacks if it's your code that you're executing?

@e-satis 2013-01-06 22:29:59

I didn't say pirating, I said hack. For exemple, if you have code that have "use strict" in it, you will have to hack the hell out of it to make it work with eval.

@Trylks 2013-07-11 10:43:31

@e-satis I guess this import is a node.js thing, am I right?

@e-satis 2013-07-12 03:13:16

@Trylks Yes, there are several importers like this. Coffeescript got one as well.

@Dissident Rage 2013-07-19 13:49:35

The events for script don't seem to fire in anything but IE (using XP so 8). Tried using addEventListener as well to no avail.

@jave.web 2013-08-11 08:28:02

Someone should really mention the .onload JS native method in context of scripts relying on each other...

@lealam 2013-10-01 05:06:50

But my page does not know JQUERY This is exactly what I want to add!!! What to do?

@mfadel 2013-11-05 13:55:48

// Here you can use anything you defined in the loaded script I want to use functions includes in the loaded script everywhere after the use of getScript, Can I do that??

@Luke 2014-01-23 21:56:32

Note: If you run loadScript before the document is loaded, you'll get an error like "Cannot call method 'appendChild' of null".

@Bugalugs Nash 2014-04-03 11:28:02

Can't the whole problem of javascript files loading asynchronously be solved by simply putting the code that requires other javascript files inside of a window.onload function?

@Lego 2014-07-18 17:32:57

@midnite 2014-09-24 08:28:59

In the JavaScript Madness: Dynamic Script Loading webpage, I cannot really follow about the readyState bits. It says the states are quite nondeterministic (isn't it?) If yes, I have an idea of using setTimeout to keep checking the typeof functions until they are not "undefined". Is it good?

@albanx 2014-10-22 12:57:14

@Toad I would agree with you but suppose one needs to load as less javascript (maybe for performance for rendering faster) as it can, what is better load a lot of javascript at once or just load on demand when it is needed?

@Toad 2014-10-23 11:43:41

@albanx as with all performance related questions: measure. 1 load of data always beats multiple requests if everything needs to be loaded anyway. But, as you say, certain things only need to be loaded when it is needed, then chunking it up is a lot faster for the initial load. So perceived performance goes up. No clear cut anwer for this one unfortunately.

@albanx 2014-10-23 14:48:29

The $.getScript(), seems to hang the browser until the the script is loaded. But this seems to happens only with some javascripts. I tried with tiny.mce.js

@Laurens Rietveld 2014-12-10 16:17:53

Note that jQuery 1.x does not fire error callbacks! jQuery 2.x does, but does not support IE <= 8

@user137717 2015-04-11 10:30:41

@MichaelPaulukonis i'm using Javascript outside a browser can't I just use the features of a given shell / engine / interpreter? If I want to write standalone JS files and run them in Node, I imagine I can use require/

@Michael Paulukonis 2015-04-11 15:15:05

At the time I wrote my original comment (5 years ago) I had never heard of node, and was running JS on the command-line with the MS scripting library or whatever it was. The point still stands -- the answer is specifically browser-based while the question only says Javascript. So, node or other JS-engines seem applicable.

@ruhong 2015-04-29 08:32:21

Your answer requires some modification for IE (onreadystatechange event and the readyState property). Also, dynamic script loading does not benefit from the broswer's preload scanners. Recommend this HTML5Rocks article: html5rocks.com/en/tutorials/speed/script-loading

@bkrall 2015-06-15 23:21:57

When I use this loadScript function, IE9 appears to be loading my script multiple times.

@Flimm 2015-06-18 14:57:25

I edited the question to point out that jQuery's getScript is not as useful as it first appeared to be, so take the previous comments with a pinch of salt.

@Andrew Clavin 2016-07-05 05:56:51

@oriadam 2017-07-05 13:04:59

Note that $.getScript adds an annoying anticache to the script url to prevent browser caching. Most people would want the script cached. jQuery 1.12.0 or later support disabling the anticache using this: $.getScript({url: "file.js",cache:true},callback)

@Cees Timmerman 2017-10-03 15:43:50

Safari 10.1.2 on MacOS Sierra says SyntaxError: Unexpected keyword 'import'.

@Stefan 2017-12-26 15:12:48

The events do not work when using script type="module" to allow for ES6 imports. For a work around see this related SO question: stackoverflow.com/questions/47978809/…

@KthProg 2018-04-12 19:33:39

Why isn't just including the script on the HTML page before the 2nd script included as an option? The vast majority of the time, this makes perfect sense, and everything else is overkill.

@Ciro Santilli 新疆改造中心法轮功六四事件 2019-07-29 08:18:34

stackoverflow.com/questions/14521108/… says dynamic script loading needs to wait for onload event.

@Willem van der Veen 2018-08-10 17:11:30

There are several ways to implement modules in Javascript, Here are the 2 most popular ones:

ES6 Modules

Browsers do not support this moduling system yet so in order for you to use this syntax you must use a bundler like webpack. Using a bundler is better anyway because this can combine all of your different files into a single (or couple related) files. This will serve the files from the server to the client faster because each HTTP request has some associated overhead accompanied with it. Thus by reducing the overal HTTP request we improve the performance. Here is an example of ES6 modules:

// 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 (used in NodeJS)

This moduling system is used in NodeJS. You basically add your exports to an object which is called module.exports. You then can access this object via a require('modulePath'). Important here is to realize that these modules are being cached, so if you require() a certain module twice it will return the already created module.

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

@jasonleonhard 2018-07-24 01:45:36

Import and export modules using ES6 that work with Node.js

Name files with .mjs extension instead of .js

Create files

touch main.mjs lib.mjs

main.js

import { add } from './lib.mjs';
console.log(add(40, 2));

lib.mjs

export let add = (x,y) => {
  return x + y
}

Run

node --experimental-modules main.js

@jasonleonhard 2018-07-24 02:01:13

Using the file extension .mjs is a simple way of attaching metadata to files.

@jasonleonhard 2018-10-25 21:23:59

I just searched the page for .mjs and at the time of this comments post it was not included outside of my answer.

@chickens 2018-06-23 06:15:26

For NodeJS only, This worked for me the best!

I've tried most solutions here, but none helped me about just being able to load another file without changing scope. Finally I used this. Which preserves the scope and everything. It is as good as your code is in that point.

const fs = require('fs');
eval(fs.readFileSync('file.js')+'');

@chickens 2018-08-24 20:32:32

fs.readFileSync('file.js') reads file and returns Buffer, +'' returns it to a string.

@Chetabahana 2018-05-15 11:57:49

If you find there are 2 or more scripts occupied the same function when they are called, then we cannot be included them in the same times, we need to do it dynamically by user selection.

Including another files in jQuery using $.getScript works since the script will not be cached by default. So we are save to call another scripts. The calls can be arranged like this:

HTML

<select class="choice">
  <option value="script1" selected>Script-1</option>
  <option value="script2">Script-2</option>
</select>

JS

  $(".choice").change(on_change);

    var url = "https://example.com";
    $.url1 = url + "/script1.js";
    $.url2 = url + "/script2.js";

  function on_change() {
    if ($(".choice").val()=="script1") {
        script1();
    } else {
        script2();
    }

    // script1
    function script1() {   
      $.getScript($.url1, function( data, textStatus, jqxhr ) {
          //excecute here
      });  
    }

    // script2
    function script2() {
       $.getScript($.url2, function( data, textStatus, jqxhr ) {
          //excecute here
      });  
    }

@BioGeek 2018-06-21 14:31:48

The jsfiddle link now points to something completely different.

@Chetabahana 2018-06-21 18:37:21

There were a lot changes already so I deleted the sample link.

@Adam111p 2018-04-23 19:35:18

Please note that we usually use static scripts. So we want to be taken from the cache as much as possible. This saves network traffic and speeds up landing.

Usage

$.cachedScript( "ajax/test.js" ).done(function( script, textStatus ) {
  console.log( textStatus );
});

cache: true option has been added to the ajax method

@KthProg 2018-04-12 19:38:17

Although these answers are great, there is a simple "solution" that has been around since script loading existed, and it will cover 99.999% of most people's use cases. Just include the script you need before the script that requires it. For most projects it does not take long to determine which scripts are needed and in what order.

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

If script2 requires script1, this really is the absolute easiest way to do something like this. I'm very surprised no-one has brought this up, as it's the most obvious and simplest answer that will apply in nearly every single case.

@Stuart McIntyre 2019-07-10 01:52:56

I'm guessing for many people including myself, we need dynamic file name.

@KthProg 2019-07-17 13:24:06

@StuartMcIntyre in that case, set the src attribute of the script tag at runtime, and wait for the onload event (of course there are better solutions in that case in 2019).

@curlyhairedgenius 2015-01-11 20:19:47

There are a lot of potential answers for this question. My answer is obviously based on a number of them. This is what I ended up with after reading through all the answers.

The problem with $.getScript and really any other solution that requires a callback when loading is complete is that if you have multiple files that use it and depend on each other you no longer have a way to know when all scripts have been loaded (once they are nested in multiple files).

Example:

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

You are right when you say that you could specify Ajax to run synchronously or use XMLHttpRequest, but the current trend appears to be to deprecate synchronous requests, so you may not get full browser support now or in the future.

You could try to use $.when to check an array of deferred objects, but now you are doing this in every file and file2 will be considered loaded as soon as the $.when is executed not when the callback is executed, so file1 still continues execution before file3 is loaded. This really still has the same problem.

I decided to go backwards instead of forwards. Thank you document.writeln. I know it's taboo, but as long as it is used correctly this works well. You end up with code that can be debugged easily, shows in the DOM correctly and can ensure the order the dependencies are loaded correctly.

You can of course use $ ("body").append(), but then you can no longer debug correctly any more.

NOTE: You must use this only while the page is loading, otherwise you get a blank screen. In other words, always place this before / outside of document.ready. I have not tested using this after the page is loaded in a click event or anything like that, but I am pretty sure it'll fail.

I liked the idea of extending jQuery, but obviously you don't need to.

Before calling document.writeln, it checks to make sure the script has not already been loading by evaluating all the script elements.

I assume that a script is not fully executed until its document.ready event has been executed. (I know using document.ready is not required, but many people use it, and handling this is a safeguard.)

When the additional files are loaded the document.ready callbacks will get executed in the wrong order. To address this when a script is actually loaded, the script that imported it is re-imported itself and execution halted. This causes the originating file to now have its document.ready callback executed after any from any scripts that it imports.

Instead of this approach you could attempt to modify the jQuery readyList, but this seemed like a worse solution.

Solution:

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

Usage:

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

@Cannicide 2017-02-02 23:31:40

This is exactly what the currently accepted answer states: just not enough.

@curlyhairedgenius 2017-02-17 00:19:54

The main difference is that if there is a missing dependency it will add the script tag for the dependency, then also add the script tag for the calling file, and throw an error which halts execution. This causes the scripts to be processed and ran in the correct order and removes the need for callbacks. So the dependent script will be loaded and executed before the calling script while supporting nesting.

@David Spector 2018-12-06 19:38:08

As to "the current trend appears to be to deprecate synchronous requests," this is true only because many developers have misused them and made users wait unnecessarily. However, if the request is naturally synchronous, like an Include statement, then simple synchronous Ajax is just fine. I created a general JavaScript extension function that synchronously executes functions like reading a file that are not part of JavaScript by running a PHP "server" file, and find it very useful when writing apps using JavaScript . No local webserver is needed for such Ajax.

@rgb_life 2011-12-01 05:36:45

I came to this question because I was looking for a simple way to maintain a collection of useful JavaScript plugins. After seeing some of the solutions here, I came up with this:

  1. Set up a file called "plugins.js" (or extensions.js or what have you). Keep your plugin files together with that one master file.

  2. plugins.js will have an array called "pluginNames[]" that we will iterate over each(), then append a tag to the head for each 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(''); });

  3. manually call just the one file in your head:
    <script src="js/plugins/plugins.js"></script>

I found that even though all of the plugins were getting dropped into the head tag the way they ought to, they weren't always being run by the browser when you click into the page or refresh.

I found it's more reliable to just write the script tags in a PHP include. You only have to write it once and that's just as much work as calling the plugin using JavaScript.

@rgb_life 2011-12-01 05:55:18

@will, your solution looks much cleaner than mine and I'm worried I might have some errors if I use mine, as it makes use of .append(). So to use this, you can just call that function once for each plugin file you wish to include?

@Venu immadi 2013-11-13 09:18:17

If you want in pure JavaScript, you can use document.write.

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

If you use the jQuery library, you can use the $.getScript method.

$.getScript("another_script.js");

@Eisa Adil 2014-01-14 00:53:51

wouldn't document.write remove everything else?

@gabriel211 2016-11-16 22:36:29

Another approach is to use HTML imports. These can contain script references as well as stylesheet references.

You can just link an HTML file like

<link rel="import" href="vendorScripts.html"/>

Within the vendorScripts.html file you can include your script references like:

<script src="scripts/vendors/jquery.js"></script>
<script src="scripts/vendors/bootstrap.js"></script>
<script src="scripts/vendors/angular.js"></script>
<script src="scripts/vendors/angular-route.js"></script>

Look at HTML Imports for more details.

Unfortunately this only works in Chrome.

@Isaac Pak 2019-08-25 18:36:02

The question is not how to include a javascript file to an html file. It's how to include a javascript file to another javascript file.

@Kipras 2011-04-28 15:25:06

There actually is a way to load a JavaScript file not asynchronously, so you could use the functions included in your newly loaded file right after loading it, and I think it works in all browsers.

You need to use jQuery.append() on the <head> element of your page, that is:

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

However, this method also has a problem: if an error happens in the imported JavaScript file, Firebug (and also Firefox Error Console and Chrome Developer Tools as well) will report its place incorrectly, which is a big problem if you use Firebug to track JavaScript errors down a lot (I do). Firebug simply doesn't know about the newly loaded file for some reason, so if an error occurs in that file, it reports that it occurred in your main HTML file, and you will have trouble finding out the real reason for the error.

But if that is not a problem for you, then this method should work.

I have actually written a jQuery plugin called $.import_js() which uses this method:

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

So all you would need to do to import JavaScript is:

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

I also made a simple test for this at Example.

It includes a main.js file in the main HTML and then the script in main.js uses $.import_js() to import an additional file called included.js, which defines this function:

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

And right after including included.js, the hello() function is called, and you get the alert.

(This answer is in response to e-satis' comment).

@juanpastas 2013-03-12 15:24:40

I am trying this method, but is not working for me, the element just does not appear in head tag.

@MattDMo 2013-06-01 17:44:30

@juanpastas - use jQuery.getScript, that way you don't have to worry about writing the plugin...

@Flimm 2015-06-18 14:28:36

Does this technique really block until the imported script is both loaded and executed?

@Flimm 2015-06-18 15:36:07

Hmm, according to this article, appending a script element to head will cause it to run asynchronously, unless the async is specifically set to false.

@RedClover 2017-08-31 13:55:18

Shouldn't the script variable have html entities encoded? If the link contains the ", code will break

@phyatt 2018-01-11 22:32:57

I was looking for something like this so that I could use Jest & Node with some jquery javascript functions. I did something along the same idea... gist.github.com/peteristhegreat/…

@Alex 2019-01-18 09:50:45

@Flimm dear sir, me and my team thank for your comment and I personally owe you a beer of even money if we ever meet in person

@Isaac Gregson 2014-03-14 04:40:51

The @import syntax for achieving CSS-like JavaScript importing is possible using a tool such as Mixture via their special .mix file type (see here). I imagine the application simply uses one of the aforementioned methods interally, though I don't know.

From the Mixture documentation on .mix files:

Mix files are simply .js or .css files with .mix. in the file name. A mix file simply extends the functionality of a normal style or script file and allows you to import and combine.

Here's an example .mix file that combines multiple .js files into one:

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

Mixture outputs this as scripts-global.js and also as a minified version (scripts-global.min.js).

Note: I'm not in any way affiliated with Mixture, other than using it as a front-end development tool. I came across this question upon seeing a .mix JavaScript file in action (in one of the Mixture boilerplates) and being a bit confused by it ("you can do this?" I thought to myself). Then I realized that it was an application-specific file type (somewhat disappointing, agreed). Nevertheless, figured the knowledge might be helpful for others.

UPDATE: Mixture is now free (offline).

UPDATE: Mixture is now discontinued. Old mixture releases are still available

@b01 2015-04-19 19:07:32

This would be awesome if it were a node module.

@Isaac Gregson 2016-04-06 10:05:59

@b01 Sounds like a challenge ;) If only I had the time... perhaps someone else does?

@Christopher Dumas 2013-05-31 19:31:34

My usual method is:

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

It works great and uses no page-reloads for me. I've tried the AJAX method (one of the other answers) but it doesn't seem to work as nicely for me.

Here's an explanation of how the code works for those that are curious: essentially, it creates a new script tag (after the first one) of the URL. It sets it to asynchronous mode so it doesn't block the rest of the code, but calls a callback when the readyState (the state of the content to be loaded) changes to 'loaded'.

@Dmitry Sheiko 2017-07-20 15:15:02

In modern language it would be

function loadJs( url ){
  return new Promise( resolve => {
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    document.head.appendChild( script );
  });
}

@Neal 2017-07-20 18:25:32

Nice. Good solution.

@Eureka 2017-10-02 07:08:11

Concise and only needs ES5, and elegantly avoids formally having a call back. Thank you Dmitry!

@zipzit 2017-11-07 02:43:48

Wow, works in the browser without server. pi.js = simply var pi = 3.14 . call the loadJS() function via loadJs("pi.js").then(function(){ console.log(pi); });

@gm2008 2017-04-13 10:42:44

If you use Angular, then a plugin module $ocLazyLoad can help you to do that.

Here are some quotes from its documentation:

Load one or more modules & components with multiple files:

$ocLazyLoad.load(['testModule.js', 'testModuleCtrl.js', 'testModuleService.js']);

Load one or more modules with multiple files and specify a type where necessary: Note: When using the requireJS style formatting (with js! at the beginning for example), do not specify a file extension. Use one or the other.

$ocLazyLoad.load([
  'testModule.js',
   {type: 'css', path: 'testModuleCtrl'},
   {type: 'html', path: 'testModuleCtrl.html'},
   {type: 'js', path: 'testModuleCtrl'},
   'js!testModuleService',
   'less!testModuleLessFile'
]);

You can load external libs (not angular):

$ocLazyLoad.load(['testModule.js', 
   'bower_components/bootstrap/dist/js/bootstrap.js', 'anotherModule.js']);

You can also load css and template files:

 $ocLazyLoad.load([
     'bower_components/bootstrap/dist/js/bootstrap.js',
     'bower_components/bootstrap/dist/css/bootstrap.css',
     'partials/template1.html'
 ]);

@gm2008 2017-04-14 08:07:24

Please explain your down vote. This is a method that can include a javascript file in another javascript file. This is what the question is asking and is a method that no one else has mentioned.

@nornagon 2010-01-23 05:20:45

I just wrote this JavaScript code (using Prototype for DOM manipulation):

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

Usage:

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

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

@Mike Caron 2011-09-14 17:14:26

jrburke wrote this as RequireJS. Github: requirejs.org/docs/requirements.html

@trusktr 2014-03-31 03:35:26

Isn't this putting the loaded script outside of the scope where require() is called? Seems like eval() is the only way to do it within scope. Or is there another way?

@Akshay Vijay Jain 2017-05-15 05:00:57

It's very simple. Suppose you want to import file A.js in file B.js.

Now it's sure you have linked B.js in an HTML file, then just link A.js before B.js in that HTML file. Then the public variables of A.js will be available inside the B.js

This does not require a complicated answer.

@Isaac Pak 2019-08-25 18:28:53

The question is not how to include a javascript file to an html file. It's how to include a javascript file to another javascript file.

@Turnerj 2015-01-01 08:58:15

In case you are using Web Workers and want to include additional scripts in the scope of the worker, the other answers provided about adding scripts to the head tag, etc. will not work for you.

Fortunately, Web Workers have their own importScripts function which is a global function in the scope of the Web Worker, native to the browser itself as it is part of the specification.

Alternatively, as the second highest voted answer to your question highlights, RequireJS can also handle including scripts inside a Web Worker (likely calling importScripts itself, but with a few other useful features).

@draupnie 2015-04-17 01:56:54

Statement import is in ECMAScript 6.

Syntax

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 2015-04-22 20:34:42

... but is not supported by any browser to date, according to the compatibility table on the page you linked to.

@Jeremy Harris 2015-06-12 20:35:13

You can now write ES6 code and compile it with Babel.js (babeljs.io) to whatever your preferred current module system is (CommonJS/AMD/UMD): babeljs.io/docs/usage/modules

@Julian Avar 2016-06-25 23:36:21

@Zero3 Apparently the new IE (Edge) is the only one

@GreySage 2019-09-05 18:37:04

in 2019 IE still doesn't support this in any form. Why must microsoft be so against usability?

@Manohar Reddy Poreddy 2015-07-22 02:15:30

I had a simple issue, but I was baffled by responses to this question.

I had to use a variable (myVar1) defined in one JavaScript file (myvariables.js) in another JavaScript file (main.js).

For this I did as below:

Loaded the JavaScript code in the HTML file, in the correct order, myvariables.js first, then 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
    // ...
}
// ...

As you saw, I had use a variable in one JavaScript file in another JavaScript file, but I didn't need to include one in another. I just needed to ensure that the first JavaScript file loaded before the second JavaScript file, and, the first JavaScript file's variables are accessible in the second JavaScript file, automatically.

This saved my day. I hope this helps.

@Cannicide 2017-02-02 23:34:27

The problem with this answer is that it is not something like import. You need an HTML file to get stuff from one js file to another.

@Manohar Reddy Poreddy 2019-10-17 18:55:36

Very true. That's what some other answers are having it as solutions. However I had two JS files, one should use other JS's variables. No node.js, next.js, express.js, etc, so import OR require won't work, just had plain .js files.

@Cannicide 2019-10-18 21:54:10

Understandable, however, the question is actually asking to import a javascript file within another file itself, not just access its variables using an HTML file. For instance, assume you are making functionality for a button, and you use three different js files, one for click handling, one for hover handling, one for the callbacks for each of the other two. It would be helpful to import the other two js in the third js itself, and only have one <script> tag. This can help with organization. This answer simply is not what the question was asking for, and is not ideal in this context.

@Manohar Reddy Poreddy 2019-10-19 08:53:26

When I searched solution for my problem, I searched the right way, however Google thinks that this is the correct page so I landed here. That's why I wrote my answer here. Looks like, I did right, due to 15 upvotes above. To not waste other people's time, I have put a clear beginning on what my scenario is - have put HTML code first - which looks like helped, since you replied & said html is not your scenario. Hope that clarified.

@Cannicide 2019-10-19 17:03:16

Yes - indeed it looks like some people searched for a slightly different problem, to which this is a solution, and found this. Although this is not necessarily the answer to this question, it most definitely is the answer to another, similar question. As such, it is alright to have this answer here since it helps those who were looking for that answer. Thanks for that reply, that clarified it.

@Adem İlhan 2015-07-24 06:53:13

If your intention to load the JavaScript file is using the functions from the imported/included file, you can also define a global object and set the functions as object items. For instance:

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

You just need to be careful when you are including scripts in an HTML file. The order should be as in below:

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

Related Questions

Sponsored Content

89 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 6155621 View
  • 7682 Score
  • 89 Answer
  • Tags:   javascript arrays

37 Answered Questions

[SOLVED] How do I check whether a file exists without exceptions?

27 Answered Questions

[SOLVED] What does "use strict" do in JavaScript, and what is the reasoning behind it?

41 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

38 Answered Questions

[SOLVED] How do you get a timestamp in JavaScript?

86 Answered Questions

[SOLVED] How do JavaScript closures work?

47 Answered Questions

3 Answered Questions

14 Answered Questions

[SOLVED] How to move an element into another element?

  • 2009-08-14 20:14:45
  • Mark Richman
  • 1055223 View
  • 1618 Score
  • 14 Answer
  • Tags:   javascript jquery html

58 Answered Questions

[SOLVED] How do I redirect to another webpage?

Sponsored Content