You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript全局作用域添加document供Node.js模块通过require.js访问的问题

解决Node.js+TypeScript中用jsdom模拟浏览器全局对象的问题

我来帮你搞定这个问题!在Node.js环境里模拟浏览器的document和XMLHttpRequest确实需要正确配置jsdom,你的代码目前有几个关键调整点,下面一步步来解决:

1. 正确初始化jsdom并挂载全局对象

现在jsdom的API已经更新为使用JSDOM构造函数,而非直接调用jsdom()函数。另外,Node.js的全局对象是global(或更通用的globalThis),你需要把模拟的浏览器对象挂载到这里,才能让其他模块访问到:

// 若使用CommonJS规范(require)
const { JSDOM } = require('jsdom');

// 若使用ES模块(import)
// import { JSDOM } from 'jsdom';

// 创建DOM实例
const dom = new JSDOM('<!DOCTYPE html>');

// 挂载到全局对象
globalThis.document = dom.window.document;
globalThis.window = dom.window;
globalThis.XMLHttpRequest = dom.window.XMLHttpRequest;

用globalThis比直接用global更规范,它在Node.js和浏览器环境中都能生效,避免环境兼容问题。

2. 解决TypeScript的类型报错

你已经用到了index.d.ts,需要扩展Node.js的全局类型定义,让TypeScript识别新增的全局对象。在你的index.d.ts中添加以下内容:

declare global {
  namespace NodeJS {
    interface Global {
      document: Document;
      window: Window;
      XMLHttpRequest: typeof XMLHttpRequest;
    }
  }
}

// 必须添加这一行,确保文件被识别为TypeScript模块
export {};

这样TypeScript就不会再报错说document或window不存在了。

3. 确保加载顺序正确

一定要先执行jsdom的全局挂载代码,再加载那个依赖浏览器对象的node_module。如果模块在初始化时就会访问document或XMLHttpRequest,提前挂载才能避免报错。比如你的入口文件应该是这样的结构:

// 第一步:配置jsdom全局对象
const { JSDOM } = require('jsdom');
const dom = new JSDOM('<!DOCTYPE html>');
globalThis.document = dom.window.document;
globalThis.window = dom.window;
globalThis.XMLHttpRequest = dom.window.XMLHttpRequest;

// 第二步:加载依赖浏览器环境的模块
const targetModule = require('your-target-module');

// 之后再执行你的业务逻辑
targetModule.doSomething();

4. 额外优化建议

  • 有些模块会检查navigator对象来判断是否在浏览器环境,你可以额外挂载这个对象:
    globalThis.navigator = dom.window.navigator;
    
  • 如果遇到XMLHttpRequest的特殊兼容性问题,可以尝试使用xhr2库代替jsdom的模拟版本,不过jsdom的实现已经覆盖了大部分常规场景。

内容的提问来源于stack exchange,提问作者pedalpete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:40:59