@supermapgis/vite-plugin-loadsdk
v1.0.0
Published
Vite 插件,用于在 Vite 项目中集成 @supermapgis/clientx 或 @supermapgis/iclient3d。通过 target 参数切换目标包。提供以下功能:1) 开发/预览服务器静态资源代理(wasm/worker/图片等);2) 构建后自动复制运行时静态资源到产物目录(支持 glob 过滤);3) 自动配置 resolve.mainFields 和 optimizeDeps,支持 SourceRelease 源码按需加载与 tree-shaking,同时预打包 CJS 依
Readme
@supermapgis/vite-plugin-loadsdk
用于在 Vite 项目中一键集成 @supermapgis/clientx 或 @supermapgis/iclient3d 三维 GIS SDK 的官方 Vite 插件。
为什么需要这个插件
@supermapgis/clientx / @supermapgis/iclient3d 是复杂的 WebGL 三维 GIS SDK,其 NPM 包包含两部分:
- ESM 模块代码(
SourceRelease/):供打包器按需引入和 tree-shaking - 运行时静态资源(
Build/<assetsDirName>/):WASM 文件、Worker 脚本、纹理图片、Widget CSS 等
直接在 Vite 项目中使用会面临以下问题:
- SDK 运行时通过
window.SUPERMAP3D_BASE_URL定位静态资源,需手动设置且易出错 - dev 模式下
/ClientX/xxx.wasm等请求需映射到node_modules,Vite 默认不提供 npm run build后dist/需要包含静态资源,否则部署后页面 404- Widget CSS 需手动引入
- 依赖树包含 CJS 模块(如
lodash.clonedeep),浏览器原生 ESM 无法直接使用 draco3d等库引用了 Node.jsfs模块,产生 "Module fs has been externalized" 警告
本插件自动完成以上全部工作,用户只需:
import * as ClientX from '@supermapgis/clientx';即可正常使用,无需任何手动配置。
安装
npm install @supermapgis/vite-plugin-loadsdk @supermapgis/clientx注意: 需同时在项目根目录
package.json中配置overrides强制依赖版本:"overrides": { "@zip.js/zip.js": "2.7.57", "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz" }
快速开始
// vite.config.js
import { defineConfig } from 'vite';
import SuperMapLoadSDKVitePlugin from '@supermapgis/vite-plugin-loadsdk';
export default defineConfig({
base: './',
plugins: [SuperMapLoadSDKVitePlugin({ target: 'clientx' })],
});// src/main.js
import * as ClientX from '@supermapgis/clientx';
const viewer = new ClientX.Viewer('Container', {});target 参数
插件通过 target 参数切换目标 SDK 包,内部自动推导 packagePath、assetsDirName 等常量:
| target | packagePath | assetsDirName | 入口文件 |
|--------|-------------|---------------|----------|
| 'clientx'(默认) | @supermapgis/clientx | ClientX | ClientX.js |
| 'iclient3d' | @supermapgis/iclient3d | SuperMap3D | SuperMap3D.js |
// 集成 @supermapgis/clientx(默认,可省略 target)
SuperMapLoadSDKVitePlugin({ target: 'clientx' })
// 集成 @supermapgis/iclient3d
SuperMapLoadSDKVitePlugin({ target: 'iclient3d' })配置项
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| target | 'clientx' \| 'iclient3d' | 'clientx' | 目标 SDK 包,决定 packagePath / assetsDirName 等内部常量 |
| packagePath | string | 根据 target 自动推导 | npm 包路径,可显式覆盖 |
| assetsDirName | string | 根据 target 自动推导 | 运行时静态资源目录名,可显式覆盖 |
| copyFolders | string[] | 见下方 | build 后复制的运行时目录(全量模式生效) |
| distDir | string | 'dist' | 构建产物目录 |
| baseUrl | string | 自动计算 | 覆盖 SUPERMAP3D_BASE_URL,未设置时根据 vite base 自动计算 |
| isAddWidgetCSS | boolean | true | 是否自动注入 Widget CSS link 标签 |
| staticAssets | object | { filter: false, keepFiles: [] } | 静态资源复制控制 |
copyFolders 默认值:
['Assets', 'Workers', 'ThirdParty', 'Widgets', 'language', 'ReactiveWidgets', 'SkyAtmosphereSystem']staticAssets 子选项:
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| filter | boolean | false | false = 全量拷贝 copyFolders 中的所有目录;true = 仅拷贝 keepFiles 匹配的文件 |
| keepFiles | string[] | [] | glob 规则列表,路径相对于 Build/<assetsDirName>/,仅在 filter: true 时生效 |
注意:
staticAssets.filter为true时依赖glob,该依赖已包含在本插件的dependencies中,安装插件时会自动安装,无需手动添加。
插件内部结构
本插件返回 4 个子插件,各司其职:
| 子插件 | 名称 | 作用 |
|--------|------|------|
| Plugin 1 | supermap3d-auto-config | 自动注入 SUPERMAP3D_BASE_URL、Widget CSS 和 forge.min.js 到 HTML |
| Plugin 2 | supermap3d-config | 配置 resolve.mainFields 和 optimizeDeps(依赖预打包优化) |
| Plugin 3 | supermap3d-assets | dev/preview 服务器静态资源代理 + 空模块兜底 |
| Plugin 4 | copy-supermap3d-assets | build 后将运行时静态资源复制到产物目录 |
Plugin 1: supermap3d-auto-config(自动配置注入)
解决的问题: SDK 运行时需要通过 window.SUPERMAP3D_BASE_URL 定位静态资源(WASM、Worker、纹理等)的 URL 路径,同时需要加载 Widget CSS。手动设置容易遗漏或路径错误。
工作方式: 在 transformIndexHtml 阶段,向 HTML <head> 最前面注入标签:
<!-- 1. 设置全局资源路径(在所有模块加载前执行) -->
<script type="text/javascript">window.SUPERMAP3D_BASE_URL="./ClientX/";</script>
<!-- 2. 引入 Widget CSS(可通过 isAddWidgetCSS 关闭) -->
<link rel="stylesheet" href="./ClientX/Widgets/widgets.css">
<!-- 3. 注入 forge.min.js(如存在),确保 UMD 格式正确挂载到 window.forge -->
<script type="text/javascript" src="./ClientX/ThirdParty/forge.min.js"></script>forge.min.js 注入背景: forge.min.js 是 UMD 格式,Vite 预构建时用
__commonJSMin包裹后,UMD 判定走module.exports=t()分支,window.forge从未被赋值。而 RSAAndAESEn-DecryptorUtil 中所有forge.xxx都读全局变量,导致运行时报错。通过<script src>加载原始 UMD 文件(非 ESM),没有exports/module对象,UMD 会走e.forge=t()分支,正确设置window.forge。
路径自动适配:
| 模式 | vite base | 注入的 BASE_URL | CSS href |
|------|-----------|----------------|----------|
| dev | '/' | /ClientX/ | /ClientX/Widgets/widgets.css |
| build | './' | ./ClientX/ | ./ClientX/Widgets/widgets.css |
| 自定义 | - | options.baseUrl | options.baseUrl + Widgets/widgets.css |
注意:
window.SUPERMAP3D_BASE_URL在 clientx 和 iclient3d 两个 target 下保持一致,不随 target 变化。
Plugin 2: supermap3d-config(依赖优化配置)
解决的问题: SDK 是扁平化 ESM 模块,需要 Vite 优先使用 module 字段解析;同时其依赖树中包含大量 CJS 模块(如 lodash.clonedeep、rgbcolor、protobufjs 等),浏览器原生 ESM 无法从 CJS 的 module.exports 读取 default 导出。此外,draco3d 等库引用了 Node.js 的 fs 模块,需要配置浏览器端空实现以消除 dev 模式下的 "Module fs has been externalized" 警告。
自动注入的配置:
{
resolve: {
mainFields: ['module', 'browser', 'main'], // 优先使用 module 字段(指向 SourceRelease)
alias: {
fs: path.resolve(__dirname, '_fs-stub.js'), // Node.js fs 模块别名到浏览器端空实现
},
},
optimizeDeps: {
// 不排除目标包,让 Vite 自动预打包整个包及其依赖树。
// Vite 会自动处理所有 CJS 互操作(lodash.clonedeep、rgbcolor 等),
// 无需手动维护 CJS 依赖列表。
//
// tree-shaking 不受影响:build 阶段由 Rollup 直接从 SourceRelease 入口
// 做 tree-shaking,与 dev 阶段的 optimizeDeps 预打包完全无关。
exclude: [
// @mapbox/geojson-types 使用 Flow 类型语法,预打包器无法解析,
// 该包为类型定义包,运行时不会被实际执行,排除预打包
'@mapbox/geojson-types'
]
}
}设计说明: 早期版本曾将 SDK 加入
optimizeDeps.exclude以追求 dev 模式按需加载,但这会导致 Vite 无法自动发现其传递依赖中的 CJS 包(如lodash.clonedeep),引发does not provide an export named 'default'报错。当前版本不再排除 SDK,让 Vite 统一预打包,CJS 互操作由 Vite 自动完成。
Plugin 3: supermap3d-assets(dev/preview 资源代理 + 空模块兜底)
解决的问题: dev 模式下浏览器通过 /ClientX/xxx.wasm 等 URL 请求静态资源,但这些文件在 node_modules 中,Vite 默认不会提供。
工作方式: 在 configureServer 和 configurePreviewServer 中注册中间件:
- 静态资源代理: 拦截
/<assetsDirName>/开头的请求,映射到node_modules/@supermapgis/<package>/Build/<assetsDirName>/目录,支持 wasm/worker/图片/css/json 等类型 - 空模块兜底: 拦截目标包内
SourceRelease/*.js请求,文件不存在时返回export default {};(空 ESM 模块),避免扁平化后悬空 import 导致 dev server 报错
Plugin 4: copy-supermap3d-assets(build 资源复制)
解决的问题: npm run build 后产物 dist/ 目录中需要包含 SDK 的运行时静态资源,否则部署后页面找不到 WASM/Worker/纹理等文件。
工作方式: 在 closeBundle 钩子中,将 Build/<assetsDirName>/ 下的资源目录复制到 dist/<assetsDirName>/:
- 全量模式(默认): 复制
copyFolders中配置的所有目录 - 过滤模式: 仅复制
keepFiles中 glob 规则匹配的文件,减少产物体积
配置示例
默认配置(推荐)
自动计算 baseUrl,自动注入 Widget CSS,全量拷贝静态资源:
import { defineConfig } from 'vite';
import SuperMapLoadSDKVitePlugin from '@supermapgis/vite-plugin-loadsdk';
export default defineConfig({
base: './',
plugins: [SuperMapLoadSDKVitePlugin()],
});切换 target
// 集成 @supermapgis/clientx
plugins: [SuperMapLoadSDKVitePlugin({ target: 'clientx' })]
// 集成 @supermapgis/iclient3d
plugins: [SuperMapLoadSDKVitePlugin({ target: 'iclient3d' })]自定义 baseUrl
当静态资源不在默认的 ./ClientX/ 路径下时(如部署到 CDN 或自定义目录):
plugins: [SuperMapLoadSDKVitePlugin({ target: 'clientx', baseUrl: './ClientX/' })]关闭 Widget CSS 注入
如果项目中已手动引入 widgets.css,或不需要 Widget 样式:
plugins: [SuperMapLoadSDKVitePlugin({ target: 'clientx', isAddWidgetCSS: false })]静态资源过滤(减小产物体积)
默认全量拷贝会将所有静态资源目录复制到 dist/ClientX/,如果项目只需要部分资源,可开启过滤模式,仅拷贝匹配的文件:
plugins: [SuperMapLoadSDKVitePlugin({
target: 'clientx',
staticAssets: {
filter: true, // 开启过滤模式
keepFiles: [ // 仅拷贝匹配以下 glob 规则的文件
'Assets/**/*', // 纹理、模型等资源
'SkyAtmosphereSystem/**/*', // 天空大气资源
'ThirdParty/**/*', // 第三方库(WASM 等)
'Widgets/**/*', // Widget CSS
'Workers/**/*', // Worker 脚本
]
}
})]常用 glob 模式:
| 模式 | 说明 |
|------|------|
| Assets/**/* | Assets 目录下的所有文件(含子目录) |
| Workers/*.js | Workers 根目录下的所有 .js 文件 |
| Workers/**/*.js | Workers 及其子目录下的所有 .js 文件 |
| ThirdParty/**/*.wasm | ThirdParty 目录下所有 WASM 文件 |
| Widgets/**/*.css | 所有 Widget CSS 文件 |
用户代码写法
插件配置好后,用户代码非常简洁,无需任何手动设置:
全量导入(默认):
import * as ClientX from '@supermapgis/clientx';
const viewer = new ClientX.Viewer("Container", {});
window.viewer = viewer;按需导入(利用 tree-shaking 减小产物体积):
import { Viewer } from '@supermapgis/clientx';
const viewer = new Viewer("Container", {});import { Cartesian3, Cartographic, Math } from '@supermapgis/clientx';
const c3 = Cartesian3.fromDegrees(116.45, 39.91, 5);tree-shaking 说明:
@supermapgis/clientx的package.json中配置了sideEffects字段。Vite build 时由 Rollup 直接从SourceRelease/ClientX.js入口做 tree-shaking,与 dev 阶段的optimizeDeps预打包完全无关。全量导入约 11MB,仅引入 Viewer 约 9MB。
缓存清理
当依赖更新后页面未生效,可执行以下命令清除 Vite 缓存并强制刷新依赖打包:
rmdir /s /q node_modules\.vite
npm run dev -- --force