some time ago we wrote about how to Import one JS file into another in the plain JS, those techniques described were quite old and in the modern era javascript has changed a lot and new frameworks have come out with a better syntax. In this case we will use the ES6 syntax to better include Js files in other Js files.
What are ES6 Modules?
In the early era of the web, the role of JavaScript was limited to form validation and to provide 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 in a JS file.
Popular Ways to Include a JavaScript File in Another JavaScript File
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 requires a 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, we used the export keyword before the function and variable to specify that these objects can be used by other files.
Now, create another file named main.js and write the following code in it:
import { greet, message } from "./utils.js";const greet_yash = greet("Yash");console.log(greet_yash); // Hello, Yash console.log(message); // How you doing?
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_yash = randomName("Yash"); console.log(greet_yash); // Hello, Yash
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 can mix default and normal exports like this:
import defaultExport, {export1, export2} from "file.js"
- We can import an entire module’s content using the *:
import * as utils from 'utils.js';
- 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 };
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_yash = greet("Yash"); console.log(greet_yash); 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.
You can’t load the modules locally (that is with a file:// URL) inside your browsers due to JavaScript module security requirements.
Using Node.js require
Another popular way to import and export JS files is using the Node JS require function.
Node.js is an open-source, cross-platform, back-end JavaScript runtime environment used to execute JavaScript code outside a web browser. It is used to create web servers.
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_yash = utils.greet("Yash");console.log(greet_yash); 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, Yash 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.
Dynamic Imports in Browsers
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("Yash")); });
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 fulfills 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
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.
So this was all in “including a JavaScript file in another JavaScript file” ,I will be coming with more such articles in the future.
Janeth Kent
Licenciada en Bellas Artes y programadora por pasión. Cuando tengo un rato retoco fotos, edito vídeos y diseño cosas. El resto del tiempo escribo en MA-NO WEB DESIGN AND DEVELOPMENT.