How to include a JavaScript file in another JavaScript file?

quiz
Challenge Inside! : Find out where you stand! Try quiz, solve problems & win rewards!

Overview

We can include a JavaScript file in another JavaScript file using the native ES6 module system. This allows us to share code between different JavaScript files and achieve modularity in the code. There are other ways to include a JS file like Node JS require, jQuery's getScript function, and Fetch Loading.
In this article, we are going to go through each method in detail.

Scope

In this article, we will discuss how to include a javascript file in another javascript file. We will get into the depth of import and export of modules in javascript.

What are ES6 Modules?

In the early era of the web, the role of JavaScript was limited to form validation and providing a little bit of interactivity, so large scripts were not needed.

Today, JavaScript has become a primary language to develop web apps, including both backend and frontend. Thus the size of the JS programs has also grown exponentially, making it harder to manage code.

This motivated the use of module system, a way to divide the code into multiple files and directories but still make sure all the bits of code can access one another.

As the old versions of JavaScript have no native module system, many JavaScript libraries come with their own. For example - CommonJS and RequireJS.

JavaScript introduced a native module system in ES6 (ECMAScript 6 - the official name of JavaScript) called the ES6 Module.

An ES6 module is just a file containing JS code with two special characteristics:

  • It is automatically in strict-mode: this prohibits the use of sloppy mistakes in the code, like using variables without defining.
  • You can use the import or export keyword inside of it: providing a way to share the code with other files.

Let's discuss different ways to achieve modularity and learn how to import a JS file into a JS file.

Takeaway:

An ES6 module is a JS file that can export its code to share with other files and import and use code from other JS files.

In this section, we will learn about two popular ways of including a JS file in another JS file:

  • Using ES6 modules.
  • Using Node JS require function.

Using import/export | ES6 module

Let's start by using the ES6 way of importing and exporting. Create a file named utils.js and define the following function and constant inside it:

export function greet(name) {
  return `Hello, ${name}`;
}

export const message = "How you doing?";

Notice that we used the export keyword before the function and variable to specify that these objects can be used by other files.

The Hello, ${name} is a template literal in JavaScript. It allows us to embed variables inside a string using the $ and {} syntax.

Now, create another file named main.js and write the following code in it:

import { greet, message } from "./utils.js";

const greet_scaler = greet("Scaler");

console.log(greet_scaler); // Hello, Scaler
console.log(message); // How you doing?

syntax to import

In the first line, we are importing greet and message from utils.js by specifying them inside of curly braces {}.
After this line, we can use the imported objects as they are defined in the same file. Then, we console logged the output of both the objects.

ES6 syntax for importing: import {object1, object2, ...} from 'filename.js'

If you are going to use ES6 modules in a node js environment, remember to name your files with .mjs extension or set "type": "module" in the package.json file.

Using Default Exports

We can use the default keyword to export one object by default from a file. What does this mean? Let's see with an example. Make the greet function in utils.js a default export by adding default before it:

export default function greet(name) {
  return `Hello, ${name}`;
}

Now, you can import it in main.js like this:

import randomName from "./utils.js";

const greet_scaler = randomName("Scaler");

console.log(greet_scaler); // Hello, Scaler

It will work the same as before!

While performing default export, randomName is imported from greet.js. Since randomName is not in utils.js, the default export (greet() in this case) is exported as random_name.

Note 📝:

Let's discuss some important points related to ES6 modules that one should remember when using them:

  • We have to remove the curly braces when importing default exports.
    For instance, if we have kept the braces in the randomName example above like this:

    import { randomName } from "./utils.js";
    

    It would have thrown an error saying no such export exists.

  • A file can contain multiple exports. However, we can only define a single default export in a file.
    Thus the following JavaScript code is invalid ❌:

    export default function greet(name) {
      return `Hello, ${name}`;
    }
    
    export default defaultMessage = "Not Possible";
    
    export const message = "How you doing?";
    
  • We cannot use an alias name when importing a normal export.
    Thus the following import is invalid ❌:

    import { randomMessage } from "./utils.js";
    

    We must use the same name when importing a normal export.

  • We can mix default and normal exports like this:

    import defaultExport, {export1, export2} from "file.js"
    

    Notice, we used {} for named (normal) exports and put the default export without {}.

  • We can import an entire module's content using the *:

    import * as utils from 'utils.js';
    

    Then, you can access all the export using the module as a namespace:

    utils.greet("Scaler");
    
  • You can export all the objects together at the end of the file Example:

    function greet(name) {
      return `Hello, ${name}`;
    }
    
    const message = "How you doing?";
    
    export { greet, message };
    
  • You can rename exports and imports

    • Example of renaming exports:
      export { greet as newGreet, message as newMessage };
      
      and in the import file:
      import { newGreet, newMessage } from "./utils.js";
      
    • Example of renaming imports:
      import { greet as newGreet, message as newMessage } from "./utils.js";
      
      and in the export file:
      export { greet, message};
      

    This could help manage name conflicts between similar imports.

Now, we will see how to run these ES6 modules inside a browser.

Using ECMAScript (ES6) modules in browsers

Most modern browsers like chrome, safari and firefox have support for running ES6 modules directly. Let's try running the modules created before in a browser.

In the previous section, we created two JS files with the following code:

  • utils.js
    export function greet(name) {
      return `Hello, ${name}`;
    }
    
    export const message = "How you doing?";
    
  • main.js
    import { greet, message } from "./utils.js";
    
    const greet_scaler = greet("Scaler");
    
    console.log(greet_scaler); 
    console.log(message);
    

In the main.js file, we imported and used a function from utils.js using the import keyword.

Now, we want to run main.js using a browser by linking the main.js module to an HTML file.

Therefore, create an index.html file and include the main.js script as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Using ES6 modules</title>
  </head>
  <body>

    <script src="main.js" type="module"></script>
  </body>
</html>

We need the type="module" attribute in the <script> element to declare this script as a module. The type="module" allows the use of import and export inside a JS file.

Open the HTML file in a browser using a local server and then open the console (press F12). You will see the following output:

seeing results in console

You can't load the modules locally (that is with a file:// URL) inside your browsers due to JavaScript module security requirements.

Tip 💡:

If you are using VS Code, you can use the live server extension to host the HTML file.

Using Node.js require

The following section requires a basic understanding of Node JS Framework. You may skip this section if you are new to JavaScript.

Another popular way to import and export JS files is using the Node JS require function.

Node.js is an open-source, cross-platform, backend JavaScript runtime environment used to execute JavaScript code outside a web browser. It is used to create web servers.

You need to install Node JS to run the code given in this section.

Node JS has the module system even before the introduction of ES6 modules in JavaScript.

Let's rewrite the earlier greet example using require in Node JS. Create a new file utils.js with the following code:

console.log("Executing utils.js")

function greet(name) {
  return `Hello, ${name}`;
}

const message = "How you doing?";

module.exports = {
  greet,
  message,
};

The modules.exports object has all the exports from this file. Now, create the main.js file with the following code:

utils = require("./utils");

const greet_scaler = utils.greet("Scaler");

console.log(greet_scaler); 
console.log(utils.message); 

Notice the first line, we are using the require function by passing the name of the file we need to import.
The require function:

  • Reads the file
  • Executes the file
  • And then returns the exports object.

We stored the returned object into the utils variable and used it to access the greet function and message.

Try running it with the node as follows:

node main.js

And you will see the following output:

Executing utils.js
Hello, Scaler
How you doing?

Notice, the Executing utils.js in the output, it is because the require function is executing the file before returning the exports object.

Takeaways:

  • The ES6 module system and Node JS require are the most popular ways of including a JS file in another JS file.
  • Modern browsers also support ES6 modules directly.

Dynamic Imports in Browsers

The following section requires an understanding of Promises and async/await in JavaScript. You may skip this section if you are new to JavaScript.

Dynamically importing modules allows us to load modules only when they are needed, rather than loading everything upfront.

We use the import as a function to achieve this. Let's look at an example:

Keep the utils.js function as before:

function greet(name) {
  return `Hello, ${name}`;
}

const message = "How you doing?";
export { greet, message };

And add the following code to main.js to call the greet function only with a click of a button.

const button = document.querySelector("button");

button.addEventListener("click", async () => {
  const utils = await import("./utils.js");
  console.log(utils.greet("Scaler"));
});

Explanation We called the import function with the path of the module as a parameter. The import function returns a promise (that's why we are using the async/await) which fulfils with an object containing all the exports.

We then access the greet function using the returned module object.

When we should use dynamic imports?

We should use dynamic imports only when necessary, for example if there is a low likelihood that you will need the code you are importing. This may help improve the performance if the imported file has many lines of code and is used rarely.

Takeaway: We can dynamically import a module as needed using the import function.

Ajax with Fetch Loading

The following section requires an understanding of Promises and async/await in JavaScript. You may skip this section if you are new to JavaScript.

Till now, we have seen two popular ways of including a JS file in another JS file. We also saw how to use the ES6 modules on-demand in the previous section.
Now, in the following sections, we will see some other possible ways on how to include a js file in a js file, starting with the fetch loading.

The fetch() function in JavaScript is used to make HTTP requests to the server and load the information on the web pages.

We can load and execute a JS file using the fetch API and eval function. Add a simple log statement in the utils.js file:

console.log("Running utils.js");

Now, add the following code in the main.js file:

document.addEventListener("DOMContentLoaded", async () => {
  const utilsFile = await fetch("utils.js");
  const utilsText = await utilsFile.text();
  eval(utilsText);
});

Explanation We are waiting for our HTML page to load and then fetching the utils file using fetch.
Then we are accessing the code of the JavaScript file using the text function and stored it in utilsText then passed it to the eval function.
The eval function evaluates JavaScript code represented as a string. Evaluating the JavaScript code means it runs the code which was passed to the function in a string.

Warning Never use the eval function as it possesses security risks and it is far too easy for a bad actor to run arbitrary code when you use eval(). For example, if you use the eval on the server-side and a user used an infinite loop as their username, then it may crash the computer leading to server downtime.

Takeaway:

  • We can use the combination of fetch and eval() to execute a JS file in another JS file.

jQuery Loading

The following section requires a basic understanding of the jQuery Library. You may skip this section if you are new to JavaScript or you are unfamiliar with jQuery.

jQuery is a JavaScript library designed to simplify HTML DOM tree traversal and manipulation.
We can use its getScript function to load a JavaScript file and execute it.

To use jQuery add the following script tag in your HTML head element.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

Now keep the utils.js as follow:

console.log("Running utils.js");

And add the following code to main.js:

$(document).ready(function () {
  $.getScript("utils.js", function (data) {
    console.log(data); // Text of JS file
    console.log("Load was performed.");
  });
});

Explanation The $ is an alias of the jQuery object, we use it to access different functions provided by jQuery. Here, we are passing the path of our JS file to the getScript function. The getScript function will execute the code of utils.js and return the data (text of utils.js) in a callback function. Inside the callback function, we are consoling the data of the file.

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

Here is the output for the above code:

seeing results in console

Takeaway:

  • jQuery provides the getScript function to load and execute a JS file in another JS file.

Dynamic Script Loading

We can avoid the use of jQuery's getScript function by injecting a script tag ourselves.

This is how you would do it in the main.js file:

const scriptTag = document.createElement("script");
scriptTag.src = "utils.js";
document.body.appendChild(scriptTag);

Explanation We created a script tag and set its source attribute to the path of the JavaScript file. Then we appended the script tag to the body element.
Check the console now and you will see the same output as before.

Concatenate Files

In the above example, we included a single JS file in the main.js, we can do the same with multiple files.

Create a file first.js with the following code:

console.log("This is first.js")

Create another file second.js as follows:

console.log("This is second.js")

Now, in the main.js you can include both files as follows:

function include(filePath) {
    const scriptTag = document.createElement("script");
    scriptTag.src = filePath;
    document.body.appendChild(scriptTag);
}

include("first.js");
include("second.js");

It's the same code as before but now in a function. Making it easier to call it multiple times. You only need to include the main.js file in the HTML, the other two files will be included automatically.

Takeaway:

We can dynamically insert a script tag using DOM manipulation to load and execute a JS file without jQuery.

Detecting When the Script has Been Executed

Now, there is a problem with the above solution (Dynamic script loading). If we try to access a variable from the imported file just after appending it to the HTML, we will run into an error because the browsers load JS files asynchronously (simultaneously) to improve performance.

For example, if this is the utils.js file:

console.log("Running utils.js");
const message = "The file was loaded successfully";

And we are trying to access the message constant in main.js like this:

const scriptTag = document.createElement("script");
scriptTag.src = "utils.js";
document.body.appendChild(scriptTag);

console.log(message);

We will run into the following error:

seeing results in console

Uncaught ReferenceError: message is not defined

To solve this, we must make sure that any code in main.js that uses the objects from utils.js is run after the file is loaded.
For this, we can use a callback function on the onload attribute of the script tag:

function loadScript(path, callback) {
  const scriptTag = document.createElement("script");
  scriptTag.src = "utils.js";

  scriptTag.onload = callback;

  document.body.appendChild(scriptTag);
}

loadScript("utils.js", function () {
  console.log(message);
});

The key line here is: scriptTag.onload = callback;. The callback function is only called when the script is loaded. Now, the output will be correct:

Takeaway:

Use the onload event of the script element to run some code only when the script is loaded.

Conclusion

  • An ES6 module is a JavaScript file that can import and export code. It automatically uses the strict mode.
  • The ES6 module system and Node JS require are the most popular ways of including a JS file in another JS file.
  • Other methods for including a JS file in another JS file are:
    • Fetch Loading: Using the fetch and eval functions.
    • jQuery Loading: Using the getScript function.
    • Dynamic Script Loading: Using DOM manipulation.(DOM refers to Document Object Model, DOM manipulation means changing the items on the HTML page).
  • We can detect the successful execution of a script using the onload event of the script element.
Challenge Time!
quiz
quiz
Time to test your skills and win rewards! Note: Rewards will be credited after the next product update.
Free Courses by top Scaler instructors
rcbGet a Free personalized Career Roadmap from