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 introduced a native module system using import and export keywords. A module is simply a file that exports values for other files to consume.
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; }
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; }
}
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}`);
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.
Bundlers like Webpack and Vite take your module files and combine them into one or more bundle files optimised for the browser.
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 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 (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
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"]
}
.gitignore file to exclude node_modules/ and build output directories. Run npm audit regularly to check for vulnerable dependencies.
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.