javascript from - How do I include a JavaScript file in another JavaScript file?




15 Answers

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.

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 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.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 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 backwards compatibility for older browsers, combine files, minify, perform code splitting etc.

html node

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




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




There is a good news for you. Very soon you will be able to load JavaScript code easily. It will become a standard way of importing modules of JavaScript code and will be part of core JavaScript itself.

You simply have to write import cond from 'cond.js'; to load a macro named cond from a file cond.js.

So you don't have to rely upon any JavaScript framework nor do you have to explicitly make Ajax calls.

Refer to:




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;



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.




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




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



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>



Or rather than including at run time, use a script to concatenate prior to upload.

I use Sprockets (I don't know if there are others). You build your JavaScript code in separate files and include comments that are processed by the Sprockets engine as includes. For development you can include files sequentially, then for production to merge them...

See also:




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.




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



var js = document.createElement("script");

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

document.body.appendChild(js);



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



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.




I have created a function that will allow you to use similar verbiage to C#/Java to include a JavaScript file. I've tested it a little bit even from inside of another JavaScript file and it seems to work. It does require jQuery though for a bit of "magic" at the end.

I put this code in a file at the root of my script directory (I named it global.js, but you can use whatever you want. Unless I'm mistaken this and jQuery should be the only required scripts on a given page. Keep in mind this is largely untested beyond some basic usage, so there may or may not be any issues with the way I've done it; use at your own risk yadda yadda I am not responsible if you screw anything up yadda yadda:

/**
* @fileoverview This file stores global functions that are required by other libraries.
*/

if (typeof(jQuery) === 'undefined') {
    throw 'jQuery is required.';
}

/** Defines the base script directory that all .js files are assumed to be organized under. */
var BASE_DIR = 'js/';

/**
* Loads the specified file, outputting it to the <head> HTMLElement.
*
* This method mimics the use of using in C# or import in Java, allowing
* JavaScript files to "load" other JavaScript files that they depend on
* using a familiar syntax.
*
* This method assumes all scripts are under a directory at the root and will
* append the .js file extension automatically.
*
* @param {string} file A file path to load using C#/Java "dot" syntax.
*
* Example Usage:
* imports('core.utils.extensions');
* This will output: <script type="text/javascript" src="/js/core/utils/extensions.js"></script>
*/
function imports(file) {
    var fileName = file.substr(file.lastIndexOf('.') + 1, file.length);

    // Convert PascalCase name to underscore_separated_name
    var regex = new RegExp(/([A-Z])/g);
    if (regex.test(fileName)) {
        var separated = fileName.replace(regex, ",$1").replace(',', '');
        fileName = separated.replace(/[,]/g, '_');
    }

    // Remove the original JavaScript file name to replace with underscore version
    file = file.substr(0, file.lastIndexOf('.'));

    // Convert the dot syntax to directory syntax to actually load the file
    if (file.indexOf('.') > 0) {
        file = file.replace(/[.]/g, '/');
    }

    var src = BASE_DIR + file + '/' + fileName.toLowerCase() + '.js';
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;

    $('head').find('script:last').append(script);
}



Related

javascript file import include