【问题标题】:jsdom window cachingjsdom窗口缓存
【发布时间】:2026-01-19 16:10:01
【问题描述】:

在 express.js 中使用 jsdom.jsdom() 我创建了一个带有一些“基本”布局标记的文档,并将一些客户端库(例如 jQuery)附加到它的窗口。

最好只进行一次此设置。

问题是窗口文档的 DOM 会根据请求的 url 而改变。有没有办法让每个请求从同一个缓存窗口对象开始并增强它,还是必须在每个请求上从头开始设置?

【问题讨论】:

  • Zombie.js,内部使用jsdom,有fork方法。我认为它被宣传为解决与您相同的问题的一种方法,但我不知道它是如何做到的。

标签: dom express jsdom


【解决方案1】:

听起来您想要一个简单的 JavaScript 对象哈希?

var cache = Object.create(null); // avoids spurious entries for `hasOwnProperty` etc.

// Incoming request happens, assume `req.url` is available...

if (req.url in cache) {
    processDom(cache[req.url]);
} else {
    jsdom.env(req.url, function (err, window) {
        if (err) {
            // handle error
            return;
        }
        cache[req.url] = window;
        processDom(cache[req.url]);
    });
}

【讨论】:

  • 我记得"__proto__" 仍然是个问题
  • 在旧版本的 V8 中,是的。但不适用于所有其他引擎,或当前版本的 V8(包括稳定版 Chrome 中使用的版本)。
【解决方案2】:

我认为这是不可能的。当您使用 jsdom 构建器创建新文档时,您指定的任何自定义选项只会影响当前正在创建的文档。在此之后创建的任何其他文档都将依赖默认功能。

但是,您实际上可以修改这些默认功能——我想这就是您所追求的。在创建任何文档之前,您可以为以后的所有文档修改这些默认值:

require('jsdom').defaultDocumentFeatures = {
  FetchExternalResources   : ['script'], 
  ProcessExternalResources : false,
  MutationEvents           : false,
  QuerySelector            : false
}

阅读 jsdom 的README 可以了解每个选项的说明。

【讨论】:

  • 问题不在于更改 JSDOM 功能/选项。它是关于克隆/缓存创建的窗口对象以供重用。