- node中require引入模块的过程
// require-mod.js
console.log("require", require.toString());
const { Module } = require("module");
// console.log("Module require", Module.prototype.require.toString());
// console.log("Module._load", Module._load.toString());
// console.log("module.load", module.load.toString());
// console.log("Module._extensions", Module._extensions[".js"].toString());
// console.log("module._compile", module._compile.toString());
现在就可以开启 nodemon require-mod.js 去看下代码实现了
- require手写代码
const { existsSync, readFileSync } = require("node:fs");
const vm = require("node:vm");
const { extname, dirname, resolve } = require("node:path");
const wrap = (content) => {
return (
"(function(exports,require,module,__filename,__dirname,){ " + content + "})"
);
};
const safeWrap = (filename, content, mod) => {
return vm.runInThisContext(content, {
filename,
});
};
const makeRequireFunction = (mod, redirects) => {
let require;
if (redirects) {
// todo
} else {
require = (path) => {
return mod.require(path);
};
}
const resolve = () => {};
require.resolve = resolve;
const paths = () => {};
require.paths = paths;
require.extensions = Module._extensions;
require.cache = Module._cache;
return require;
};
class Module {
constructor() {
this.id = "";
this.exports = {};
}
static _cache = {};
static _extensions = {
[".js"](mod) {
const content = readFileSync(mod.id, "utf-8");
mod._compile(content, mod.id);
},
[".json"](mod) {
// todo
},
[".node"](mod) {
// todo
},
};
static _load(filePath) {
const abFilePath = resolve(dirname(filePath), filePath);
const modCache = Module._cache[abFilePath];
if (modCache) return modCache.exports;
if (!existsSync(abFilePath)) return;
const mod = new Module(abFilePath);
mod.id = abFilePath;
mod.load(abFilePath);
Module._cache[abFilePath] = mod;
return mod.exports;
}
load(filePath) {
const extName = extname(filePath);
Module._extensions[extName](this);
this.loaded = true;
}
_compile(content, filename) {
const wrapperContent = wrap(content);
const compiledWrapper = safeWrap(filename, wrapperContent);
const exports = this.exports;
const dirName = dirname(filename);
const require = makeRequireFunction(this);
compiledWrapper.call(this, exports, require, this, filename, dirName);
}
}
const requireNew = (filePath) => {
return Module._load(filePath);
};
const aaa = requireNew("./mmm.js");
console.log("aaa666666", aaa);
console.log("requireNew", module.require.toString());