6246

How do I include a JavaScript file inside another JavaScript file, similar to @import in CSS?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Alec Smart
  • 94,115
  • 39
  • 120
  • 184
  • 3
    [MDN docs about JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), with [corresponding examples on github](https://github.com/mdn/js-examples/tree/master/modules) – djvg Nov 20 '21 at 19:08
  • My answer here https://stackoverflow.com/a/72335692/9868445 has been downvoted anonymously and without any comments explaining the reason, but I still absolutely recommend having a look at it. – aderchox May 30 '22 at 07:14
  • Yeah. People around here have this tendency to downvote questions they don't like or understand. – luenib Jul 05 '23 at 14:16

71 Answers71

5388

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 the extension could be just `.js`
  hello('world');
</script>
// hello.mjs -- or the extension could be just `.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.

Keatinge
  • 4,330
  • 6
  • 25
  • 44
Bite code
  • 578,959
  • 113
  • 301
  • 329
  • I have loaded div dynamically by clicking menu without page loading by using URL hash. My problem is when i click same page 2/3 times js loading 2/3 times. thats why every event occurs multiple time. I want to check js file already loaded into footer/head before appending in that code: var js = document.createElement("script"); js.type = "text/javascript"; js.src = jsFilePath; document.body.appendChild(js); – Alien Aug 15 '20 at 17:33
  • You can also use something like Gulp (https://gulpjs.com/) to preprocess them with the output being a single file that's called. For example: a) concatenate several JavaScript files together into one, b) use Babel to make it backwards compatible, c) minify/uglify to remove comments, whitespace, etc. Then, you've not only organized those files but also optimized them as well by initiating a pipeline with the potential of doing the same for other file formats (such as css and images.) – Steven Ventimiglia Feb 22 '21 at 01:48
  • Using the "ECMAScript" method, I got `Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.` Changing `hello.mjs` to `hello.js` made it work. – Dan Aug 25 '23 at 18:36
629

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.

...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Strickler
  • 25,151
  • 4
  • 52
  • 68
237

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></script>").attr("src", url));

/* Note that following line of code is incorrect because it doesn't escape the
 * HTML attribute src correctly and will fail if `url` contains special characters:
 * $("head").append('<script src="' + url + '"></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></script').attr('src', 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).

Flimm
  • 136,138
  • 45
  • 251
  • 267
Kipras
  • 2,664
  • 1
  • 16
  • 10
176

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(); 
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ariel
  • 4,502
  • 2
  • 21
  • 23
129

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");
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Svitlana Maksymchuk
  • 4,330
  • 2
  • 16
  • 11
  • Great answer. For 2015+ browsers, is it still necessary to override `js.type`? (Even going back to Chrome 66, the browser is not having any issue understanding the MIME type supplied by the server). – personal_cloud Dec 23 '22 at 19:00
112

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:

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Imdad
  • 5,942
  • 4
  • 33
  • 53
  • 2
    Seven years later, this answer doesn't work: "SyntaxError: import declarations may only appear at top level of a module". – David Spector May 27 '21 at 15:52
  • Share your code what you are trying to do. – Imdad May 31 '21 at 12:06
  • Okay, here is code that works nicely: function Include(jsFilePath) { var js = d.createElement("script"); js.type = "text/javascript"; js.src = jsFilePath; d.body.appendChild(js); } // Include – David Spector May 31 '21 at 17:04
91

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;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
draupnie
  • 1,120
  • 8
  • 11
69

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)
}
Ajeet Lakhani
  • 3,768
  • 2
  • 22
  • 37
61

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.

Flimm
  • 136,138
  • 45
  • 251
  • 267
heinob
  • 19,127
  • 5
  • 41
  • 61
53

If you want it 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");
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Venu immadi
  • 1,585
  • 11
  • 20
53

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.

Talha Awan
  • 4,573
  • 4
  • 25
  • 40
nornagon
  • 15,393
  • 18
  • 71
  • 85
52

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

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
36

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Calmarius
  • 18,570
  • 18
  • 110
  • 157
33

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(){}
    }
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dmitry Sheiko
  • 2,130
  • 1
  • 25
  • 28
30

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>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adem İlhan
  • 1,460
  • 3
  • 16
  • 26
  • This is not a good idea when you have a lot of separate files; the more files you create, the more requests will to be sent from the client, which makes the loading longer and also might affect the page SEO. – YektaDev Apr 12 '21 at 08:00
25

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:

Imdad
  • 5,942
  • 4
  • 33
  • 53
JMawer
  • 259
  • 3
  • 2
25

This should do:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tggagne
  • 2,864
  • 1
  • 21
  • 15
23

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
21

ES6 Modules

Yes, use type="module" in a script tag (support):

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

And in a script.js file include another file like this:

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

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

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

A working example is here.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
19

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 assume the application does this via one of above-mentioned methods.

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.

Note: Mixture was discontinued on 2016/07/26 (after being open sourced on 2015/04/12).

Isaac Gregson
  • 1,999
  • 1
  • 21
  • 31
  • It is better to avoid "Update" (meta information that belongs in the revision history to this post). Instead apply it to the content (not this post), e.g. *"Mixture was open sourced on 2015-04-12, and it was discontinued on 2016-07-26."* – Peter Mortensen Oct 03 '20 at 20:50
19

In a 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 = "${url}" ]`) !== null ){
        console.warn( `script already loaded: ${url}` );
        resolve();
    }
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    script.onerror = function( reason ){
        // This can be useful for your error-handling code
        reason.message = `error trying to load script ${url}`;
        reject( reason );
    };
    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 => {} );
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dmitry Sheiko
  • 2,130
  • 1
  • 25
  • 28
  • This is very good if you want to avoid having to get involved in modules, and don't want to use a callback function, but do want to use `async` / `await`. – mike rodent Jul 19 '20 at 07:25
  • `url` needs to be properly escaped here: `\`head > script[ src = "${url}" ]\`` – Flimm May 12 '21 at 13:00
18

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

Community
  • 1
  • 1
Turnerj
  • 4,258
  • 5
  • 35
  • 52
18

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.

KthProg
  • 2,050
  • 1
  • 24
  • 32
  • This is a good answer. It may have been missed because it does not directly answer the question, but it's also important to understand that 'you usually don't need to do that'. Especially since the other solutions are so messy. – Nathan Kovner Jul 27 '20 at 18:44
  • But this only works in a web browser? What about offline unit testing (say, under Node.js)? – Peter Mortensen Oct 03 '20 at 20:31
  • This answer is similar to a detailed 2015 answer here - https://stackoverflow.com/a/31552759/984471 – Manohar Reddy Poreddy Sep 24 '21 at 02:45
17
var js = document.createElement("script");

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

document.body.appendChild(js);
Spudley
  • 166,037
  • 39
  • 233
  • 307
Sam4Code
  • 541
  • 5
  • 9
14

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

Alexis Dumas
  • 1,299
  • 11
  • 30
13

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);
};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
stamat
  • 1,832
  • 21
  • 26
13

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);
})();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vicky Gonsalves
  • 11,593
  • 2
  • 37
  • 58
13

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

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tfont
  • 10,891
  • 7
  • 56
  • 52
12

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 you need to 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 an 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 stuff, 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 a script together using the <script> tag...

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

There are also the async and defer attributes which I should mention 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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alireza
  • 100,211
  • 27
  • 269
  • 172
12

There are several ways to implement modules in JavaScript. Here are the two 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 a couple of 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 overall 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 Node.js)

This moduling system is used in Node.js. 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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
12

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.

rgb_life
  • 353
  • 3
  • 10
  • Note that if pluginNames contains special characters, this won't work, and might even lead to a security vulnerability. You need to use proper escaping here: `$('head').append('');` – Flimm May 12 '21 at 13:01
10

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ale
  • 1,998
  • 19
  • 31
10

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"
});
Community
  • 1
  • 1
10

For Node.js 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') + '');
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
chickens
  • 19,976
  • 6
  • 58
  • 55
9

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.

Yairopro
  • 9,084
  • 6
  • 44
  • 51
9

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);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wayne Molina
  • 19,158
  • 26
  • 98
  • 163
8

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

$.holdReady(true);
$.getScript("myplugin.js", function() {
    $.holdReady(false);
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
weageoo
  • 97
  • 1
  • 1
8

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.
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
7

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marcin
  • 5,469
  • 15
  • 55
  • 69
6

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MiBol
  • 1,985
  • 10
  • 37
  • 64
6

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

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

    mylog.log('Hurray, it works! :)');
    mylog.mylog();

refs

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

xgqfrms
  • 10,077
  • 1
  • 69
  • 68
6

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

Here are some quotes from its documentation:

Load one or more modules & components with multiple files:

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

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

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

You can load external libs (not angular):

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

You can also load css and template files:

 $ocLazyLoad.load([
     'bower_components/bootstrap/dist/js/bootstrap.js',
     'bower_components/bootstrap/dist/css/bootstrap.css',
     'partials/template1.html'
 ]);
gm2008
  • 4,245
  • 1
  • 36
  • 38
6

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

Name files with .mjs extension instead of .js

Create files

touch main.mjs lib.mjs

main.js

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

lib.mjs

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

Run

node --experimental-modules main.js
jasonleonhard
  • 12,047
  • 89
  • 66
6

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.

jpierson
  • 16,435
  • 14
  • 105
  • 149
5

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>
Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22
emolaus
  • 599
  • 9
  • 13
5

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Duncan
  • 1,530
  • 15
  • 20
5
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)
};
The_asMan
  • 6,364
  • 4
  • 23
  • 34
Robert A
  • 337
  • 4
  • 3
5

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Akshay Vijay Jain
  • 13,461
  • 8
  • 60
  • 73
5

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
MishkuMoss
  • 118
  • 2
  • 6
3

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Evgeniy Miroshnichenko
  • 1,788
  • 2
  • 19
  • 30
3

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.

Prags
  • 2,457
  • 2
  • 21
  • 38
gabriel211
  • 79
  • 4
  • Unfortunately that HTML Imports link says that the feature was deprecated and removed from Chrome - https://www.chromestatus.com/feature/5144752345317376 – PhysicalEd Oct 27 '20 at 23:41
3

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.

Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22
AlienKevin
  • 2,691
  • 2
  • 17
  • 19
2

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

The cache: true option has been added to the Ajax method.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adam111p
  • 3,469
  • 1
  • 23
  • 18
2

If you find there are two or more scripts occupying the same function when they are called, and we cannot be include them at the same time, we need to do it dynamically by user selection.

Including another file in jQuery using $.getScript works since the script will not be cached by default. So we are safe to call other 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>

JavaScript

$(".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 ) {
    // Execute here
  });
}

// script2
function script2() {
  $.getScript($.url2, function( data, textStatus, jqxhr ) {
    // Execute here
  });
}
Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22
eQ19
  • 9,880
  • 3
  • 65
  • 77
2

A little extension to the library from Dan Dascalescu's answer taken from the 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';
}));
Makyen
  • 31,849
  • 12
  • 86
  • 121
Kamil Dąbrowski
  • 984
  • 11
  • 17
2

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 JavaScript code 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Torxed
  • 22,866
  • 14
  • 82
  • 131
1
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
Mesut Yiğit
  • 649
  • 10
  • 21
1

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: the following options are 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 occurred. The default is undefined.

    str: error details

    e: event

appendTo: The node to which the new script will be append. The default is the 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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrej
  • 679
  • 5
  • 14
1

Make a fetch request and eval the result.

9pfs
  • 560
  • 5
  • 17
1

My general solution taken from the efekt.js.st library from EdgeS (which I authored).

shameless plug alert - I am on other stackexchange network sites. This is a relink of https://codereview.stackexchange.com/questions/263764/dynamic-load-css-or-script.

What code or design would you use to support dynamic-loading of css and scripts?

Requirements

  • support promise-await-async including error-handling
  • support load-once caching, including reloading
  • support load in head, body, or current script-element
  • support load css, js, mjs modules or other script-types
  • support other tag attrs, like nonce, crossorigin, etc
static loadScriptOrStyle(url, options) {
  // provenance :<# **Smallscript EdgeS efekt** `efekt.js.st` github libraries #>
  // returns    :<Promise#onload;onerror>
  // options    :<# `fIgnoreCache`, `fAppendToHead`, `fUrlIsStyle`, `attrs:{}` #>
  const head = document.head; let node = options?.fAppendToBody ? document.body : head;
  const url_loader_cache = document.head.url_loader_cache
    ? head.url_loader_cache
    : (head.url_loader_cache = {script:{},link:{}})
  const kind = (options?.fUrlIsStyle || /\.css(?:(?:\?|#).*)?$/i.test(url))
    ? 'link' : 'script';
  // check already-loaded cache
  if(url_loader_cache[kind][url]) {
    const el = url_loader_cache[kind][url];
    // support `fIgnoreCache` reload-option; should not use on `head`
    if(options?.fIgnoreCache)
      el.remove();
    else
      return(new CustomEvent('cache',{detail:el}));
  }
  // (re)create and record it
  const self = document.currentScript;
  const el = url_loader_cache[kind][url] = document.createElement(kind);
  const append = (!self || options?.fAppendToHead || options?.fAppendToBody)
    ? el => node.appendChild(el)
    : el => self.parentNode.insertBefore(el, self);
  const load = new Promise((resolve, reject) => {
    el.onload  = e => {e.detail = el;resolve(e)};
    el.onerror = e => {e.detail = el;reject(e)};
    // `onload` or `onerror` possibly alter `cache` value
    // throw(new URIError(`The ${url} didn't load correctly.`))
  });
  // configure `module` attr, as appropriate
  if(/\.mjs(?:(?:\?|#).*)?$/i.test(url))
    el.type = 'module'
  // configure other attrs as appropriate (referrer, nonce, etc)
  for(const key in options?.attrs) {el[key] = attrs[key]}
  // trigger it
  if(kind === 'link') el.rel = 'stylesheet', el.href = url; else el.src = url;
  append(el);
  return(load);
}
smallscript
  • 643
  • 7
  • 13
1

So if you want it quick, and easy... Try this:

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

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

    head.appendChild(script)
}
Enrico König
  • 206
  • 1
  • 13
  • 22
1

It’s this simple:

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

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

document.body.appendChild(js);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Enrico König
  • 206
  • 1
  • 13
  • 22
1

If you want to have a single link to all your javascript functions which are located in different files, you can do something like this using php:

Create a php file that will store all your javascript functions/triggers javascript.php and make sure its a .php file:

in your <head> section

 <script src="/directory/javascript.php"></script>

Let say you have a folder called /functions where all the javascript files are located. Within your javascript.php, create a header with content type application/javascript, and use php glob to include all the javascript files/scripts like so:

javascript.php

<?php 
header("content-type:application/javascript");
foreach(glob("/functions/*.js") as $filename){include($filename);}
?> 

Now you can just create separate javascript files and add them to your /functions folder, or whatever you may call it. Those will be automatically included into the javascript.php file that is actually a functioning js file which you can link in your <head> section.

Maciek Semik
  • 1,872
  • 23
  • 43
0

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

File jsMod.js

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

File jsView.js

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

File jsContr.js

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 a lot of time in the beginning to set up, but it saves you time in the long run.

I use this in a slightly different way, but this way also works.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hmerman6006
  • 1,622
  • 1
  • 20
  • 45
0

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

File 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"
  }
}

File src/someimport.ts

class SomeClass {
    delay: number;
}

File src/main.ts

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

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

This main Gulp.js 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. Triple-Slash Directives
  2. When do I need a triple slash reference?

Refer to gulp-typescript if you would like to customize the var tsProject = ts.createProject call and not use a tsconfig.json file or override its parameters.

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

Pure javascript version

If you would like to target all your TypeScript 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:

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

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

File 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. TypeScript: Gulp
  2. Can I use TypeScript without RequireJS?
  3. Simple concatenation of main file that requires another JavaScript file using Gulp.js
  4. Client on Node.js: Uncaught ReferenceError: require is not defined
  5. How can TypeScript browser Node.js modules be compiled with Gulp.js?
  6. Concatenate files using babel
  7. How can I 'require' CommonJS modules in the browser?
  8. Is there an alternative to Browserify?
Evandro Coan
  • 8,560
  • 11
  • 83
  • 144
0

To import another script in JavaScript use the import keyword:

import '/src/js/example.js';

// both types of quotes work
import "/src/js/example2.js";
BGP100
  • 61
  • 5
0

I will assume you are importing a file from the same directory, if not, you can update the path to fit the path.

To import another JavaScript file in the same directory, you can use the ES6 import statement. Assuming you have two files, main.js and helper.js, both located in the same directory, you can import helper.js in main.js as follows:

In helper.js:

export function helperFunction() {
    // helper function code
}

In main.js:

import { helperFunction } from './helper.js';

// use helper function
helperFunction();

The import statement is followed by the name of the function or variable you want to import, and the path to the file, starting with ./ to indicate that it's in the current directory.

Note that the file extension .js is usually omitted in the import statement, but you can include it if you prefer.

Make sure to include the appropriate script tags in your HTML file to load both main.js and helper.js.

David Kariuki
  • 1,522
  • 1
  • 15
  • 30
0

include js internal url path

function createElement(urlPath) {
  let s = document.createElement("script");
  s.url = urlPath
  document.body.appendChild(s);
}
function includeMoreJsPath(jsFilePath) {
    for(let path of jsFilePath){
      createElement(path)
    }
}

includeMoreJsPath(["/path/to/some/file.js","/path/to/some/file2.js"]);
/*
<script src="/path/to/some/file.js"></script>
<script src="/path/to/some/file2.js"></script>
*/

include the external js url path
or you can eval directly from text code

function createElement(code) {
  let s = document.createElement("script");
  s.appendChild(document.createTextNode(code));
  document.body.appendChild(s);
}
async function includeMoreJsPath(jsFilePath) {
    for(let path of jsFilePath){
      let code = await(await fetch(path)).text()
      createElement(code)
    }
}

includeMoreJsPath(["'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'"]);
/*
<script> ...code... </script>
*/
perona chan
  • 101
  • 1
  • 8
-1

On the back-end, you can use CommonJS modules. For example:

//a.js
function func () {
   var result = "OK Bro";
   return result;
}

module.exports = { func };
//b.js
var a = require('./a.js');
console.log(a.func);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nirvana
  • 405
  • 3
  • 15
-1

This is the easiest solution. Use a bundler like Vite.js and then simply do:

import "./path/to/js/file";

That's it! The OP has asked for something like "@import in CSS" and this is exactly like that. It is also not as rocket science complex as some of the old methods. It is at least undoubtedly the most beginner-friendly method, but I'm sure non-beginners do like it as well.

To get started with Vite for a vanilla JavaScript project, just have Node.js and [NPM3 installed, and then do:

npm create vite@latest <your-vanilla-js-app-name> --template vanilla

E.g.:

npm create vite@latest my-js-app --template vanilla

Now add imports like mentioned at the beginning of this answer and call it a day.

Just as a side note: Also another thing that might pop into your mind is namespacing issues, e.g., what if a name you have used in a file you're including is similar to a name you already have in your current file? But that's the nature of JavaScript, right? It's not an issue specific to this method.

So you'll need to devise strategies for handling that separately. There's a comprehensive article on Addy Osmani's blog in case you want to learn more about that: Design Patterns for Handling the Global Namespace in JavaScript.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
aderchox
  • 3,163
  • 2
  • 28
  • 37
  • __Notice1:__ You might need to run an additional `npm run dev` as well in case it doesn't start the server for you automatically. __Notice2:__ Of course Vite.js is more than just a bundler, refer to their website if you want to know more: https://vitejs.dev/. __Notice3:__ I was the 5959th upvote on this question, it's pointless, but it's funny :D – aderchox May 22 '22 at 07:58
-3

You can just use the require(); tag.

For example, if I had a addition.js module that I wanted to add to math.js, I would do this:

//this is math.js

//vars
let a = 1;
let b = 3;

//start of code
const additionfile = require('addition.js');
window.alert("You added " + a + " and " + b + " together, to get " + additionfile.add(a,b) + "!");

if you wanted the addition.js file, it would look something like this

function add(a,b) {
   const sum = a + b;
   return sum;
}