Join the Stack Overflow Community
Stack Overflow is a community of 6.7 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
33  
30  
@Daniel, I do not want to use an AJAX call. – Alec Smart Jun 4 '09 at 12:02
3  
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
    
@falsarella how would that help? – Claudiu Creanga Feb 18 '16 at 19:42
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 '16 at 12:29

44 Answers 44

up vote 2766 down vote accepted

JavaScript has no import, include, or require. (Update 2015: it does now with ES6 modules) There are other ways for JavaScript to include external JavaScript contents, though.

Ajax Loading

Load an additional script with an Ajax call and then use eval. 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 and hacks.

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

Add a script tag with the script URL in 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.

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.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 = 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 what ever 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

Another solution is to combine the two files into a single file. This can be used with minification to produce a single, minimally sized JavaScript file to include as normal.

share|improve this answer
84  
not all javascript files are executed in a browser. – Michael Paulukonis Jul 14 '10 at 17:42
86  
Nope but somebody that uses something as advanced as Rhino or else wouldn't ask this question. – e-satis Jul 15 '10 at 3:53
137  
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. – Toad Sep 7 '12 at 8:36
11  
Shouldn't "document.createElement("my_lovely_script.js");" in the example be "document.createElement("script")" ? – Russell Silva Dec 14 '12 at 23:28
7  
How does eval open the door to hacks if it's your code that you're executing? – Vince Panuccio Jan 6 '13 at 9:39

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

share|improve this answer

There are a lot of potential answers for this question. 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).

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"
});
share|improve this answer
    
This is exactly what the currently accepted answer states: just not enough. – IamGuest 2 days ago

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;
share|improve this answer
    
... but is not supported by any browser to date, according to the compatibility table on the page you linked to. – Zero3 Apr 22 '15 at 20:34
4  
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 – Jeremy Harris Jun 12 '15 at 20:35
    
@Zero3 Apparently the new IE (Edge) is the only one – Julian Avar Jun 25 '16 at 23:36
    
is there a way to do this without ES6? Browser compatibility and those who don't have ES6 demands it. – IamGuest 2 days ago

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.

share|improve this answer
1  
This is exactly what I needed, thanks for this simple demonstration. – Paul Aug 30 '16 at 9:23
    
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. – IamGuest 2 days ago
    
Agreed. What is your use case? – Manohar Reddy Poreddy yesterday

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>
share|improve this answer

I basically do it like the following, creating a 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 JavaScript code here.
});
share|improve this answer

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

// Load a JavaScript file from other JavaScript file
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 will not load until the first is completely loaded, and so...

Results:

Result

share|improve this answer
1  
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 '16 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 your own PATH to the JavaScript file.

I don't know if it will work in other IDEs. Probably yes, just try. It should work in Visual Studio too.

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
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? – Washington Guedes Oct 20 '16 at 11:52
    
yes it's modern javascript (es6) and it's taking over real fast – Thielicious Oct 31 '16 at 14:16

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 '16 at 13:55

This is perhaps the biggest weakness of JavaScript in my opinion. It's caused me no end of problems over the years with dependency tracing. Anyhow, it does appear that the only practical solution is to use script includes in the HTML file and thus horribly making your JavaScript code dependent upon the user including the source you need and making reuse unfriendly.

Sorry if this comes across as a lecture ;) It's a (bad) habit of mine, but I want to make this point.

The problem comes back to the same as everything else with the web, the history of JavaScript. It really wasn't designed to be used in the widespread manner it's used in today. Netscape made a language that would allow you to control a few things, but they didn't envisage its widespread use for so many things as it is put to now and for one reason or another it's expanded from there, without addressing some of the fundamental weaknesses of the original strategy.

It's not alone of course. HTML wasn't designed for the modern webpage; it was designed to be a way of expressing the logic of a document, so that readers (browsers in the modern world) could display this in an applicable form that was within the capabilities of the system, and it took years for a solution (other than the hacks of MS and Netscape) to come along. CSS solves this problem, but it was a long time coming and even longer to get people to use it rather than the established BAD techniques. It happened though, praise be.

Hopefully JavaScript (especially now it's part of the standard) will develop to take on board the concept of proper modularity (as well as some other things) as every other (extant) programming language in the world does and this stupidity will go away. Until then you just have to not like it and lump it, I'm afraid.

share|improve this answer
2  
"it's part of the standard" :D Good comments though. – Almo Jun 5 '12 at 14:45
2  
ecmascript 6 seems like a real programming language. until then, we need to bear with it. – allenhwkim Feb 23 '13 at 18:24
    
See this answer below: stackoverflow.com/a/29688912/266535 – styfle Sep 6 '16 at 19:13

Here's the generalized version of how Facebook does it for their ubiquitous Like button:

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

If it works for Facebook, it will work for you.

The reason why we look for the first script element instead of head or body is because some browsers don't create one if missing, but we're guaranteed to have a script element - this one. Read more at http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/.

share|improve this answer
2  
Damn nice! Some of the methods here work too, but under a dynamic setting this works the best. – tfont Jul 13 '16 at 15:51

Here is a synchronous version without 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);
}

Note that to get this working cross-domain, the server will need to set allow-origin header in its response.

share|improve this answer
    
Excellent function! Loads the JavaScript before any additional JS is written after the body. Very important when loading multiple scripts. – tfont Feb 28 '14 at 21:50
2  
@heinob : What can I do to get it working for cross-domain? (loading script from http://web.archive.org/web/20140905044059/http://www.howtocr‌​eate.co.uk/operaStuf‌​f/userjs/aagmfunctio‌​ns.js) – user2284570 Sep 14 '14 at 2:20
    
@user2284570: If you are the owner of the foreign domain: set `allow-origin' header in server answer. If you are'nt the owner: nothing. Sorry! That is cross-origin-policy. – heinob Sep 14 '14 at 5:42
    
@heinob : No because, this is for a user script! (need to load this script : http://web.archive.org/web/20140905044059/http://www.howtocr‌​eate.co.uk/operaStu‌‌​​ff/userjs/aagmfunct‌​ions.js) – user2284570 Sep 14 '14 at 9:53
1  
@user2284570: I understand your comment in that way, that you are not the owner of the domain from which you want to load the script. In that case you only can load a script via an inserted <script> tag, not via XMLHttpRequest. – heinob Sep 14 '14 at 16:10

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.

share|improve this answer
6  
jrburke wrote this as RequireJS. Github: requirejs.org/docs/requirements.html – Mike Caron Sep 14 '11 at 17:14
    
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? – trusktr Mar 31 '14 at 3:35

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 http://www.kipras.com/dev/import_js_test/.

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

share|improve this answer
    
I am trying this method, but is not working for me, the element just does not appear in head tag. – juanpastas Mar 12 '13 at 15:24
9  
@juanpastas - use jQuery.getScript, that way you don't have to worry about writing the plugin... – MattDMo Jun 1 '13 at 17:44
    
Does this technique really block until the imported script is both loaded and executed? – Flimm Jun 18 '15 at 14:28
1  
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. – Flimm Jun 18 '15 at 15:36

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 "under the hood," 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.

share|improve this answer
    
This would be awesome if it were a node module. – b01 Apr 19 '15 at 19:07
    
@b01 Sounds like a challenge ;) If only I had the time... perhaps someone else does? – Isaac Gregson Apr 6 '16 at 10:05

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

Maybe you can use this function that I found on this page How do I include a JavaScript file in a JavaScript file?:

function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';

    head.appendChild(script)
}
share|improve this answer
3  
Should be useful to add script.onload = callback; – Vitim.us Aug 23 '13 at 15:37
    
@SvitlanaMaksymchuk so, if I don't use var, the variable will be global ? – Francisco Corrales Morales Mar 18 '14 at 15:22
    
@FranciscoCorrales yes. – Christopher Chiche May 21 '14 at 10:03
    
It ends up in global with or without the var :) – Wexoni Jan 16 '15 at 8:27
    
This fails if the page has no head. – Dan Dascalescu Jul 8 '15 at 2:50

This should do:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
share|improve this answer
5  
the eval is what's wrong with it. From Crockford, "eval is evil. The eval function is the most misused feature of JavaScript. Avoid it. eval has aliases. Do not use the Function constructor. Do not pass strings to setTimeout or setInterval." If you haven't read his "JavaScript: The Good Parts" then go out and do it right now. You will not regret it. – MattDMo Jun 1 '13 at 17:56
9  
@MattDMo "Someone said it was bad" isn't really an argument. – Casey Sep 3 '14 at 19:05
4  
@emodendroket I take it you're not aware of who Douglas Crockford is. – MattDMo Sep 3 '14 at 19:24
8  
@MattDMo I'm fully aware of who he is, but he's a human being, not a god. – Casey Sep 3 '14 at 19:52
2  
@tggagne : What can I do to get it working for cross-domain? (loading script from http://web.archive.org/web/20140905044059/http://www.howtocr‌​eate.co.uk/operaStuf‌​f/userjs/aagmfunctio‌​ns.js) – user2284570 Sep 14 '14 at 2:18

I wrote a simple module that automates the job of importing/including module scripts in JavaScript. For detailed explanation of the code, refer to the blog post JavaScript require / import / include modules.

// ----- 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);
};
share|improve this answer

There is also Head.js. It is very easy to deal with:

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

As you see, it's easier than Require.js and as convenient as jQuery's $.getScript method. It also has some advanced features, like conditional loading, feature detection and much more.

share|improve this answer

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

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

share|improve this answer

This script will add a JavaScript file to the top of any other <script> tag:

(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);
})();
share|improve this answer

Most of solutions shown here imply dynamical loading. I was searching instead for a compiler which assemble all the depended files into a single output file. The same as Less/Sass preprocessors deal with the CSS @import at-rule. Since I didn't find anything decent of this sort, I wrote a simple tool solving the issue.

So here is the compiler, https://github.com/dsheiko/jsic, which replaces $import("file-path") with the requested file content securely. Here is the corresponding Grunt plugin: https://github.com/dsheiko/grunt-jsic.

On the jQuery master branch, they simply concatenate atomic source files into a single one starting with intro.js and ending with outtro.js. That doesn't suits me as it provides no flexibility on the source code design. Check out how it works with jsic:

src/main.js

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

src/Form/Input/Tel.js

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

Now we can run the compiler:

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

And get the combined file

build/main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
share|improve this answer
2  
Since this post I came up with much better solution - CommonJS module compiler - github.com/dsheiko/cjsc So you can simply write CommonJs or NodeJs modules and access each other yet keeping them in isolated scopes. The benefits: No need of multiple HTTP requests that affect performance You don't need manually wrapping you module code - it is responsibility of the compiler (so better source code readability) You don't need any external libraries It is compatible with UMD- and NodeJs modules (e.g. you can address jQuery, Backbone as modules without touching their code) – Dmitry Sheiko Mar 7 '14 at 16:07

I did:

var require = function (src, cb) {
    cb = cb || function () {};

    var newScriptTag = document.createElement('script'),
        firstScriptTag = document.getElementsByTagName('script')[0];
    newScriptTag.src = src;
    newScriptTag.async = true;
    console.log(newScriptTag)
    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 tried that Ajax thing, but it doesn't really work.

share|improve this answer

Now, I may be totally misguided, but here's what I've recently started doing... Start and end your JavaScript files with a carriage return, place in the PHP script, followed by one more carriage return. The JavaScript comment "//" is ignored by PHP so the inclusion happens anyway. The purpose for the carriage returns is so that the first line of your included JavaScript isn't commented out.

Technically, you don't need the comment, but it posts errors in Dreamweaver that annoy me. If you're scripting in an IDE that doesn't post errors, you shouldn't need the comment or the carriage returns.

\n
//<?php require_once("path/to/javascript/dependency.js"); ?>

function myFunction(){
    // stuff
}
\n
share|improve this answer

Better use the jQuery way. To delay the ready event, first call $.holdReady(true). Example (source):

$.holdReady(true);
$.getScript("myplugin.js", function() {
    $.holdReady(false);
});
share|improve this answer
    
The jQuery docs say that the callback passed to getScript will run "once the script has been loaded but not necessarily executed". – Flimm Jun 18 '15 at 14:47

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.