JavaScript (Node.js) 中的模块、包和导入:详细指南
What is it and why? (a real-life analogy)
Imagine you are building a huge house. You wouldn't make the bricks yourself, smelt the glass, and chop down the forest, would you? Of course not! You would buy ready-made materials: bricks from the factory, windows from the store, and boards from the sawmill. It's the same in programming: when a program becomes large, writing all the code in one file is like trying to build a skyscraper from one giant piece of plasticine. It will be inconvenient, confusing, and will break at the first attempt to change something.
Modules are those very "ready-made bricks" for your program. Each module is a separate file (or piece of code) that does one thing, but does it well. For example, one module can send emails, a second can draw graphs, and a third can work with a database.
Packages are entire "toolkits" or "boxes of parts". If a module is one brick, then a package is a whole pallet of bricks, plus instructions for laying, plus a trowel. In the world of JavaScript (Node.js), packages are ready-made libraries that other programmers have written and posted on the internet so that you can download and use them.
Import is the process where you tell the program: "Hey, bring me that brick from that warehouse!". That is, you take ready-made code from another file or from a package and use it in your project.
💡 Important: Without modules and imports, you would have to write everything from scratch every time. Imagine that every time you need to calculate a square root, you reinvent mathematics. Modules allow you not to reinvent the wheel, but to take a ready-made "wheel" tested by thousands of people and ride it.
Why is this needed?
- Order: The code is broken down into small, understandable pieces. It's easy to find an error.
- Reusability: Write a module for calculating a discount once — use it in 10 different projects.
- Teamwork: One programmer writes a module for logging in, another for a chat. They don't interfere with each other.
- Saves time: You don't need to write complex things yourself. Download a package (for example, for sending SMS) — and it's done.
Theory: how it works from the inside
Let's look "under the hood" of Node.js and see what happens when you write require('fs') or import fs from 'fs'.
In Node.js, there are two main module systems: CommonJS (CJS) and ES Modules (ESM). They are like two different languages within one: both solve the same problem, but do it differently.
CommonJS (CJS) — the old but reliable school
Previously, JavaScript did not have a built-in module system. Node.js invented its own — CommonJS. It works like this:
- Each file is a separate module.
- Variables and functions declared in a file are not visible from the outside until they are specifically "exported".
- To take something from another file, the
require()function is used. - To give something out, the
module.exportsobject or simplyexportsis used.
When Node.js encounters require('./myModule'), it does the following:
- Searches for the file: First, it checks if the file
myModule.jsexists. If not, it looks for a foldermyModulewith a fileindex.jsinside. If it doesn't find that either, it goes into thenode_modulesfolder (where downloaded packages are stored). - Reads the file: Opens the file and reads its contents.
- Wraps in a function: Node.js does not execute the file's code as is. It wraps it in a special wrapper function that gives the module its own variables:
exports,require,module,__filename,__dirname. - Executes: Runs the code inside this function.
- Caches: Remembers the result. If you request the same module again, Node.js will not execute it again, but will simply return the saved result. This is very fast!
- Returns module.exports: What the module put into
module.exportsbecomes the result of callingrequire().
ES Modules (ESM) — the new standard
Modern JavaScript (starting from ES2015) invented its own, more elegant way: import and export. It works a bit differently:
- Uses the keywords
importandexport. - Works asynchronously (can load modules in parallel, which is faster).
- Stricter: imports must be at the very top of the file; they cannot be hidden inside an
ifcondition. - To use ESM in Node.js, you need to either put the line
"type": "module"inpackage.json, or give the files the.mjsextension.
⚠️ Important difference: In CommonJS,require()is a regular function that can be called anywhere (even inside a loop). In ESM,importis a static declaration that is executed before the main code starts executing. This allows code analyzers to better understand the program's structure and optimize it.
Syntax in JavaScript (Node.js): all forms and variants
Let's break down all possible ways to export and import code. We will look at both systems: CommonJS (CJS) and ES Modules (ESM).
CommonJS (CJS) — syntax
Export (giving out):
| Method | Code | Description |
|---|---|---|
| Exporting a single value | ```