Node.js require 模块加载原理 All In One
1.Adafruit & CircuitPython & Node.js All In One2.Node.js os module All In One3.Node.js & Raspberry Pi & WS2812B RGB LEDs strip All In One4.Node.js Buffer.from All In One5.Node.js Event Loop & V8 engine & libuv All In One6.Node.js & npm package.json exports field All In One7.Node.js cli tools auto install npm packages All In One8.Node.js 微服务 All In One9.如何定位和分析 Node.js 项目中的内存泄漏问题 All In One10.Node.js process.nextTick All In One11.Web API setImmediate & Node.js setImmediate All In One12.如何使用 Node.js 和 OpenAI API 快速开发一个私有的 ChatGPT 智能聊天机器人程序 All In One13.how to config `node.js` version in vercel All In One14.Node.js & file system & async await & forEach bug All In One15.Microsoft & Node.js All In One16.Node.js fs API docs All In One17.macOS brew uninstall node.js All In One18.nvm & grep filter out only Node.js Latest LTS versions All In One19.Node.js ORM All In One20.How to exit Node.js REPL environment All In One21.Node.js 面试题 All In One22.How to custom your own Node.js Docker Image All In One23.Node.js 中 CommonJS 模块 exports 与 module.exports 实现原理剖析 All In One24.change nvm default Node.js version All In One25.Node.js path All In One26.如何使用 Node.js 服务器控制浏览器下载文件还是预览文件 All In One27.Node.js server render Blob file All In One28.how to exit terminal from a Node.js program All In One29.Node.js CommonJS __dirname ../ relative path bug All In One30.Node.js import ESM module error All In One31.TypeScript & Node.js crawler All In One32.Node.js process All In One33.autoprefixer: ignore next not work bug All In One34.如何判断当前 js 代码是运行在浏览器还是node环境中 All In One35.Node.js project auto open localhost with ip address All In One36.Node.js & TypeScript error All In One37.Node.js & child_process All In One38.cross-env & shelljs & set custom node.js env All In One39.nvm set system node version All In One40.Node.js 设置内存大小 All In One41.Node.js & ES Modules & TypeScript All In One42.Node.js & TS & VSCode error All In One43.Node.js & Express server support CORS44.Node.js in action All In One45.Node.js & Express.js Server get binary data All In One46.node.js & webpack proxy bug47.Node.js 实战(第2版)All In One48.node.js ECONNRESET error49.node.js cli downloader50.Node.js 文件上传 cli tools51.Node.js 实战 & 最佳 Express 项目架构52.cnblogs blogs backup & node.js crawler53.Node.js 返回 JSON 数据54.node.js 怎么扩大默认的分配的最大运行内存55.Node.js fs API _dirname & _filename & path All In One56.Node.js Backend Developer
57.Node.js require 模块加载原理 All In One
58.node.js module.exports & exports & module.export all in one59.Nest.js tutorials All In One60.PM2 & nodemon & Node.js Deamon All In One61.node.js 中间件62.node --experimental-modules & node.js ES Modules63.Express All In One64.Node.js & ES Modules & Jest65.how to config custom process.env in Node.js All In One66.一个最简单 node.js 命令行工具67.Node.js delete directory & file system All In One68.Node.js Learning Paths All In One69.Deno 1.0 & Node.js All In One70.Node.js & ORM & ODM All In One71.Node.js & BFF & FaaS72.Node.js 如何处理一个很大的文件 All In One73.Node.js RESTful API & EJS template engine All In One74.Node.js & ES modules & .mjs75.Node.js & 页面截图 & 生成画报 All In One76.Node.js & LTS77.Node.js Debugger All In One78.VSCode & Node.js & debugger & inspector79.玩转 Node.js & React 系列教程:graphql 教程80.Node.js & module.exports & exports All In One81.Node.js & process.env & OS Platform checker82.How to write a Node.js cli tools step by step tutorials All In One83.node.js & read argv84.Node.js & create file All In One85.Docker & Node.js86.NAIO & Node.js All In One87.node.js & fs & file read & file write All In One88.node.js & Unbuntu Linux & nvm & npm89.Node.js & SSR90.nodejs & docker91.Node.js & Koa.js All In One92.mongodb & vue & node.js93.Node.js & module system94.Node.js Spider95.How to Install Multiple Versions of Node.js on the same Server(PC) All In One96.how to updating Node.js and npm97.Node.js : npm-install 教程98.node.js && npm commands99.node.js <=> Command Line Options100.有关 Node.js, npm 和 modules 安装及使用方法的个人总结!All In OneNode.js require 模块加载原理 All In One
require 加载模块,搜索路径
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2020-10-01
* @modified
*
* @description
* @difficulty Easy Medium Hard
* @complexity O(n)
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/
const log = console.log;
function Module(id, parent) {
this.id = id;
this.path = id;
// path = (id - filename.js)
this.paths = [];
// [paths1, parent path, ..., root path]
// paths1 = (id - filename.js) + node_modules
this.exports = {};
this.parent = parent;
this.filename = null;
this.loaded = false;
this.children = [];
}
// ✅ 在原型上添加只有实例才可以访问的实例方法 require
Module.prototype.require = function(path) {
// 调用构造函数的静态方法 Module._load
return Module._load(path, this);
};
// 用模块的绝对路径,那么除了 module.filename
// Node 还提供一个 require.resolve 方法,供外部调用,用于从模块名取到绝对路径
require.resolve = function(request) {
return Module._resolveFilename(request, self);
};
Module.prototype.load = function(filename) {
var extension = path.extname(filename) || '.js';
if (!Module._extensions[extension]) {
extension = '.js';
}
Module._extensions[extension](this, filename);
this.loaded = true;
};
// 首先,将模块文件读取成字符串;
// 然后剥离 utf8 编码特有的 BOM 文件头,最后编译该模块.
Module._extensions['.js'] = function(module, filename) {
var content = fs.readFileSync(filename, 'utf8');
module._compile(stripBOM(content), filename);
};
Module._extensions['.json'] = function(module, filename) {
var content = fs.readFileSync(filename, 'utf8');
try {
module.exports = JSON.parse(stripBOM(content));
} catch (err) {
err.message = filename + ': ' + err.message;
throw err;
}
};
Module.prototype._compile = function(content, filename) {
var self = this;
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
}
// 👍 上面的代码基本等同于下面的形式
// (function (exports, require, module, __filename, __dirname) {
// // 模块源码
// });
Module._load = function(request, parent, isMain) {
// 计算绝对路径
var filename = Module._resolveFilename(request, parent);
// 第一步:如果有缓存,取出缓存
var cachedModule = Module._cache[filename];
if (cachedModule) {
return cachedModule.exports;
}
// 第二步:是否为内置模块
if (NativeModule.exists(filename)) {
return NativeModule.require(filename);
}
// 第三步:生成模块实例,存入缓存
var module = new Module(filename, parent);
// ✅ 实例化 module
Module._cache[filename] = module;
// 第四步:加载模块
try {
module.load(filename);
hadException = false;
} finally {
if (hadException) {
delete Module._cache[filename];
}
}
// 第五步:输出模块的exports属性
return module.exports;
}
// Module._cache = [];
Module._resolveFilename = function(request, parent) {
// 第一步:如果是内置模块,不含路径返回
if (NativeModule.exists(request)) {
return request;
}
// 第二步:确定所有可能的路径
var resolvedModule = Module._resolveLookupPaths(request, parent);
var id = resolvedModule[0];
var paths = resolvedModule[1];
// 第三步:确定哪一个路径为真
var filename = Module._findPath(request, paths);
if (!filename) {
var err = new Error("Cannot find module '" + request + "'");
err.code = 'MODULE_NOT_FOUND';
throw err;
}
return filename;
};
Module._resolveLookupPaths = function(request, parent){
// 列出可能的路径
}
// 确认哪一个路径为真
Module._findPath = function(request, paths) {
// 列出所有可能的后缀名:.js,.json, .node
var exists = Object.keys(Module._extensions);
// 如果是绝对路径,就不再搜索
if (request.charAt(0) === '/') {
paths = [''];
}
// 是否有后缀的目录斜杠
var trailingSlash = (request.slice(-1) === '/');
// 第一步:如果当前路径已在缓存中,就直接返回缓存
var cacheKey = JSON.stringify({request: request, paths: paths});
if (Module._pathCache[cacheKey]) {
return Module._pathCache[cacheKey];
}
// 第二步:依次遍历所有路径
for (var i = 0, PL = paths.length; i < PL; i++) {
var basePath = path.resolve(paths[i], request);
var filename;
if (!trailingSlash) {
// 第三步:是否存在该模块文件
filename = tryFile(basePath);
if (!filename && !trailingSlash) {
// 第四步:该模块文件加上后缀名,是否存在
filename = tryExtensions(basePath, exists);
}
}
// 第五步:目录中是否存在 package.json
if (!filename) {
filename = tryPackage(basePath, exists);
}
if (!filename) {
// 第六步:是否存在目录名 + index + 后缀名
filename = tryExtensions(path.resolve(basePath, 'index'), exists);
}
// 第七步:将找到的文件路径存入返回缓存,然后返回
if (filename) {
Module._pathCache[cacheKey] = filename;
return filename;
}
}
// 第八步:没有找到文件,返回false
return false;
};
module.exports = Module;
// 模块的加载实质上
// 注入 exports、require、module 三个全局变量;
// 然后执行模块的源码;
// 最后将模块的 exports 变量的值输出.
exports = module.exports
✅ module.exports 与 exports 指向同一个Object 引用
https://blog.tableflip.io/the-difference-between-module-exports-and-exports
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2020-10-01
* @modified
*
* @description
* @difficulty Easy Medium Hard
* @complexity O(n)
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/
const log = console.log;
// ✅ module.exports 与 exports 指向同一个Object 引用
// SyntaxError: Identifier 'module' has already been declared
// module = {
// exports: {},
// //others
// };
// // {exports: {…}}
// module.exports;
// // {}
// exports = module.exports;
// // {}
// exports.a = `a`;
// module.exports.a = `aa`;
// module.exports.b = `b`;
// log(`exports =`, exports);
// log(`module.exports =`, module.exports);
/*
exports = { a: 'aa', b: 'b' }
module.exports = { a: 'aa', b: 'b' }
*/
const test = () => {
const module = {
exports: {},
//others
};
// {exports: {…}}
module.exports;
// {}
const exports = module.exports;
// {}
exports.a = `a`;
module.exports.a = `aa`;
module.exports.b = `b`;
log(`exports =`, exports);
log(`module.exports =`, module.exports);
}
test();
/*
exports = { a: 'aa', b: 'b' }
module.exports = { a: 'aa', b: 'b' }
*/
node_modules
paths: [
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/node_modules',
'/Users/xgqfrms-mbp/Documents/node_modules',
'/Users/xgqfrms-mbp/node_modules',
'/Users/node_modules',
'/node_modules'
]
➜ module.exports git:(master) ✗ node test.js
exports = {}
module.exports = [Function: app] { test: 'abc' }
module Module {
id: '/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports/app.js',
path: '/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports',
exports: [Function: app] { test: 'abc' },
parent: Module {
id: '.',
path: '/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports',
exports: {},
parent: null,
filename: '/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports/test.js',
loaded: false,
children: [ [Circular] ],
paths: [
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/node_modules',
'/Users/xgqfrms-mbp/Documents/node_modules',
'/Users/xgqfrms-mbp/node_modules',
'/Users/node_modules',
'/node_modules'
]
},
filename: '/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports/app.js',
loaded: false,
children: [],
paths: [
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.exports/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/node_modules',
'/Users/xgqfrms-mbp/Documents/node_modules',
'/Users/xgqfrms-mbp/node_modules',
'/Users/node_modules',
'/node_modules'
]
}
app = [Function: app] { test: 'abc' } undefined
args = []
test = abc
path & paths
function Module(id, parent) {
this.id = id;
this.path = path;// id - filename.js
this.paths = [path, parent path, ..., root path];
this.exports = {};
this.parent = parent;
this.filename = null;
this.loaded = false;
this.children = [];
}
module.exports = Module;
var module = new Module(filename, parent);
demo
const log = console.log;
// module.js
log('module.id: ', module.id);
log('module.exports: ', module.exports);
log('module.parent: ', module.parent);
log('module.filename: ', module.filename);
log('module.loaded: ', module.loaded);
log('module.children: ', module.children);
log('module.paths: ', module.paths);
log(`\nmodule =`, module);
/*
$ node module.js
module.id: .
module.exports: {}
module.parent: null
module.filename: /Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.js
module.loaded: false
module.children: []
module.paths: [
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/node_modules',
'/Users/xgqfrms-mbp/Documents/node_modules',
'/Users/xgqfrms-mbp/node_modules',
'/Users/node_modules',
'/node_modules'
]
*/
/*
module = Module {
id: '.',
path: '/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system',
exports: {},
parent: null,
filename: '/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/module.js',
loaded: false,
children: [],
paths: [
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/module-system/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/src/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/learn-node.js-by-practice/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/node_modules',
'/Users/xgqfrms-mbp/Documents/node_modules',
'/Users/xgqfrms-mbp/node_modules',
'/Users/node_modules',
'/node_modules'
]
}
*/
CommonJS
https://en.wikipedia.org/wiki/CommonJS
require() function & module.exports (alias, exports)
default exports
module.exports = xxx;
module.exports.xxx = xxx;
module.exports = {
xxx: xxx,
};
"use strict";
/**
*
* @author xgqfrms
* @license MIT
* @copyright xgqfrms
* @created 2020-10-01
* @modified
*
* @description
* @difficulty Easy Medium Hard
* @complexity O(n)
* @augments
* @example
* @link
* @solutions
*
* @best_solutions
*
*/
const log = console.log;
const app = (datas = [], debug = false) => {
log(`datas =`, datas)
};
// 👎❌
// exports = app;
// ✅ module export (const { app, } = require(`./app`);)
// exports.app = app;
// 👍✅ default export (const app = require(`./app`);)
module.exports = app;
// ✅
// module.exports.app = app;
// ✅
// module.exports = {
// app,
// };
module.exports 覆盖 exports
const log = console.log;
log(`exports`, exports);
log(`module`, module);
// TypeError: Cannot set property 'a' of undefined
// module.export.a = 1;
// module.export.b = 2;
// module.export.c = 3;
// module.export.d = 4;
// 自定义属性 umd ✅
module.umd = {
a: 1,
b: 2,
c: 3,
d: 4,
};
// 自定义属性 export ✅
module.export = {
a: 1,
b: 2,
c: 3,
d: 4,
};
exports.a = 11;
exports.b = 22;
exports.c = 33;
exports.d = 44;
// module.exports 覆盖 exports
module.exports = { c: 333 };
module.exports.d = 444;
log(`\nexports`, exports);
log(`module`, module);
/*
exports { a: 11, b: 22, c: 33, d: 44 }
module Module {
id: '.',
path: '/Users/xgqfrms-mbp/Documents/GitHub/umd-npm-package/src',
exports: { c: 333, d: 444 },
parent: null,
filename: '/Users/xgqfrms-mbp/Documents/GitHub/umd-npm-package/src/export.js',
loaded: false,
children: [],
paths: [
'/Users/xgqfrms-mbp/Documents/GitHub/umd-npm-package/src/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/umd-npm-package/node_modules',
'/Users/xgqfrms-mbp/Documents/GitHub/node_modules',
'/Users/xgqfrms-mbp/Documents/node_modules',
'/Users/xgqfrms-mbp/node_modules',
'/Users/node_modules',
'/node_modules'
],
umd: { a: 1, b: 2, c: 3, d: 4 },
export: { a: 1, b: 2, c: 3, d: 4 }
}
*/
https://nodejs.org/api/modules.html#modules_exports_shortcut
refs
http://www.ruanyifeng.com/blog/2015/05/require.html
Module System
https://www.cnblogs.com/xgqfrms/p/9493550.html
node --experimental-modules & node.js ES Modules
https://www.cnblogs.com/xgqfrms/p/13591967.html
©xgqfrms 2012-2025
www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/13772016.html
未经授权禁止转载,违者必究!
合集:
Node.js
标签:
require
, Node.js
, 模块加载原理
, exports
, module.exports
, Module System
, default exports
, node_modules
, path & paths
, JavaScript
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
2016-10-05 gulp error handler
2015-10-05 Top 10 Best Free PHP Frameworks of 2015
2015-10-05 路由协议 All In One