简单require实现
发布于 4 年前 作者 zhsonga 4085 次浏览 来自 问答

require方法主要实现的功能

1.module的上下文独立 2.module的上下文缓存 3.根据路径从当前目录下加载文件,从nodemodules中加载模块,原声模块的加载

require.js实现

const path = require('path')
const fs = require('fs')
const mymodule = { 
    catch: {} //用于做module的缓存  require不会重复的读取同一个文件 优先从缓存中读取
}
function myRequire(modulePath) {

    let file = path.join(__dirname, modulePath)
    const exports = mymodule.exports = {}  // cnode大佬有写关于它的文章哦   https://cnodejs.org/topic/52308842101e574521c16e06

    if (mymodule.catch[file]) {
        eval(mymodule.catch[file]) 
        return mymodule.exports 
    }
    // if (mymodule.catch[file]) {  
    //     return mymodule.catch[file]
    // }
    const content = fs.readFileSync(file, 'utf-8')
    console.log(content)
    let res = eval(content)
    // mymodule.catch[file] = res  //不能缓存eval执行完的内容 缓存读取的同一个对象导致module不是独立的上下文
    mymodule.catch[file] = content //只缓存读取的文件内容
    console.log(mymodule, res)
    return mymodule.exports
}
let aa = myRequire('./test.js')
let bb = myRequire('./test.js')
aa.bbb = 777
console.log(aa, bb)

test.js

class aa {
    constructor() {
        this.a = 1
        console.log(this)
    }
}

mymodule.exports = { a: 66 }

那么热更新 热重载等功能的实现 是不是对module的缓存进行处理就可以了呢?

简单猜想:监听到文件发生变化之后 替换掉module的缓存内容 然后再不重启程序的前提下 释放旧模块的引用? 旧模块的引用如何处理呢? 大佬们 给点建议和思路QAQ

3 回复

我是这样做的. 监控文件变化,然后从父级开始逐级删除缓存,然后再重新加载缓存.

不知道其他大佬怎么做的,个人只是试了试这样可以在启动服务时,实现热更新,并没有深度研究,这其中是否有什么坑.

其实最麻烦的是引用模块的__dirname和__filename的实现,还有就是父子孙之间模块引用的关系,所以require里面才有一堆环状引用。 不过这种方法,简单用用来处理引用module的缓存还是不错的。顺便提个意见eval可以用new Function代替,这样作用域污染小些。

type: catch —> cache

回到顶部