ArcGIS JS API 5.0 ESM 双模块系统冲突解决方案

📅 2026/7/4 20:21:19
ArcGIS JS API 5.0 ESM 双模块系统冲突解决方案
ArcGIS JS API 5.0 ESM 双模块系统冲突解决方案ArcGIS JS API 5.0 ESM 双模块系统冲突解决方案一、问题描述二、问题原因2.1 核心原因AMD 与 ESM 模块系统混用2.2 具体场景还原2.3 为什么 SpatialReference.WGS84 也会出问题三、解决过程第 1 步尝试修复空间参考实例第 2 步添加 try-catch 回退第 3 步根治方案——统一为纯 ESM 系统四、解决方案4.1 核心操作移除 AMD 入口添加 Import Map4.2 修改资源引入方式4.3 Import Map 的关键作用4.4 完整对比ArcGIS JS API 5.0 ESM 双模块系统冲突解决方案一、问题描述在将 ArcGIS JS API 5.0 的测试页面从 AMD$arcgis.import迁移到 ESMimport ... from ...引入方式时页面运行时抛出以下类型检查错误[arcgis/core/core/accessorSupport/ensureTypes] Accessor#set Assigning an instance of arcgis.geometry.SpatialReference which is not a subclass of arcgis.geometry.SpatialReference进一步的链式错误还包括OperatorProject.js:3 Uncaught (in promise) TypeError: Cannot read properties of null (reading hasVCS)完整错误栈at OperatorProject.js:3:552630 at Kr (OperatorProject.js:3:553489) at Object.Qr [as create$3] (OperatorProject.js:3:552446) at e.createProjectionTransformation (projectionTransformation.js:3:924) at o.execute (projectOperator.js:3:231)这些错误的直接表现是空间参考坐标系对象类型不匹配投影引擎无法正常工作。二、问题原因2.1 核心原因AMD 与 ESM 模块系统混用问题的根源在于同一个页面同时存在两套模块加载系统它们各自维护独立的模块缓存导致同一个逻辑类如SpatialReference产生了两个不同的实例┌─────────────────────────────────────────────────────┐ │ 浏览器页面 │ │ │ │ ┌───────────────┐ ┌──────────────────────┐ │ │ │ core.js │ │ ESM 静态 import │ │ │ │ (AMD 系统) │ │ │ │ │ │ │ │ import Map from │ │ │ │ $arcgis │ │ ./5.0/ │ │ │ │ .import() │ │ arcgis/core/ │ │ │ │ │ │ Map.js │ │ │ └───┬────────────┘ └──────────┬───────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────┐ ┌──────────────────────┐ │ │ │ AMD 缓存 │ │ ESM 模块缓存 │ │ │ │ │ │ (浏览器原生) │ │ │ │ SpatialRef │ │ SpatialRef ←不同实例 │ │ │ │ erence (v1) │ │ erence (v2) │ │ │ └──────────────┘ └──────────────────────┘ │ │ │ │ v1 ! v2 → instanceof 检查失败 ❌ │ └─────────────────────────────────────────────────────┘2.2 具体场景还原测试页面contour_demo.html中的代码结构!-- 1. 加载 core.js引入 AMD 模块系统 --scripttypemodulesrc./5.0/core.js/script!-- 2. HTML 内使用 ESM 静态 import --scripttypemoduleimportSpatialReferencefrom./5.0/arcgis/core/geometry/SpatialReference.js;// .../script与此同时工具类ContourAnalysis.js内部asyncinit(){if(typeof$arcgis!undefined$arcgis.import){// ── AMD 路径因为 core.js 加载了$arcgis 存在──[SpatialReference]await$arcgis.import([arcgis/core/geometry/SpatialReference.js]);}else{// ── ESM 路径永远不会执行──constmodsawaitimport(arcgis/core/geometry/SpatialReference.js);SpatialReferencemods.default;}this._spatialReferencenewSpatialReference({wkid:4326});}冲突链路core.js加载 → 全局$arcgis可用 →ContourAnalysis.init()走 AMD 路径AMD 路径获取的SpatialReference类 → 存储在 AMD 模块缓存中页面script typemodule中import SpatialReference from ...→ 浏览器 ESM 模块缓存中两个SpatialReference是不同的类实例框架内部Accessor#set类型检查通过instanceof判断 →检查失败2.3 为什么 SpatialReference.WGS84 也会出问题SpatialReference.WGS84是一个静态 getter返回缓存的空间参考实例。由于该类本身来自 AMD 系统其内部缓存的 WGS84 实例携带的 VCS垂直坐标系属性可能为null导致投影引擎在调用createProjectionTransformation()时读取hasVCS失败。三、解决过程第 1 步尝试修复空间参考实例思路不依赖缓存单例SpatialReference.WGS84改为新建实例。SpatialReference.WGS84 → new SpatialReference({ wkid: 4326 }) sr.isWGS84 → sr.wkid ! 4326结果hasVCS错误依旧。说明问题不在空间参考对象本身而在投影引擎的模块系统一致性。第 2 步添加 try-catch 回退思路在投影调用外层加try-catch异常时手动用 Web Mercator 数学公式转换坐标。try{geompo.execute(geometry,this._spatialReference);}catch(e){// Web Mercator → WGS84 手动转换constR20037508.34;geom{rings:geometry.rings.map(rr.map(p{return[p[0]/R*180,180/Math.PI*(2*Math.atan(Math.exp(p[1]/R*Math.PI))-Math.PI/2),p[2]];}))};}结果绕过了投影引擎的hasVCS错误但紧接着触发了instanceof类型检查错误。验证了根因是双模块系统冲突。第 3 步根治方案——统一为纯 ESM 系统思路移除core.jsAMD 入口使$arcgis不可用强制所有模块走 ESM 路径。结果所有错误消失功能正常运行。手动回退代码也无需触发纯 ESM 下投影引擎本身工作正常。四、解决方案4.1 核心操作移除 AMD 入口- script typemodule src../../5.0/core.js/script添加 Import Mapscripttypeimportmap{imports:{arcgis/core/:../../5.0/arcgis/core/}}/script4.2 修改资源引入方式将$arcgis.import()调用替换为 ESM 静态import语句。AMD 方式修改前const[Map,SceneView,GraphicsLayer]await$arcgis.import([arcgis/core/Map.js,arcgis/core/views/SceneView.js,arcgis/core/layers/GraphicsLayer.js,]);ESM 方式修改后由于 import map 已将arcgis/core/映射为../../5.0/arcgis/core/直接使用裸路径即可importMapfromarcgis/core/Map.js;importSceneViewfromarcgis/core/views/SceneView.js;importGraphicsLayerfromarcgis/core/layers/GraphicsLayer.js;4.3 Import Map 的关键作用方面说明裸路径解析工具类内部import(arcgis/core/...)的动态导入依赖 import map 来解析裸模块标识符模块一致性静态import和动态import()通过 import map 解析到同一 URL → 浏览器 ESM 缓存返回同一实例部署灵活性无需修改工具类源码中的arcgis/core/前缀只需调整 HTML 中的 import map4.4 完整对比修改前修改后AMD 入口script typemodule srccore.js移除导入方式await $arcgis.import([...])import X from arcgis/core/X.js裸路径解析依赖 core.js 的 AMD 加载器Import Map模块系统AMD ESM 混用 ❌纯 ESM ✅模块实例两套缓存类不相等统一缓存类唯一投影引擎hasVCS: null崩溃正常工作