FEATURED · 精选文章

OHIF v3.9 迁移指南:browserImport 外部库动态加载与 ViewReference 视图导航机制

发布时间 / 2026/9/18 22:11:12
来源 / 创域科博编辑部
栏目 / 资讯中心
OHIF v3.9 迁移指南:browserImport 外部库动态加载与 ViewReference 视图导航机制 OHIF v3.9 迁移指南browserImport 外部库动态加载与 ViewReference 视图导航机制【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers在 OHIF 3.8 升级到 3.9 的过程中除了核心渲染管线和扩展 API 的变更外还有一批其他变更同样影响着每一个自建部署外部库如dicom-microscopy-viewer不再作为 webpack 构建期依赖打进包内而是通过全局browserImport函数在浏览器运行时动态加载并借助pluginConfig.json声明模块来源同时跨视图导航从传统的相机参数跳转全面转向基于getViewReference/isReferenceViewable/setViewReference的 ViewReference 机制MPR、Stack、视频与显微镜视口之间的测量跳转行为也因此发生变化。本文基于 9-other.md 展开逐项说明这两个主题的迁移步骤、配置细节与底层源码原理帮助你在升级到 3.9 后正确配置外部依赖、理解并规避导航行为变化带来的影响。外部库的动态加载从构建期依赖到运行时导入为什么需要 browserImportOHIF 3.9 的插件体系扩展 extension、模式 mode在构建时会被静态解析。但对于体积较大、更新频繁或由第三方发布的库典型如整张切片显微图像的渲染库dicom-microscopy-viewer将其作为构建期依赖会显著拉长构建时间、增大产物体积也会让零足迹的轻量部署变得困难。迁移文档给出的方案是这些库改为在运行时通过动态import()按需加载。为了让动态导入不参与 webpack 的依赖静态分析否则 webpack 仍会尝试打包并可能失败需要在应用的根 HTML 文件中提供一个全局函数browserImportFunctionscript function browserImportFunction(moduleId) { return import(moduleId); } /script该函数定义在window作用域接收一个模块标识moduleId并返回import()的 Promise。在 OHIF 平台应用中这个函数已经内置在默认的 HTML 模板中见 platform/app/public/html-templates/index.html#L209-L215script function browserImportFunction(moduleId) { return import(moduleId); } window.PUBLIC_URL % PUBLIC_URL %; /script迁移到 3.9 后你的自定义部署如果沿用该模板则无需额外改动如果是自建的 HTML 入口则必须自行注入等价的browserImportFunction。迁移步骤移除依赖、声明引用将某个库改为运行时动态加载需要同时完成两件事移除对该外部库的构建期dependencies依赖——即不要把它放进package.json的 dependencies 中被 webpack 静态打包或者在构建配置中将其标记为 external在pluginConfig.json的public段中声明该外部模块说明它的加载路径、导出方式和文件来源。pluginConfig.json位于 platform/app/pluginConfig.json其中public数组的每一项定义一个目录模块其内容会被原样复制到构建输出目录或一个动态导入模块通过packageName识别运行时由browserImportFunction加载。实战示例dicom-microscopy-viewer迁移文档给出的dicom-microscopy-viewer配置该示例正是默认pluginConfig.json中的内容public: [ { directory: ./platform/public }, { packageName: dicom-microscopy-viewer, importPath: /dicom-microscopy-viewer/dicomMicroscopyViewer.min.js, globalName: dicomMicroscopyViewer, directory: ./node_modules/dicom-microscopy-viewer/dist/dynamic-import } ]逐字段说明directory./platform/public是应用自身的静态资源目录会被原样复制到构建输出目录packageNamedicom-microscopy-viewer用于在插件体系内唯一标识这个外部模块importPath传入上文browserImportFunction的模块标识即实际加载的 JS 文件地址globalName加载完成后挂载在window上的全局变量名即通过window.dicomMicroscopyViewer访问该库directory外部库文件的来源目录构建时将其内容复制到输出目录供importPath引用。需要说明的是当前仓库中 platform/app/pluginConfig.json#L104-L115 的实际写法在此基础上做了一点演进importPath使用相对路径dicom-microscopy-viewer/dicomMicroscopyViewer.min.js并增加了to: /dicom-microscopy-viewer/字段来显式指定复制目标目录public: [ { directory: ./platform/public }, { packageName: dicom-microscopy-viewer, importPath: dicom-microscopy-viewer/dicomMicroscopyViewer.min.js, globalName: dicomMicroscopyViewer, directory: ./node_modules/dicom-microscopy-viewer/dist/dynamic-import, to: /dicom-microscopy-viewer/ } ]底层原理writePluginImportsFile 与生成的 pluginImports.jspluginConfig.json并不直接被运行时消费而是由构建脚本 platform/app/.webpack/writePluginImportsFile.js 在构建时读取动态生成pluginImports.jsplatform/app/src/pluginImports.js为构建产物仓库中不静态存在。生成逻辑位于getRuntimeLoadModesExtensions其关键分支writePluginImportsFile.js#L66-L108如下对配置了importPath的模块生成通过window.browserImportFunction(...)加载的代码且会自动拼接PUBLIC_URL前缀除非importPath以http或/开头见isAbsolutePath判断加载完成后按globalName取window[dicomMicroscopyViewer]未声明globalName时则回退到imported[default]或importName指定的具名导出未配置importPath的扩展/模式仍走静态import(packageName)同时public段中的目录如./platform/public与./node_modules/dicom-microscopy-viewer/dist/dynamic-import会被复制进构建输出目录保证运行时importPath可解析。应用启动时platform/app/src/appInit.js#L27 引入生成的pluginImports.js并将其中的loadModule作为peerImport注入appConfigappInit.js#L49-L50// Default the peer import function appConfig.peerImport || peerImport;peerImport随后被ExtensionManager持有见 platform/core/src/extensions/ExtensionManager.ts#L34、ExtensionManager.ts#L119供各扩展在运行时加载外部模块。引用外部导入peerImport 与 CS3D 的衔接迁移文档指出appConfig要么自定义、要么默认提供一个peerImport函数用于加载pluginConfig.json中声明的模块cornerstone 扩展的init.tsx是展示如何将其传给 CS3D 以加载全切片成像WSIWhole Slide Imaging库的示例。对应源码在 extensions/cornerstone/src/init.tsx#L77-L80await cs3DInit({ peerImport: appConfig.peerImport, debug: { statsOverlay }, });即 cornerstone 核心初始化时把peerImport作为外部模块加载通道交给 CS3D。显微镜扩展则直接通过该通道在运行时获取dicom-microscopy-viewer见 extensions/dicom-microscopy/src/services/MicroscopyService.ts#L42 与 MicroscopyService.ts#L73-L75public importDicomMicroscopyViewer(): Promiseany { return this.peerImport(dicom-microscopy-viewer); }迁移到 3.9 时如果你的自定义扩展需要加载类似的运行时外部库遵循同样的三步在根 HTML 定义browserImportFunction、在pluginConfig.json的public段声明模块、在代码中通过appConfig.peerImport或扩展内注入的peerImport发起加载。使用 ViewReference 进行导航三个核心方法3.9 起测量跳转与导航位置的保存/恢复统一围绕三个 viewport 方法展开viewport.getViewReference()——获取当前视图位置的引用参考信息viewport.isReferenceViewable(reference, options)——检查某个引用能否应用到当前视口viewport.setViewReference(reference)——将视口导航到引用所描述的视图位置。在 cornerstone 扩展中这三个方法由CornerstoneViewportService的视口实现暴露getViewReference在 extensions/cornerstone/src/services/ViewportService/Viewport.ts#L209 处定义。注意这一变更改变了 MPR 与 Stack 视口之间的导航行为并且使得 CS3D 中视频video与显微镜microscopy视口也能参与统一导航。因此导航是否如预期工作取决于帧参考系Frame of Reference相关数值如何配置——不同的 FOR 配置会直接影响跨视口导航的结果。getViewReference 与 forFrameOfReference 标志getViewReference的行为由forFrameOfReference为帧参考系标志决定当该标志为true时返回的引用可以被任何包含同一帧参考系、且覆盖给定 FOR、且能显示所需方向的视口显示。换言之它描述的是该 FOR 中的这个位置与具体哪一帧图像绑定较松当该标志为false默认时返回的引用会被包含指定 imageId 的 Stack 视口或包含该 imageId/指定 volume 的 Volume 视口显示。即它更贴近具体的图像/体积实例。这一区别解释了为什么在 Stack 与 Volume 之间切换时导航表现可能不同取自某个具体 Stack 的引用未带 FOR 标志只能回到包含该 imageId 的视口而带 FOR 标志的引用则可以跨到同 FOR 下任意能呈现该方向的视口。isReferenceViewable 与导航/方向标志isReferenceViewable在引用能被视口原样直接显示时才返回true。但它可以接收各种标志用来判断如果对视口做某种修改例如改变位置或方向引用是否能够被显示。这允许对接近程度进行分级检查从而选出最合适的视口。源码中预定义了两组标志见 CornerstoneViewportService.ts#L111-L112export const WITH_NAVIGATION { withNavigation: true, withOrientation: false }; export const WITH_ORIENTATION { withNavigation: true, withOrientation: true };WITH_NAVIGATION仅允许通过改变位置滚动/平移来显示引用不允许改变方向WITH_ORIENTATION允许通过改变方向来显示引用同时保留导航能力。findNavigationCompatibleViewportIdCornerstoneViewportService.ts#L680-L713正是按接近程度分级搜索的典型实现其查找顺序为当前激活视口能否仅靠导航显示该引用isReferenceViewable(metadata, WITH_NAVIGATION)其他任意视口能否仅靠导航显示该引用通过getViewportAlignmentData计算各视口与引用方向的对齐分数基于viewPlaneNormal与planeRestriction的点积按最接近方向排序后检查是否可通过方向变化显示WITH_ORIENTATION以上都不满足则返回null表示需要更换视口的显示集/类型才能展示。这里需要特别留意文档强调的行为变化一个视口中的测量可能被显示在完全不同的另一个视口上。例如Stack 视口上用 Probe 工具画的测量在 MPR 视图上也能被展示出来。这是isReferenceViewable在WITH_NAVIGATION/WITH_ORIENTATION语义下就近选视口的预期结果但也意味着迁移后测量跳转的目标视口可能与 3.8 时代不同。源码级佐证jumpToMeasurementViewport 的完整链路测量跳转命令jumpToMeasurementViewport展示了三个方法的完整协作extensions/cornerstone/src/commandsModule.ts#L236-L262先选中该标注setAnnotationSelected调用findNavigationCompatibleViewportId找出最适合展示该测量引用的视口——它可能不是当前激活视口命中后调用viewport.setViewReference(metadata)导航到测量所在切片并render()若测量在当前视口中不可见再由ops.centerOnMeasurement进行平面内重定位legacy 后端走getCamera/setCamera重定位native 后端因setViewReference已导航到位而跳过。这条调用链同时也印证了存储/记住导航位置的机制位置状态通过getViewReference()保存例如 SegmentationService 在交互前后记录prevViewReference并在需要时用setViewReference恢复见 extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts#L1772-L1779。此外cornerstone 扩展还提供了一个面向挂载协议/自定义逻辑的辅助函数isReferenceViewableextensions/cornerstone/src/utils/isReferenceViewable.ts#L6-L39其默认行为等价于同时开启withNavigation: true与asVolume: true当传入显式viewportOptions时Stack 视口只要求包含被引用的imageIdVolume 视口则通过getClosestOrientationFromIOP计算最接近的解剖方向并与之比对isReferenceViewable.ts#L48-L95该函数已在 extensions/cornerstone/src/utils/index.ts 中导出并绑定servicesManager后注册为isReferenceViewable命令见 extensions/cornerstone/src/index.tsx#L245。迁移清单与注意事项针对 3.8 → 3.9 的这两项变更升级时建议按以下清单核对HTML 入口确认根 HTML 中定义了全局browserImportFunction或沿用 platform/app/public/html-templates/index.html 默认模板依赖声明需要运行时加载的外部库从dependencies中移除避免被 webpack 静态打包pluginConfig.json在public段补齐packageName/importPath/globalName/directory必要时加to指定复制目标参照 platform/app/pluginConfig.json#L104-L115加载通道代码中通过appConfig.peerImport发起加载ExtensionManager会持有该函数cornerstone 扩展将其传给 CS3D见 extensions/cornerstone/src/init.tsx#L77-L80导航语义理解getViewReference的forFrameOfReference标志差异以及isReferenceViewable的withNavigation/withOrientation分级——同一测量可能在完全不同的视口如 Stack 的 Probe 出现在 MPR上展示帧参考系配置若发现跨 MPR/Stack 导航行为与预期不符优先检查帧参考系FOR数值的配置方式它直接决定了 ViewReference 能否在视口间传递。【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻