本地IIS部署ArcGIS API for JavaScript 4.13这件事我踩过不少坑也帮同事排过不少雷。说真的官方CDN在国外国内加载速度不稳定遇到内网环境更是彻底没戏。项目要上线了前端地图组件却白屏错误面板上一排排404那感觉可真不太好受。所以这次我把自己实操过的部署过程完整梳理一遍从下载解压、IIS站点配置到前端dojoConfig引用、常见报错排查全部走下来。目前这套方法在Windows Server IIS环境下反复验证过代码层面不需要做任何改动只要把引用路径指到本地就能让地图应用跑起来。1. 为什么要把API从CDN搬到本地IIS上1.1 官方CDN的硬伤速度、稳定、内网ArcGIS API for JavaScript官方推荐方式是直接引用https://js.arcgis.com/4.13/下的脚本。这个方式对个人开发或者海外项目没问题但落到国内生产环境就非常头疼。跨地域访问官方CDN体感上就是地图组件半天出不来瓦片请求都正常唯独加载esri那一堆模块时白屏卡顿。更重要的是很多政企项目网络环境是封闭的或者只允许访问白名单域名官方CDN根本不在白名单里整个地图功能直接就废了。本地部署的本质很简单把API相关的静态文件下载到你自己的服务器上通过IIS站点提供访问前端页面用本地URL去加载API脚本。这样加载速度由内网带宽决定稳定可控不依赖外网。同时也能配合应用系统做统一的代码版本管理API升级时只改服务器文件不需要改前端每一处引用。1.2 4.13版本为什么还算个“熟面孔”4.13是ArcGIS API for JavaScript 4.x系列里一个比较有代表性的版本它保留了基于Dojo的AMD模块加载机制但同时提供了大量现代GIS能力比如2D/3D一体化视图、场景视图、图层管理、WebMap加载、矢量切片渲染等。虽然现在官方已经发布到了4.2x但不少存量系统仍然锁在4.13上尤其是那些上线多年、验证过稳定性的业务系统不会轻易升级API主版本。理解4.13的加载机制是部署成功的关键。4.x版本的API不是一个大JS文件直接引入而是由一个加载器dojo loader按需加载各个模块。所以你部署的不仅是“某个js”而是一整个包含dojo、esri、dijit等依赖的静态目录树。任何一部分缺失都会导致初始化失败。2. 部署前的核心准备下载、解压与目录结构2.1 获取API压缩包的正确姿势ArcGIS API for JavaScript 4.13需要从官方下载中心获取通常是一个zip压缩包文件名类似arcgis_js_api_v413_api.zip。注意这个包和开发版SDK包不一样我们要的是“API”这个包不是完整开发包也不是文档包。解压之后会得到一个arcgis_js_api目录里面有两个子目录library和webpack部分版本可能有差异。我们真正关心的是library/4.13/这个目录里面包含了dojo/Dojo框架核心loader机制就在这里dijit/Dojo组件库API某些控件依赖它dojox/扩展库某些扩展模块需要esri/ArcGIS API的核心模块config/配置文件目录init.js这个文件是API的入口脚本package.json模块描述文件整个目录体积可能超过200MB因为包含了大量源码、样式、图片、字体资源。部署时这些文件都要原样保留不要“精简”否则容易造成模块加载异常。2.2 将资源搬运到服务器部署时我会先把解压好的arcgis_js_api整个目录复制到服务器的某个物理路径下。比如E:\WebSites\arcgis\arcgis_js_api。这算是个经验尽量用不含中文和空格的纯英文路径可以省掉很多编码问题。然后在IIS里新建一个站点或者复用现有站点下的虚拟目录/应用程序把物理路径指到这个目录。这里有一个选择如果你的ArcGIS API只服务一个WebGIS应用建议直接建独立站点分配80端口或独立域名。如果是要嵌入到现有门户系统下更省事的是在现有站点下建一个虚拟目录比如http://yourhost/arcgis/。两种方式我都跑过都可行。关键是前端代码里引用的路径必须和实际部署的URL一致。3. IIS站点配置实操一步步把API“跑”起来3.1 创建站点或虚拟目录以Windows Server IIS 8/10为例打开IIS管理器在左侧“网站”节点上右键选择“添加网站”。网站名称随便起比如“ArcGISAPI”。物理路径选到刚才那个arcgis_js_api所在目录。绑定类型默认“http”主机名可以留空端口建议单独用一个端口比如8090避免和现有应用冲突。更常见的做法是在已有站点下添加虚拟目录右键站点 → 添加虚拟目录 → 别名填arcgis→ 物理路径指向E:\WebSites\arcgis\arcgis_js_api。这样访问地址就是http://localhost:8090/arcgis/。两种方式后面配置MIME类型时操作位置有区别但原理是一样的。3.2 配置应用程序池这是一个很多新手容易忽视的环节。如果API部署在虚拟目录或独立站点中默认应用程序池使用的是“无托管代码”或“集成”模式这本身没问题。但要注意IIS在“集成”模式下可能对静态文件请求附加一些处理流程造成不必要的性能损耗。我的做法是针对ArcGIS API单独创建一个应用程序池.NET CLR版本选“无托管代码”托管管道模式用“集成”。虽然这个站点里根本没有.NET代码纯粹是静态文件托管但单独建池可以避免和其他站点互相影响。还要注意“应用程序池”设置右键 → 高级设置 → “启用32位应用程序”为False这对于64位环境下的静态文件服务没什么影响但能避免一些历史遗留问题。3.3 关键一步MIME类型配置ArcGIS API目录里存在大量不同类型的文件.js、.css、.json、.png、.svg、.woff、.ttf等。IIS默认的静态文件MIME列表通常能覆盖大部分常见类型但有时候会遇到.json或.woff没被识别的情况。一旦IIS识别不了文件类型就会直接返回404前端控制台会报类似Failed to load resource: the server responded with a status of 404 (Not Found)的错误。我建议直接在站点根目录的web.config里显式声明MIME类型configuration system.webServer staticContent remove fileExtension.json / mimeMap fileExtension.json mimeTypeapplication/json / remove fileExtension.js / mimeMap fileExtension.js mimeTypeapplication/javascript / remove fileExtension.svg / mimeMap fileExtension.svg mimeTypeimage/svgxml / remove fileExtension.woff / mimeMap fileExtension.woff mimeTypefont/woff / remove fileExtension.woff2 / mimeMap fileExtension.woff2 mimeTypefont/woff2 / /staticContent /system.webServer /configuration如果你部署的路径是网站根目录可以直接在IIS管理器的“MIME类型”功能中逐项添加但我用web.config有三个好处可随代码配置版本管理一次配置整个目录都生效避免IIS管理器界面在服务器上操作的额外耗时。3.4 确认静态资源能被访问配置完之后先别急着写前端代码先用浏览器验证服务器端是否正常释放文件。比如你部署的是http://localhost:8090/arcgis/那直接访问http://localhost:8090/arcgis/library/4.13/init.js如果浏览器里显示了一个JS文件内容就说明静态路径OK。如果404按这个顺序排查物理路径是不是写错。IIS里的站点或虚拟目录是否启动。端口是否被占用或防火墙是否放行。MIME类型是否覆盖到该文件扩展名。这一步确认通过服务器端的部署其实已经完成了九成。4. 前端页面接入本地APIdojoConfig是成败的关键4.1 理解4.13的加载机制4.13的API基于Dojo AMD加载器意思就是你在页面里先引入init.js或dojo.js然后dojo加载器根据你注册的包packages路径动态加载需要用到的模块。esri、dojo、dijit、dojox都是独立的包它们各自对应一个目录路径。官方CDN模式下一切路径都是写死的浏览器自己会从https://js.arcgis.com/4.13/去取。但本地部署时你必须替加载器指明每个包所在的位置。这就是dojoConfig的作用。4.2 引路径的两种写法第一种引用init.js配合全局dojoConfig!DOCTYPE html html head meta charsetutf-8 / title本地API测试/title style html, body, #viewDiv { padding: 0; margin: 0; height: 100%; width: 100%; } /style /head body div idviewDiv/div script var dojoConfig { async: true, packages: [ { name: esri, location: /arcgis/library/4.13/esri }, { name: dojo, location: /arcgis/library/4.13/dojo }, { name: dijit, location: /arcgis/library/4.13/dijit }, { name: dojox, location: /arcgis/library/4.13/dojox } ] }; /script script src/arcgis/library/4.13/init.js/script script require([ esri/config, esri/Map, esri/views/MapView ], function (esriConfig, Map, MapView) { var map new Map({ basemap: topo-vector }); var view new MapView({ container: viewDiv, map: map, zoom: 4, center: [104, 30] }); }); /script /body /html注意这里的location路径都是相对于当前域名的绝对路径。如果你的应用部署在根路径location: /arcgis/...是正确的。但如果是放在某个子路径下比如http://host/myapp/那么location要写绝对路径加上应用上下文比如/myapp/arcgis/library/4.13/esri或者直接用完整的http://host/arcgis/library/4.13/esri。第二种不配置packages直接引用官方推荐的写法其实更简洁script srchttp://localhost:8090/arcgis/library/4.13/init.js/script前提是 init.js 内部有一套默认包路径规则它会自动依据当前脚本位置来设定esri等包的位置。这是我后来才确认的4.x版本的init.js内置了baseUrl逻辑如果直接通过init.js引入它通常能根据自身所在目录推导出其他包的位置所以自定义dojoConfig不是必须的。但是我在实盘项目中强烈建议显式配置dojoConfig。原因在于如果你把API部署在虚拟目录或二级路径下某些情况下init.js的自动推导会出偏差而且一旦页面里还有其他Dojo组件比如dijit不显式配置包路径就容易冲突。显式声明多花两行代码但能减少后续排查的烦恼。4.3 basemap图源问题小心“白屏”上面示例代码用了basemap: topo-vector。在本地部署API后如果地图底图仍然请求官方在线服务https://basemaps.arcgis.com/...而你的内网访问不了这些域名那么地图照样呈现空白。这个问题和API部署本身无关但经常被误认为“部署没成功”。排查时分两步先确认view创建是否成功容器里有DOM节点再确认底图服务能否访问。如果内网禁止外网访问就得配置自己的瓦片服务或者使用内网可访问的底图服务地址。另外还要注意4.13的esriConfig里有一个portalUrl和portal的配置。如果你的应用需要连接内网Portal/GIS Server需要把默认的https://www.arcgis.com替换成内网Portal地址require([esri/config], function (esriConfig) { esriConfig.portalUrl http://你的内网Portal/gis; });否则即使API加载成功后续调用在线登录、要素服务分析等能力时依然会失败。4.4 多页面复用的公共配置如果项目里不止一个页面要用地图不要把dojoConfig复制粘贴到每个HTML。建议在脚本公共目录放一个dojo-config.js然后在页面中先引用它script src/js/dojo-config.js/script script src/arcgis/library/4.13/init.js/script公共JS里维护packages路径和全局配置日后如果要切换API版本只改这一处。这个方法我在多个系统里用过至少节省了每次升级时几十个页面的改动成本。5. 常见问题排查部署完成后最容易踩的坑5.1 控制台报错“define is not defined”这类错误的根因通常是dojo loader根本没加载成功。检查init.js或dojo.js是否被正确引入浏览器网络面板里这些脚本是不是200。更隐蔽的情况是你的公共页面CSS里加载了其他纯JS文件使用了非AMD方式的define()函数和dojo全局define产生冲突。解决方法是确保页面里只有dojo一个AMD加载器。5.2 图标、字体请求404部署后我遇到过地图控件上图标显示不出来、图标缺字或方块仔细排查是指向.svg或.woff2文件的请求404。根源就是前文说的MIME类型没配置全。IIS里的静态文件模块对未识别扩展名的默认处理是直接返回404不是返回到浏览器。把.svg、.woff、.woff2对应的MIME补上后问题就消失了。5.3 资源请求出现跨域错误如果你把API部署在http://serverA/arcgis/而前端页面放在http://serverB/并且直接引用了serverA的脚本浏览器控制台大概率会报跨域错误。4.x的模块加载存在跨域约束遇到这种情况不要急着改代码最稳妥的方案是让API和你应用同域或同主域名或者在后端统一用反向代理把/arcgis/代理到地图站点。这样前端写/arcgis/library/4.13/init.js浏览器看来是同源请求不自找麻烦。如果你确实需要跨域调用那要在IIS端开启CORS。在API站点web.config里加system.webServer httpProtocol customHeaders remove nameAccess-Control-Allow-Origin / add nameAccess-Control-Allow-Origin value* / add nameAccess-Control-Allow-Methods valueGET, POST, OPTIONS / add nameAccess-Control-Allow-Headers valueContent-Type, Authorization / /customHeaders /httpProtocol /system.webServer但CORS模式下还要处理dojo loader的跨域加载策略有些浏览器会要求脚本带跨域属性调试起来会比较麻烦所以优先还是同域部署。5.4 更新API版本后总是加载旧代码IIS对静态文件默认带缓存协商机制如果API文件更新后前端浏览器和服务端缓存仍然生效就可能加载到旧文件。实测中我遇到过地图组件已经改成新版本接口但某些模块请求还是旧内容以为是代码问题后来发现是缓存。解决办法有两条在web.config里对API目录添加缓存控制响应头禁止缓存system.webServer caching profiles add extension.js policyDisableCache kernelCachePolicyDisableCache / add extension.css policyDisableCache kernelCachePolicyDisableCache / /profiles /caching /system.webServer最见效的是在URL上加版本参数比如init.js?v20250101同时配合IIS的静态内容缓存设置。我一般会选择后者因为改文件名或加查询参数能精确控制发布节奏而全局禁用缓存会让浏览器每次加载都全量走网络浪费内网资源。5.5 路径大小写敏感问题Windows的IIS默认不区分路径大小写但前端代码、目录里的实际文件名有的是区分大小写的。比如esri目录下某个模块文件名是MapView.js但你require参数写的esri/view/MapView少写了一个大写V这种情况IIS不会帮忙纠正模块会加载失败。排查方法是直接访问那个拼接好的URL看是否存在。这类问题在内网的大写URL规范里很少见但一旦出现找起来非常隐蔽。6. 最后再分享一点经验部署这系列操作其实不复杂核心就三件事API文件原样放好、IIS把MIME配全、前端加载路径指对。但真正决定项目成败的往往是前后端衔接的细节比如底图服务、Portal地址、内网访问控制这些容易被人忽略的地方。我个人习惯是所有静态资源统一走一个域名比如API目录放在根下、应用页面也放在同一个站点的子目录这样模块加载路径、CORS、Cookie会话管理都少很多麻烦。还有一点IIS部署完成后记得把IIS的“目录浏览”关掉防止API源码被外部直接浏览安全审计也比较严。如果有条件生产环境最好多留一个API目录做版本回滚。比如arcgis_js_api/library/4.13保留不动新版本放4.14前端通过配置切版本出问题随时回退。这条经验帮我避免过两次上线失败。