data: URL Worker 八年都能直接读 localStorage,Chrome 157 用 opaque origin 把它锁死了
写过 Web Worker 的人,大概都知道 Worker 里拿不到 localStorage。但 Chrome 149 开始,这个「拿不到」变成了字面意思——Worker 不再和主页面共享同一个 origin,而是被分配了一个独立的 opaque origin,连 localStorage、cookies、IndexedDB 都读不到了。更关键的是:企业 IT 用来临时维持旧行为的那扇后门(DataUrlInWebWorkerOpaqueOriginEnabled 策略),将在 Chrome 157 彻底移除,届时所有依赖旧行为的内部应用将被迫迁移。
发生了什么:旧行为 vs 新行为
Chrome 149 之前(旧行为):
// index.html(同源页面)
localStorage.setItem('token', 'abc123');
const worker = new Worker('data:text/javascript,postMessage(localStorage.getItem("token"))');
// Worker 继承了主页面的 origin → 可以访问 localStorage
Chrome 149~156(过渡期):默认行为变为 opaque origin,但企业可配 DataUrlInWebWorkerOpaqueOriginEnabled=0 策略回退。
Chrome 157 之后(新行为):
// 主页面的 localStorage token='abc123'
const worker = new Worker('data:text/javascript,postMessage(localStorage.getItem("token"))');
// Worker 有独立 opaque origin → localStorage.getItem("token") 返回 null
// IndexedDB/cookies 同样访问不到
这不只是 Chrome 自己的决定——它是 WHATWG HTML 规范 的要求。Firefox 和 Safari 早已如此,Chrome 是在补全合规性。
为什么有 8 个月的过渡窗口
这次变更有破坏性。Chrome 团队很清楚:许多内部企业应用用 data: URL 方式嵌入 Worker 脚本,目的是想在 Worker 里直接读主页面存的认证 token、用户偏好等数据。直接切断会直接 break 一批业务。
所以 Chrome 149 引入了临时策略 DataUrlInWebWorkerOpaqueOriginEnabled:
- Enabled(默认):新安全行为,Worker 独立 opaque origin
- Disabled:回退到旧行为,Worker 继承创建页面的 origin
企业 IT 有 8 个月时间(149→157)逐步迁移代码,而不是被迫在某个版本升级后立即崩溃。
但这扇后门只在 149~156 期间有效。Chrome 157 将移除该策略,届时无论是否配置,Worker 都强制 opaque origin,不再有任何回退手段。
怎么判断你的代码是否受影响
如果你的代码符合以下任一模式,就需要注意:
// 场景1:data: URL Worker 直接读 localStorage
const worker = new Worker(
'data:text/javascript,self.onmessage=()=>postMessage(localStorage.getItem("user"))'
);
// 场景2:SharedWorker 用 data: URL 跨标签共享状态
const shared = new SharedWorker(
'data:text/javascript,self.onconnect=function(e){...}'
);
// 场景3:Worker 内部写 IndexedDB
const worker = new Worker(
'data:text/javascript,onmessage=e=>{ let db=indexedDB.open("app"); }'
);
检查方法:在 Chrome 149+ 环境打开 DevTools,在 Worker 里跑一行 console.log(localStorage.length),如果返回 0 就说明已经受影响。
迁移方案
方案一:通过 postMessage 主动传参(推荐)
不再让 Worker 自己去读,而是主页面主动把需要的数据通过 postMessage 传进去:
// 主页面
const token = localStorage.getItem('token');
const worker = new Worker('/worker.js');
worker.postMessage({ token }); // 主动传,不依赖 Worker 自己读
// worker.js
self.onmessage = (e) => {
const { token } = e.data;
// 用 token 做事
};
方案二:用 importScripts 替代 data: URL
如果 Worker 逻辑复杂,用独立 JS 文件 + importScripts 替代 data: URL,可以更干净地控制脚本来源和缓存。
方案三:MessageChannel 做双向通信桥
如果 Worker 和主页面需要双向状态同步,用 MessageChannel 建立专用通道:
const channel = new MessageChannel();
// 主页面端
parentPort.postMessage({ type: 'get-token' });
// 主页面的 message handler 根据请求类型读取 localStorage 再发回去
降级策略:检测 + 优雅提示
Chrome 157 之后策略移除,无法再回退。但可以在代码里做 Feature Detection:
if (typeof Worker !== 'undefined') {
const testWorker = new Worker('data:text/javascript,void 0');
let canAccessStorage = false;
testWorker.onmessage = () => { canAccessStorage = true; };
testWorker.postMessage('test');
setTimeout(() => {
if (!canAccessStorage) {
console.warn('当前环境 data: URL Worker 无法访问 localStorage,请使用 postMessage 传参');
}
}, 100);
}
时间节点速记
| 版本 | 行为 |
|---|---|
| Chrome 148 及之前 | Worker 继承创建页面 origin(可访问 localStorage) |
| Chrome 149 | 默认 opaque origin;DataUrlInWebWorkerOpaqueOriginEnabled 策略可临时回退 |
| Chrome 157 | 策略移除,强制 opaque origin,无回退 |
如果你是企业 IT 管理员:Chrome 157 预计在 2026 年第四季度 稳定版发布,迁移窗口只剩几个月。
如果你是前端开发者:现在就去搜一下项目里有没有 new Worker('data: 这类写法,有的话尽快改成 postMessage 主动传参,别等政策窗口关闭后被动 hotfix。
评论区
登录后可评论。