Join the Stack Overflow Community
Stack Overflow is a community of 6.4 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

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

share|improve this question
31  
27  
@Daniel, I do not want to use an AJAX call. – Alec Smart Jun 4 '09 at 12:02
    
Take a look at the other questions. – Daniel A. White Jun 4 '09 at 12:26
2  
Why not declaring the imported file before the other one that requires it, simply using ordered script tags? – falsarella Jan 6 '15 at 21:07
2  
@Claudiu That wouldn't help to import anything, but it should work as well. If you have a JS file that depends of another JS file, just declare the script tags of the dependency files first, so the later will already have its dependencies loaded. If you have a situation where it isn't a possible approach, the answers here should be helpful. – falsarella Feb 19 at 12:29

44 Answers 44

Here is a Grunt plugin allowing you to use @import "path/to/file.js"; syntax in any file including JavaScript files. It can be paired with uglify or watch or any other plugin.

It can be installed with npm install: https://npmjs.org/package/grunt-import

share|improve this answer

Keep it nice, short, simple, and maintainable! :]

// 3rd party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
    FULL_PATH + 'plugins/script.js'      // Script example
    FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library 
    FULL_PATH + 'plugins/crypto-js/hmac-sha1.js',      // CryptoJS
    FULL_PATH + 'plugins/crypto-js/enc-base64-min.js'  // CryptoJS
];

function load(url)
{
    var ajax = new XMLHttpRequest();
    ajax.open('GET', url, false);
    ajax.onreadystatechange = function ()
    {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4)
        {
            switch(ajax.status)
            {
                case 200:
                    eval.apply( window, [script] );
                    console.log("library loaded: ", url);
                    break;
                default:
                    console.log("ERROR: library not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

 // initialize a single load 
load('plugins/script.js');

// initialize a full load of scripts
if (s.length > 0)
{
    for (i = 0; i < s.length; i++)
    {
        load(s[i]);
    }
}

This code is simply a short functional example that could require additional feature functionality for full support on any (or given) platform.

share|improve this answer

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

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

For this I did as below:
Loaded the JS 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 variable in one JS file in another JS file
but I din't need to include one in another
I just needed to ensure that 1st JS file loaded before 2nd JS file,
and, 1st JS file's variables are accessible in 2nd JS file, automatically.

This saved my day. Hope this helps.

share|improve this answer
1  
This is exactly what I needed, thanks for this simple demonstration. – Paul Aug 30 at 9:23

Don't forget to check out LAB.js!

<script type="text/javascript">
       $LAB
       .script("jquery-1.8.3.js").wait()
       .script("scripts/clientscript.js");      
</script>
share|improve this answer
2  
Unfortunately, it's not really under development any more, and there's no guarantee that some future browser or JS engine or language version won't break it. You should try to be as up-to-date as possible with JS, although there is something to be said for stability. Even though this could be a good option for somebody, I'd much rather steer them toward RequireJS or jQuery.getScript(), both of which are stable and under constant development. – MattDMo Jun 1 '13 at 18:02
var s=["Hscript.js","checkRobert.js","Hscript.js"];
for(i=0;i<s.length;i++){
  var script=document.createElement("script");
  script.type="text/javascript";
  script.src=s[i];
  document.getElementsByTagName("head")[0].appendChild(script)
};
share|improve this answer
2  
This doesn't seem like a complete answer. – Lee Taylor Mar 10 '13 at 14:11
1  
Where is this from? What's the deal with "checkRobert"? – Dan Dascalescu Jul 8 '15 at 2:21

I also wrote a JavaScript dependency manager for Java web applications: JS-Class-Loader.

share|improve this answer

There are a lot of potential answers for this questions. My answer is obviously based on a number of them. Thank you for all the help. 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.)

ex:

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 its 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 anymore.

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 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, 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 it's 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 js 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"
});
share|improve this answer

I basically do like this, create new element and attach that to head.

var x = document.createElement('script');
x.src = 'http://example.com/test.js';
document.getElementsByTagName("head")[0].appendChild(x);

in jquery:

// jQuery
$.getScript('/path/to/imported/script.js', function()
{
    // script is now loaded and executed.
    // put your dependent JS here.
});
share|improve this answer

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 https://www.html5rocks.com/en/tutorials/webcomponents/imports/ for more details.

Unfortunately this only works in Chrome

share|improve this answer

I have the requirement to load async an array of javascripts and at the final make a callback. Basically my best approach is the following:

// Load a JavaScript from other Javascript
function loadScript(urlPack, callback) {
    var url = urlPack.shift();
    var subCallback;

    if (urlPack.length == 0) subCallback = callback;
    else subCallback = function () {
        console.log("Log script: " + new Date().getTime());
        loadScript(urlPack, callback);
    }

    // Adding the script tag to the head as suggested before
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = subCallback;
    script.onload = subCallback;

    // Fire the loading
    head.appendChild(script);
}

Example:

loadScript(
[
    "js/DataTable/jquery.dataTables.js",
    "js/DataTable/dataTables.bootstrap.js",
    "js/DataTable/dataTables.buttons.min.js",
    "js/DataTable/dataTables.colReorder.min.js",
    "js/DataTable/dataTables.fixedHeader.min.js",
    "js/DataTable/buttons.bootstrap.min.js",
    "js/DataTable/buttons.colVis.min.js",
    "js/DataTable/buttons.html5.min.js"
], function() { gpLoad(params); });

The second script don't will load until the first is completely loaded, and so...

Results:

Result

share|improve this answer
    
script.onreadystatechange will never fire. It's specific to XMLHttpRequest. If it would fire, for example because you were actually loading the script using XMLHttpRequest, it would cause your callback to be called too often. So you should remove that line. – Julian Aug 7 at 21:27

You can't import, but you can reference.

PhpShtorm IDE. To reference, in one .js file to another .js, just add this to the top of the file:

<reference path="../js/file.js" />

Of course, you should use you own PATH to JS file.

I don`t now will it work at others IDE. Probably yes, just try. It should work in Visual Studio too.

share|improve this answer

Here is maybe another way! In Node.js you do that just like the following! http://requirejs.org/docs/node.html

sub.js

module.exports = {
  log: function(string) {
    if(console) console.log(string);
  }
  mylog: function(){
    console.log('just for log test!');
  }
}

main.js

var mylog =require('./sub');

mylog.log('Hurray, it works! :)');
mylog.mylog();
share|improve this answer
    
just using for node+react test! – xgqfrms Oct 4 at 13:55
var xxx = require("../lib/your-library.js")

or

import xxx from "../lib/your-library.js" //get default export
import {specificPart} from '../lib/your-library.js' //get named export
import * as _name from '../lib/your-library.js'  //get full export to alias _name
share|improve this answer
    
Is it plain javascript? – Guedes Oct 20 at 11:52
    
yes it's modern javascript (es6) and it's taking over real fast – Thielicious Oct 31 at 14:16
function include(js)
{
    document.writeln("<script src=" + js + "><" + "/script>");
}
share|improve this answer
    
Why was this downvoted? I'm no JS expert, but wouldn't this work? – Gottlieb Notschnabel Oct 20 '13 at 11:35
5  
Because if the page is already done loading when it is executing, or if it is executed because of a user action, then it will clear the page first. – SevenBits Oct 20 '13 at 11:56
    
@SevenBits is correct and this answer is buggy, see this page: developer.mozilla.org/en-US/docs/Web/API/Document/write – Flimm Jun 18 '15 at 14:52
    
@Flimm you could have linked to the page on writeln instead, but it's basically the same. – gcampbell Jun 22 at 19:21

protected by NullPoiиteя Jun 10 '13 at 5:07

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.