Table of Contents
Node.js module
module.exports
require('id')
Module type
Module name
File path
Single loading & circular dependency
工作原理
在 Node.js 中使用 ES Module
babel 构建
原生支持
Home Web Front-end JS Tutorial Understanding the module system in Node.js

Understanding the module system in Node.js

Nov 24, 2020 pm 05:58 PM
node.js Module system

Understanding the module system in Node.js

Related recommendations: "node js tutorial"

Node.js module

JavaScript as a A simple scripting language to add interactive functions to web pages came out. It did not include a module system at the beginning. As JavaScript solved more and more complex problems, writing all codes in one file and using function to distinguish functional units can no longer support the development of complex applications. Yes, ES6 brings classes and modules that are common in most high-level languages, making it easier for developers to organize code

import _ from 'lodash';

class Fun {}

export default Fun;
Copy after login

The above three lines of code show the two most important elements of a module system, import and export

  • export is used to specify the external interface of the module

  • import is used to import the functions provided by other modules

Before ES6, many module loading solutions appeared in the community, the most important ones were CommonJS and AMD. Node.js was born earlier than ES6, and the module system used something similar to CommonJS The implementation follows several principles

  • A file is a module, and the scope of variables in the file is within the module

  • Usemodule.exports Object export module external interface

  • Use require to introduce other modules

circle.js

const { PI } = Math;

module.exports = function area(r) {
  PI * r ** 2;
};
Copy after login

The above code implements a module of Node.js. The module does not depend on other modules and exports the methodarea to calculate the area of ​​a circle

test.js

const area = require('./circle.js');
console.log(`半径为 4 的圆的面积是 ${area(4)}`);
Copy after login

The module relies on circle.js and uses its exposed area method to calculate the area of ​​the circle

module.exports

The external exposed interface of the module uses module.exports. There are two common usages: adding attributes to it or assigning values ​​to new objects.
test.js

// 添加属性
module.exports.prop1 = xxx;
module.exports.funA = xxx;
module.exports.funB = xxx;

// 赋值到全新对象
module.exports = {
  prop1,
	funA,
  funB,
};
Copy after login

The two writing methods are equal to Price, there is no difference when using

const mod = require('./test.js');

console.log(mod.prop1);
console.log(mod.funA());
Copy after login

There is another way to directly use the exports object, but you can only add attributes to it and cannot assign it to a new object. The reason will be introduced later.

// 正确的写法:添加属性
exports.prop1 = xxx;
exports.funA = xxx;
exports.funB = xxx;

// 赋值到全新对象
module.exports = {
  prop1,
	funA,
  funB,
};
Copy after login

require('id')

Module type

require usage is relatively simple, id supports two types: module name and file path

Module name

const fs = require('fs');
const _ = require('lodash');
Copy after login

The fs and lodash in the example are both module names. fs is the built-in core module of Node.js, and lodash is a third-party module installed through npm under node_modules. If there are duplicate names , give priority to using the system’s built-in modules

Because a project may contain multiple node_modules folders (Node.js’ relatively failed design), the third-party module search process will follow the principle of proximity and go up layer by layer (you can find it in the program Print module.paths to view the specific search path) until the file system root directory is found according to the NODE_PATH environment variable. For the specific process, please refer to the official documentation

In addition, Node .js also searches the following global directory listing:

  • $HOME/.node_modules
  • $HOME/.node_libraries
  • $PREFIX/lib/node

$HOME is the user's home directory, $PREFIX is the node_prefix configured in Node.js. It is strongly recommended to place all dependencies in the local node_modules directory, which will load faster and be more reliable

File path

Modules can also be loaded using file paths. This is the project A common loading method for custom modules within the directory. The path extension can be omitted. Modules prefixed with

'/'
    will be tried in the order of .js, .json, and .node.
  • Is the absolute path of the file. Find the module according to the system path.
  • Modules prefixed with './' are relative to the file currently calling the require method, and are not affected by where subsequent modules are used. To affect

Single loading & circular dependency

The module will be cached to Module._cache after the first load, if it is called every time ## If #require('foo') is parsed to the same file, the same object will be returned. Calling require(foo) multiple times at the same time will not cause the module's code to be executed multiple times. Node.js caches modules based on their actual file names, so the same module is not loaded twice when referenced from different levels of directories.

The understood module single loading mechanism facilitates our understanding of the phenomenon of module circular dependencies


a.js

console.log('a 开始');
exports.done = false;
const b = require('./b.js');
console.log('在 a 中,b.done = %j', b.done);
exports.done = true;
console.log('a 结束');
Copy after login

b.js

console.log('b 开始');
exports.done = false;
const a = require('./a.js');
console.log('在 b 中,a.done = %j', a.done);
exports.done = true;
console.log('b 结束');
Copy after login

main.js:

console.log('main 开始');
const a = require('./a.js');
const b = require('./b.js');
console.log('在 main 中,a.done=%j,b.done=%j', a.done, b.done);
Copy after login
When main.js loads a.js, a.js loads b.js. At this time, b.js will Try to load a.js

In order to prevent an infinite loop, an

unfinished copy of the exports object of a.js will be returned to the b.js module, and then b.js will complete the loading. And provide the exports object to the a.js module

so the output of the example is

main 开始
a 开始
b 开始
在 b 中,a.done = false
b 结束
在 a 中,b.done = true
a 结束
在 main 中,a.done=true,b.done=true
Copy after login

看不懂上面的过程也没关系,日常工作根本用不到,即使看懂了也不要在项目中使用循环依赖!

工作原理

Node.js 每个文件都是一个模块,模块内的变量都是局部变量,不会污染全局变量,在执行模块代码之前,Node.js 会使用一个如下的函数封装器将模块封装

(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});
Copy after login
  • __filename:当前模块文件的绝对路径
  • __dirname:当前模块文件据所在目录的绝对路径
  • module:当前的模块实例
  • require:加载其它模块的方法,module.require 的快捷方式
  • exports:导出模块接口的对象,module.exports 的快捷方式

回头看看最开始的问题,为什么 exports 对象不支持赋值为其它对象?把上面函数添加一句 exports 对象来源就很简单了

const exports = module.exports;
(function(exports, require, module, __filename, __dirname) {
	// 模块的代码实际上在这里
});
Copy after login

其它模块 require 到的肯定是模块的 module.exports 对象,如果吧 exports 对象赋值给其它对象,就和 module.exports 对象断开了连接,自然就没用了

在 Node.js 中使用 ES Module

随着 ES6 使用越来越广泛,Node.js 也支持了 ES6 Module,有几种方法

babel 构建

使用 babel 构建是在 v12 之前版本最简单、通用的方式,具体配置参考 @babel/preset-env(https://babeljs.io/docs/en/babel-preset-env)

.babelrc

{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "node": "8.9.0",
        "esmodules": true
      }      
    }]
  ]
}
Copy after login

原生支持

在 v12 后可以使用原生方式支持 ES Module

  • 开启 --experimental-modules

  • 模块名修改为 .mjs (强烈不推荐使用)或者 package.json 中设置 "type": module

这样 Node.js 会把 js 文件都当做 ES Module 来处理,更多详情参考官方文档(https://nodejs.org/dist/latest-v13.x/docs/api/esm.html)

更多编程相关知识,请访问:编程视频!!

The above is the detailed content of Understanding the module system in Node.js. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Detailed graphic explanation of the memory and GC of the Node V8 engine Detailed graphic explanation of the memory and GC of the Node V8 engine Mar 29, 2023 pm 06:02 PM

This article will give you an in-depth understanding of the memory and garbage collector (GC) of the NodeJS V8 engine. I hope it will be helpful to you!

An article about memory control in Node An article about memory control in Node Apr 26, 2023 pm 05:37 PM

The Node service built based on non-blocking and event-driven has the advantage of low memory consumption and is very suitable for handling massive network requests. Under the premise of massive requests, issues related to "memory control" need to be considered. 1. V8’s garbage collection mechanism and memory limitations Js is controlled by the garbage collection machine

Let's talk about how to choose the best Node.js Docker image? Let's talk about how to choose the best Node.js Docker image? Dec 13, 2022 pm 08:00 PM

Choosing a Docker image for Node may seem like a trivial matter, but the size and potential vulnerabilities of the image can have a significant impact on your CI/CD process and security. So how do we choose the best Node.js Docker image?

Node.js 19 is officially released, let's talk about its 6 major features! Node.js 19 is officially released, let's talk about its 6 major features! Nov 16, 2022 pm 08:34 PM

Node 19 has been officially released. This article will give you a detailed explanation of the 6 major features of Node.js 19. I hope it will be helpful to you!

Let's talk in depth about the File module in Node Let's talk in depth about the File module in Node Apr 24, 2023 pm 05:49 PM

The file module is an encapsulation of underlying file operations, such as file reading/writing/opening/closing/delete adding, etc. The biggest feature of the file module is that all methods provide two versions of **synchronous** and **asynchronous**, with Methods with the sync suffix are all synchronization methods, and those without are all heterogeneous methods.

Let's talk about the GC (garbage collection) mechanism in Node.js Let's talk about the GC (garbage collection) mechanism in Node.js Nov 29, 2022 pm 08:44 PM

How does Node.js do GC (garbage collection)? The following article will take you through it.

Let's talk about the event loop in Node Let's talk about the event loop in Node Apr 11, 2023 pm 07:08 PM

The event loop is a fundamental part of Node.js and enables asynchronous programming by ensuring that the main thread is not blocked. Understanding the event loop is crucial to building efficient applications. The following article will give you an in-depth understanding of the event loop in Node. I hope it will be helpful to you!

Let's talk about how to use pkg to package Node.js projects into executable files. Let's talk about how to use pkg to package Node.js projects into executable files. Dec 02, 2022 pm 09:06 PM

How to package nodejs executable file with pkg? The following article will introduce to you how to use pkg to package a Node project into an executable file. I hope it will be helpful to you!

See all articles