深入浅出nodejs里说,“从缓存加载的优化策略是的二次引入时不需要路径分析,文件定位和编译执行过程”, 不用编译可以理解,但为什么不用文件定位,路径分析呢?我看了下缓存的路径都是文件的真实路径,比如"E:\projects\node\test\nodemodules\express\index.js", 第二次require(“expess”)如果不路径分析和文件定位,是如何直接找到这个路径的缓存的呢
都已经缓存下来了当然不用再去找一遍了
@dislido 但是它是如何找到缓存的呢,我看到require里储存了缓存对应的真实路径,感觉应该根据真实路径找缓存吧,那找到真实路径应该要定位和分析路径啊
require.cache里已经包含了使用这个模块所需的一切,查找这个缓存的过程和你访问一个普通对象的属性是一样的 只有第一次require这个模块的时候才会通过路径去加载,之后的require只是返回最初加载的那个模块的exports对象而已
@dislido 也就是说是需要定位和分析的。
@bluedrinker 因为require.cache的结构是这样的
{
'F:\\test\\test.js': Module { },
'F:\\test\\test2.js': Module { }
}
所以要用真实路径来获取缓存里的模块 只要计算出来这个路径就可以了,并不需要通过这个路径去找文件,这个路径只是一个id
@dislido 嗯,对的
楼上解释的也不完全对,在根据 require 的入参定位文件全路径的时候也会做缓存
// lib/module.js
Module._resolveFilename = function(request, parent, isMain, options) {
//...
// Module._findPath 会优先从缓存读取
var filename = Module._findPath(request, paths, isMain);
//...
}
Module._findPath 大致逻辑:
Module._findPath = function(request, paths, isMain) {
if (path.isAbsolute(request)) {
paths = [''];
} else if (!paths || paths.length === 0) {
return false;
}
// 根据 require 的入参组装的缓存 key
var cacheKey = request + '\x00' +
(paths.length === 1 ? paths[0] : paths.join('\x00'));
// 如果已经定位过文件的全路径,则存在缓存,直接返回缓存的全路径
var entry = Module._pathCache[cacheKey];
if (entry)
return entry;
// 如果没有缓存,则按照正常的方式组合 paths 定位具体文件全路径
//...
}
所以深入浅出的书里描述的并没有问题
@hyj1991 感谢指正