file
javascript

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

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Including one JavaScript file in another is really a module-loading problem, and the right approach depends on runtime environment. Browsers, Node.js, and build tools support different module systems with different syntax and behavior. Using the correct system avoids path bugs, duplicate execution, and deployment surprises.

Use ES Modules in Modern JavaScript

For modern browser and Node.js code, ES modules are the default pattern.

math.js:

javascript
1export function add(a, b) {
2  return a + b;
3}
4
5export const PI = 3.14159;

main.js:

javascript
1import { add, PI } from "./math.js";
2
3console.log(add(2, 3));
4console.log(PI);

Browser HTML needs module script type.

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

Without module script type, browser treats import as syntax error.

Default Exports Versus Named Exports

A module can export one default value and multiple named values. Keep style consistent within a codebase.

javascript
1// logger.js
2export default function log(message) {
3  console.log(`[app] ${message}`);
4}
5
6export function warn(message) {
7  console.warn(`[warn] ${message}`);
8}
javascript
1import log, { warn } from "./logger.js";
2
3log("started");
4warn("slow response");

Named exports improve refactor safety for large modules, while default exports are sometimes convenient for single-primary modules.

Node.js: ES Modules and CommonJS

Node.js supports both systems, but mixing them requires care.

CommonJS style

javascript
1// calc.cjs
2function multiply(a, b) {
3  return a * b;
4}
5
6module.exports = { multiply };
javascript
// app.cjs
const { multiply } = require("./calc.cjs");
console.log(multiply(4, 5));

ES module style in Node

Set module type in package configuration or use .mjs extension.

json
{
  "type": "module"
}
javascript
// app.js
import { add } from "./math.js";
console.log(add(1, 2));

Choose one system per package where possible to keep tooling simple.

Script Tags Without Modules

If you are not using modules, script load order in HTML matters.

html
<script src="lib.js"></script>
<script src="main.js"></script>

main.js can use globals declared by lib.js only if lib.js loaded first. This approach works but scales poorly because global namespace collisions become likely in large apps.

Dynamic Loading with import

When code should load on demand, use dynamic import.

javascript
1async function loadCharts() {
2  const mod = await import("./charts.js");
3  mod.renderChart();
4}
5
6document.getElementById("open-report").addEventListener("click", loadCharts);

This can reduce initial bundle size and improve startup performance.

Build Tools and Path Resolution

In real apps, bundlers such as Vite, Webpack, and Rollup often handle import resolution and transpilation. Even then, module semantics remain the same.

Useful rules:

  • use explicit relative paths for local files
  • avoid circular dependencies
  • keep side-effect modules clearly documented

Example side-effect import:

javascript
1import "./polyfills.js";
2import { bootstrap } from "./app.js";
3
4bootstrap();

This pattern is valid but should be used intentionally because import execution order can influence app startup behavior.

Browser Security and CORS Notes

When testing modules in browser, serving files over HTTP is usually required. Opening file URLs directly can fail with module import restrictions.

Quick local server example:

bash
npx serve .

Then open provided localhost URL. This avoids cross-origin and file-origin module loading problems.

Debugging Failed Imports

When import fails, check these first:

  1. path spelling and extension
  2. module type configuration
  3. server response status code
  4. case-sensitivity differences across operating systems

In browser dev tools, network tab often reveals wrong path or MIME errors immediately.

Common Pitfalls

A common pitfall is using import in browser without type="module". Another is mixing CommonJS and ES module syntax in the same file without interoperability handling. Teams also often omit file extension in browser imports and get failed network requests. Finally, relying heavily on global script order works for small pages but becomes fragile in larger codebases.

Summary

  • Prefer ES modules for modern JavaScript in browser and Node.js.
  • Use require only in CommonJS codebases or legacy environments.
  • Configure module type correctly in HTML and Node package settings.
  • Use dynamic import for on-demand code loading.
  • Debug import failures through path, config, and network checks first.

Course illustration
Course illustration

All Rights Reserved.