How do I include a JavaScript file in another JavaScript file?

2009-06-04 javascript file import include

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

Answers

It is possible to dynamically generate a JavaScript tag and append it to HTML document from inside other JavaScript code. This will load targeted JavaScript file.

function includeJs(jsFilePath) {
    var js = document.createElement("script");

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

    document.body.appendChild(js);
}

includeJs("/path/to/some/file.js");

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

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 tools like Webpack and Rollup and/or transpilation tools like Babel can be used.

ES6 Modules

ECMAScript (ES6) modules have been supported in Node.js since v8.5, with the --experimental-modules flag, and since at least Node.js v13.8.0 without the flag. To enable "ESM" (vs. Node.js's previous CommonJS-style module system ["CJS"]) you either use "type": "module" in package.json or give the files the extension .mjs. (Similarly, modules written with Node.js's previous CJS module can be named .cjs if your default is ESM.)

Using package.json:

{
    "type": "module"
}

Then module.js:

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

Then main.js:

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

Using .mjs, you'd have module.mjs:

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

Then main.mjs:

import { hello } from './module.mjs';
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. There is no need to use Node.js' .mjs extension; browsers completely ignore file extensions on modules/scripts.

<script type="module">
  import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
  hello('world');
</script>
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}

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 older CJS module style, 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.

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.

You can also assemble your scripts using PHP:

File main.js.php:

<?php
    header('Content-type:text/javascript; charset=utf-8');
    include_once("foo.js.php");
    include_once("bar.js.php");
?>

// Main JavaScript code goes here

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

Another way, that in my opinion is much cleaner, is to make a synchronous Ajax request instead of using a <script> tag. Which is also how Node.js handles includes.

Here's an example using jQuery:

function require(script) {
    $.ajax({
        url: script,
        dataType: "script",
        async: false,           // <-- This is the key
        success: function () {
            // all good...
        },
        error: function () {
            throw new Error("Could not load script " + script);
        }
    });
}

You can then use it in your code as you'd usually use an include:

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

And be able to call a function from the required script in the next line:

subscript.doSomethingCool(); 

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 whatever you want). 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 <script> 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('<script src="js/plugins/' + this + '.js"></script>');
});
  1. Manually call just the one file in your head:
    <script src="js/plugins/plugins.js"></script>

BUT:

Even though all of the plugins get dropped into the head tag the way they ought to, they don't always get run by the browser when you click into the page or refresh.

I've 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);
}

In a past project I had quite a bit of success using ajile to do imports of reusable JavaScript files. I always wished there was a feature for this built into JavaScript itself.

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:

If anyone is looking for something more advanced, try out RequireJS. You'll get added benefits such as dependency management, better concurrency, and avoid duplication (that is, retrieving a script more than once).

You can write your JavaScript files in "modules" and then reference them as dependencies in other scripts. Or you can use RequireJS as a simple "go get this script" solution.

Example:

Define dependencies as modules:

some-dependency.js

define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {

     //Your actual script goes here.   
     //The dependent scripts will be fetched if necessary.

     return libraryObject;  //For example, jQuery object
});

implementation.js is your "main" JavaScript file that depends on some-dependency.js

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

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

Excerpt from the GitHub README:

RequireJS loads plain JavaScript files as well as more defined modules. It is optimized for in-browser use, including in a Web Worker, but it can be used in other JavaScript environments, like Rhino and Node. It implements the Asynchronous Module API.

RequireJS uses plain script tags to load modules/files, so it should allow for easy debugging. It can be used simply to load existing JavaScript files, so you can add it to your existing project without having to re-write your JavaScript files.

...

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:

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

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

document.body.appendChild(js);

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

$.holdReady(true);
$.getScript("myplugin.js", function() {
    $.holdReady(false);
});

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>

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

This should do:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);

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

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

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

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

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

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

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.

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.

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

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

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

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.

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

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.

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>

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

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

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.

Here is maybe another way!

In Node.js you can do that just like the following code shows!

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

refs

http://requirejs.org/docs/node.html

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

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.

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'
 ]);

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.

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.

In modern language with the check if script has already been loaded it would be:

function loadJs(url){
  return new Promise( (resolve, reject) => {
    if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
    const script = document.createElement("script")
    script.src = url
    script.onload = resolve
    script.onerror = reject
    document.head.appendChild(script)
  });
}

Usage (async/await):

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

or

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

Usage (Promise):

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

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.

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

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

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

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')+'');

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

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

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

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.

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

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

ES6 Modules

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.

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.

I did not see an answer whereby you create an object of all functions and variables in a file and then make that object an argument to refer to it in another file.
E.g. you have files called 'jsMod.js', 'jsView' and 'jsContr.js'


    //jsMod.js file
    JSMODOBJ = {};
    JSMODOBJ.valueAddition = function(/* element value 1 */ val1, 
                                          /* element value 2 */ val2) {
        return val1 + val2;
    }


    //jsView.js file
    JSVIEWOBJ = {};
    JSVIEWOBJ.elementColour = function(/* element id to change colour */ id, 
                                          /* css colour classname */ col) {
        document.getElementById(id).className = col;
    }


    //jsContr.js file
    JSCONTROBJ = {};
    var jsMod = JSMODOBJ;
    var jsView = JSVIEWOBJ;

    JSCONTROBJ.changeColourByValue = function (val1, val2, id, clss) {
        if (jsMod.valueAddition(val1,val2) !== 0) {
            jsView.elementColour(id, clss);
        }
    }

Then you can set the js files dynamically by echoeing the scripts into your html or php file:

<?php
    echo "<script src = './js/dleafView.js'></script>
        <script src = './js/dleafModule.js'></script>
        <script src = './js/dleafContr.js'></script>";
?>

Then just call the control function within a <script type="text/javascript"></script> tag. Of course this will take alot of time in the beginning to set up, but save you time in the long run.
I use this in a slightly different way, but this way also works.

You can also use gulp, gulp-concat, gulp-typescript with /// <reference path= includes:

packages.json

{
  "scripts": {
    "gulp": "gulp main"
  },
  "dependencies": {
    "@types/gulp": "^4.0.6",
    "@types/gulp-concat",
    "@types/gulp-typescript",
    "gulp": "^4.0.2",
    "gulp-concat": "^2.6.1",
    "gulp-resolve-dependencies": "^3.0.1",
    "gulp-typescript": "^6.0.0-alpha.1",
    "typescript": "^3.7.3"
  }
}

src/someimport.ts

class SomeClass {
    delay: number;
}

src/main.ts

/// <reference path="./someimport.ts" />

someclass = new SomeClass();
someclass.delay = 1;

This main gulp task (on gulpfile.js) targets only the src/main.js file, resolving all its /// <reference path=... include references. These includes are know as Triple-Slash Directives and they are used only for transpilers tools to combine files. In our case, they are used explicitly by .pipe(resolveDependencies({ and by typescript itself when checking the file for missing types, variables, etc.

  1. https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html
  2. When do I need a triple slash reference?

Refer to https://github.com/ivogabe/gulp-typescript#api-overview if you would like to customize the var tsProject = ts.createProject call and not use a tsconfig.json file or override its parameters.

gulpfile.js

var gulp = require("gulp");
var concat = require('gulp-concat');
var resolveDependencies = require('gulp-resolve-dependencies');

var ts = require("gulp-typescript");
var tsProject = ts.createProject("tsconfig.json");

gulp.task("main", function() {
  return gulp
    .src(["src/main.ts"])
    .pipe(resolveDependencies({
      pattern: /^\s*\/\/\/\s*<\s*reference\s*path\s*=\s*(?:"|')([^'"\n]+)/gm
    }))
    .on('error', function(err) {
        console.log(err.message);
    })
    .pipe(tsProject())
    .pipe(concat('main.js'))
    .pipe(gulp.dest("build/"));
});

If you wold like to target all your type script project files instead of only src/main.ts, you can replace this:

  return gulp
    .src(["src/main.ts"])
    .pipe(resolveDependencies({
    ...
// -->
  return tsProject
    .src()
    .pipe(resolveDependencies({
    ...

If you do not want to use typescript, you can use this simplified gulpfile.js and remove all typescript includes from package.json:

gulpfile.js

var gulp = require("gulp");
var concat = require('gulp-concat');
var resolveDependencies = require('gulp-resolve-dependencies');

gulp.task("main", function() {
  return gulp
    .src(["src/main.js"])
    .pipe(resolveDependencies({
      pattern: /^\s*\/\/\/\s*<\s*reference\s*path\s*=\s*(?:"|')([^'"\n]+)/gm
    }))
    .on('error', function(err) {
        console.log(err.message);
    })
    .pipe(concat('main.js'))
    .pipe(gulp.dest("build/"));
});

packages.json

{
  "scripts": {
    "gulp": "gulp main"
  },
  "dependencies": {
    "gulp": "^4.0.2",
    "gulp-concat": "^2.6.1",
    "gulp-resolve-dependencies": "^3.0.1"
  }
}

Then, after running the command npm run gulp, the file build/main.js is created with the following as its contents:

build/main.js

class SomeClass {
}
/// <reference path="./someimport.ts" />
someclass = new SomeClass();
someclass.delay = 1;

Which allows me to include it in the browser with the script tag, after serving the build directory files:

<html>
    <head>
        <script src="main.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            console.log(someclass.delay);
        </script>
    </body>
</html>

Related questions:

  1. https://www.typescriptlang.org/docs/handbook/gulp.html
  2. Can I use the typescript without requireJS?
  3. Gulp simple concatenation of main file that requires another JS file
  4. Client on node: Uncaught ReferenceError: require is not defined
  5. How can typescript browser node modules be compiled with gulp?
  6. Concatenate files using babel
  7. How to require CommonJS modules in the browser?
  8. Is there an alternative to Browserify?

You shall use this:

<script src="your_file.js"></script>

Easy!

Related