Vue2引入zimjs后DRACOLoader报createObjectURL执行失败错误
冲突根因
报错本质是@danzen/createjs(zimjs的强制运行时依赖)对全局浏览器API的非兼容污染:
@danzen/createjs内置了面向老旧浏览器的createObjectURLpolyfill,初始化时会无判断直接覆盖原生URL.createObjectURL方法,该polyfill仅支持早期非标准参数格式,无法识别Blob/File类型入参。- Three.js的
DRACOLoader加载DRACO解码Worker、wasm模块时,会将拉取到的二进制资源封装为Blob对象,调用原生URL.createObjectURL生成临时资源地址。被覆盖后的方法无法处理Blob参数,直接触发参数类型不匹配的重载错误。 - 注释
makeZIM()初始化逻辑时,createjs的polyfill不会执行,原生URL方法未被篡改,因此DRACOLoader可正常加载模型。
可行解决方法
方案1:缓存并恢复原生API(侵入性最低,优先选用)
在ZIM初始化逻辑前后手动备份、还原原生URL方法,不需要修改第三方依赖源码,也不影响两个库的正常功能,实现代码如下:
// 备份原生方法 const nativeCreateObjectURL = URL.createObjectURL; const nativeRevokeObjectURL = URL.revokeObjectURL; // 原有依赖引入与初始化逻辑 require('@danzen/createjs'); const makeZIM = require('zimjs'); const zim = makeZIM(); // 初始化完成后立即恢复原生API URL.createObjectURL = nativeCreateObjectURL; URL.revokeObjectURL = nativeRevokeObjectURL;
- ZIM仅在初始化阶段调用一次自定义polyfill做兼容检测,初始化完成后不再依赖该重写方法,恢复原生API不会影响ZIM的2D渲染能力。
- 该方案不需要调整组件加载逻辑,也不需要额外安装依赖。
方案2:构建阶段剔除polyfill代码
如果使用Vue CLI(基于webpack)构建项目,可通过构建配置在打包时移除createjs中重写URL方法的代码段,从根源避免全局污染:
- 先安装字符串替换loader:
npm install string-replace-loader --save-dev
- 在项目根目录的
vue.config.js中添加如下配置:
module.exports = { chainWebpack: config => { config.module .rule('drop-createjs-polyfill') .test(/@danzen[\\/]createjs.*\.js$/) .use('string-replace-loader') .loader('string-replace-loader') .options({ search: /URL\.createObjectURL\s*=[\s\S]*?;/g, replace: '' }) } }
- 重启开发服务或重新打包即可生效。
方案3:错峰加载两个组件
如果不想修改依赖引入或构建配置,可在父组件中控制两个子组件的挂载时机,等3D模型加载完成、DRACOLoader完成资源初始化后,再挂载2D组件:
<template> <div class="home-container"> <!-- 3D组件先挂载 --> <BaseModel @model-ready="is3DReady = true" /> <!-- 3D加载完成后再挂载2D组件 --> <Projection2D v-if="is3DReady" /> </div> </template> <script> import BaseModel from './components/BaseModel.vue'; import Projection2D from './components/Projection2D.vue'; export default { components: { BaseModel, Projection2D }, data() { return { is3DReady: false } } } </script>
- 需要在BaseModel.vue的GLTF模型加载完成回调中,触发
this.$emit('model-ready')事件。 - 该方案缺点是2D组件会延迟初始化,不适合需要两个组件同步渲染的场景。
验证结果
以上三种方案均可以解决该报错,DRACO压缩的glb模型加载、OrbitControls交互、ZIM 2D渲染功能均可正常运行,全程使用npm本地化依赖,不需要引入CDN资源。
内容的提问来源于stack exchange,提问作者mustafa00
相关产品推荐
相关产品推荐

