NodeJs 手写简单实现 require 函数

前言:

        今天带给大家手写 require 函数代码,希望对大家有所帮助。


代码:

// 1. 现将 .a 文件转化为绝对路径
// 2. 读取这个文件,需要增加一个函数,函数内部需要返回 module.exports
// 3. 让函数执行
// 4. new Module 创建模块,根据文件名来创建, exports  id
//    --  module.load 加载模块
//    --  Module._extensions 代表一个对象,对象上放着很多处理方法
//    --  exports require  module  __filename
// 5. 最终返回 module.exports

let path = require("path");

let fs = require("fs");

let vm = require("vm");

function Module(id) {
	this.id = id;
	this.exports = {};
}

function resolveFileName(filename) {
	// 先将路径 转化为 绝对路径
	let r = path.resolve(__dirname, filename);
	// 需要看一下 文件路径是否存在,如果不存在,尝试添加 .js  和  .json 后缀
	let isExists = fs.existsSync(r);
	if (isExists) {
		return r;
	} else {
		let keys = Object.keys(Module._extensions);
		for (let i = 0; i < keys.length; i++) {
			let ext = keys[i];
			let tryFileName = r + ext;
			if (fs.existsSync(tryFileName)) {
				return tryFileName;
			}
		}
		throw new Error("module not found!");
	}
}

function tryModuleLoad(module) {
	// 获取文件的后缀名
	let extname = path.extname(module.id); // a.js
	Module._extensions[extname](module); // 不同后缀执行不同的加载逻辑
}

let wrapper = [
	"(function(exports,require,module,__filename,__dirname){",
	"\n})",
];
Module._extensions = {
	".js"(module) {
		let scripts = fs.readFileSync(module.id, "utf8");
		let fnStr = wrapper[0] + scripts + wrapper[1];
		let fn = vm.runInThisContext(fnStr);
		let exports = module.exports; // exports 和 module.exports
		// 不能直接改变 exports 他是不会影响 module.exports 的
		fn.call(
			exports,
			exports,
			req,
			module,
			module.id,
			path.dirname(module.id)
		);
	},
	".json"(module) {
		let scripts = fs.readFileSync(module.id, "utf8");
		try {
			module.exports = JSON.parse(scripts);
		} catch (err) {
			console.log("转换 失败!", err);
		}
	},
};
Module._cache = {};

function req(filename) {
	let id = resolveFileName(filename);
	let cacheModule = Module._cache[id];
	if (cacheModule) {
		console.log("缓存了");
		return cacheModule.exports;
	}
	let module = new Module(id);
	// 缓存模块
	Module._cache[id] = module;
	// 加载这个模块
	tryModuleLoad(module);
	return module.exports;
}

let str = req("./a");

let strr = req("./a");

console.log(req("./a.json"));

console.log(str, strr);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

靖凡无所畏惧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值