如何解决JSDOM加载本地网页时localStorage报opaque origins错误的问题
解决方案
以下为3种可直接落地的解决方式,任选其一即可:
方式1:配置合法HTTP协议的url参数
该问题触发的核心原因是file://协议的URL默认生成的origin为null,将url参数替换为任意http/https开头的合法域名即可,不需要对应服务真实启动:
const { JSDOM } = require('jsdom'); const fs = require('fs'); const htmlContent = fs.readFileSync('./你的本地文件路径.html', 'utf-8'); const dom = new JSDOM(htmlContent, { url: 'http://localhost:3000', // 替换原file协议路径,origin会自动生成为http://localhost:3000 runScripts: 'dangerously', // 必须开启,否则页面内脚本不会执行 resources: 'usable' });
方式2:手动指定origin参数(兼容file协议url)
如果需要保留原file协议的url配置,可以直接通过origin参数手动指定合法值,该配置在JSDOM 16及以上版本支持:
const { JSDOM } = require('jsdom'); const fs = require('fs'); const htmlContent = fs.readFileSync('./你的本地文件路径.html', 'utf-8'); const dom = new JSDOM(htmlContent, { url: 'file:///本地文件的绝对路径.html', origin: 'http://localhost:3000', // 手动覆盖origin值,避免生成null runScripts: 'dangerously' });
方式3:模拟localStorage对象挂载
如果不需要真实的localStorage存储能力,可以手动实现模拟对象挂载到JSDOM的window上,完全绕开origin校验:
const { JSDOM } = require('jsdom'); const fs = require('fs'); // 简易localStorage模拟实现 class MockLocalStorage { #store = {}; getItem = (key) => this.#store[key] ?? null; setItem = (key, value) => this.#store[key] = String(value); removeItem = (key) => delete this.#store[key]; clear = () => this.#store = {}; } const htmlContent = fs.readFileSync('./你的本地文件路径.html', 'utf-8'); const dom = new JSDOM(htmlContent, { runScripts: 'dangerously' }); // 挂载模拟对象 dom.window.localStorage = new MockLocalStorage(); // 如有全局调用需求可额外挂载到global对象 global.localStorage = dom.window.localStorage;
注意事项
- 如果你是在Jest等测试框架中使用封装后的JSDOM,只需要在配置文件中添加
testURL: 'http://localhost'即可解决 - 所有需要执行页面内部脚本的场景,必须配置
runScripts: 'dangerously',否则页面逻辑不会触发也不会调用localStorage
内容的提问来源于stack exchange,提问作者Michiel de Vos
相关产品推荐
相关产品推荐

