← Back to Tutorials Chapter 9

Modules & Tooling

Modern JavaScript development relies on modules to organise code and tooling to automate repetitive tasks. This chapter covers ES6 modules, dynamic imports, module bundlers, npm, and build tools.

ES6 Modules

ES6 introduced a native module system using import and export keywords. A module is simply a file that exports values for other files to consume.

Named Exports

You can export multiple values from a module by prefixing declarations with export.

// math.js
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }

Default Export

Each module can have one default export, typically used for the main functionality.

// calculator.js
export default class Calculator {
  constructor() { this.result = 0; }
  add(n) { this.result += n; return this; }
  subtract(n) { this.result -= n; return this; }
  getResult() { return this.result; }
}

Importing

Named imports use curly braces; default imports do not.

// app.js
import Calculator from './calculator.js';
import { PI, add } from './math.js';

const calc = new Calculator();
calc.add(10).subtract(3);
console.log(calc.getResult()); // 7
console.log(`PI is ${PI}`);
Module Scope: Variables declared in a module are scoped to that module and never leak to the global scope. You must explicitly export anything you want to share.

Dynamic Import()

Use import() as a function to load modules on demand at runtime. It returns a promise.

const modulePath = './math.js';
const module = await import(modulePath);
console.log(module.PI);

Dynamic imports are useful for code splitting — loading only the code the user needs at the moment they need it.

Module Bundlers

Bundlers like Webpack and Vite take your module files and combine them into one or more bundle files optimised for the browser.

JavaScript module dependency tree

Webpack

Webpack is a mature bundler that processes your entry file, follows the dependency graph, and outputs bundled assets. It uses loaders for CSS, images, and transpilers.

// webpack.config.js (basic)
module.exports = {
  entry: './src/index.js',
  output: { path: __dirname + '/dist', filename: 'bundle.js' },
};

Vite

Vite is a next-generation build tool that leverages native ES modules during development for near-instant hot reloading. It uses Rollup under the hood for production builds.

# Create a new Vite project
npm create vite@latest my-app -- --template vanilla

npm Basics

npm (Node Package Manager) is the default package manager for Node.js. A package.json file tracks your project’s metadata and dependencies.

{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": {
    "lodash": "^4.17.21"
  }
}
# Installing packages
npm install lodash
npm install -D eslint   # dev dependency

Transpilers & Build Tools

Babel transpiles modern JavaScript (ES6+) into backwards-compatible versions for older browsers. It works as a plugin system and is commonly integrated with Webpack.

// .babelrc
{
  "presets": ["@babel/preset-env"]
}
Best Practice: Always use a .gitignore file to exclude node_modules/ and build output directories. Run npm audit regularly to check for vulnerable dependencies.

Exercise: Module Refactor

Take a script with three utility functions (e.g., capitalize, reverse, randomInt). Split them into a separate module file with named exports. Import them in your main file and use each function. Then create a default export class called StringHelper that wraps some of these utilities.