fix: webpack import bugs showing warnings on import (#4265)

This commit is contained in:
Bill Wallace 2024-07-05 13:19:42 -04:00 committed by GitHub
parent 6d11048ca5
commit 24c511f4bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 975 additions and 1008 deletions

View File

@ -46,9 +46,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.81.6",
"@cornerstonejs/core": "^1.81.6",
"@cornerstonejs/tools": "^1.81.6",
"@cornerstonejs/adapters": "^1.82.0",
"@cornerstonejs/core": "^1.82.0",
"@cornerstonejs/tools": "^1.82.0",
"classnames": "^2.3.2"
}
}

View File

@ -42,9 +42,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/core": "^1.81.6",
"@cornerstonejs/streaming-image-volume-loader": "^1.81.6",
"@cornerstonejs/tools": "^1.81.6",
"@cornerstonejs/core": "^1.82.0",
"@cornerstonejs/streaming-image-volume-loader": "^1.82.0",
"@cornerstonejs/tools": "^1.82.0",
"classnames": "^2.3.2"
}
}

View File

@ -38,7 +38,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
"@cornerstonejs/dicom-image-loader": "^1.81.6",
"@cornerstonejs/dicom-image-loader": "^1.82.0",
"@icr/polyseg-wasm": "^0.4.0",
"@ohif/core": "3.9.0-beta.58",
"@ohif/ui": "3.9.0-beta.58",
@ -55,10 +55,10 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
"@cornerstonejs/adapters": "^1.81.6",
"@cornerstonejs/core": "^1.81.6",
"@cornerstonejs/streaming-image-volume-loader": "^1.81.6",
"@cornerstonejs/tools": "^1.81.6",
"@cornerstonejs/adapters": "^1.82.0",
"@cornerstonejs/core": "^1.82.0",
"@cornerstonejs/streaming-image-volume-loader": "^1.82.0",
"@cornerstonejs/tools": "^1.82.0",
"@icr/polyseg-wasm": "^0.4.0",
"@kitware/vtk.js": "30.4.1",
"html2canvas": "^1.4.1",

View File

@ -37,8 +37,8 @@ import { colormaps } from './utils/colormaps';
const { registerColormap } = csUtilities.colormap;
// TODO: Cypress tests are currently grabbing this from the window?
window.cornerstone = cornerstone;
window.cornerstoneTools = cornerstoneTools;
(window as any).cornerstone = cornerstone;
(window as any).cornerstoneTools = cornerstoneTools;
/**
*
*/
@ -46,7 +46,7 @@ export default async function init({
servicesManager,
commandsManager,
extensionManager,
appConfig,
appConfig
}: Types.Extensions.ExtensionParams): Promise<void> {
// Note: this should run first before initializing the cornerstone
// DO NOT CHANGE THE ORDER
@ -67,6 +67,7 @@ export default async function init({
preferSizeOverAccuracy: Boolean(appConfig.preferSizeOverAccuracy),
useNorm16Texture: Boolean(appConfig.useNorm16Texture),
},
peerImport: appConfig.peerImport,
});
// For debugging e2e tests that are failing on CI

View File

@ -49,13 +49,6 @@ class DicomMicroscopyViewport extends Component {
resizeRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]),
};
/**
* Need to return this as a function to prevent webpack from munging it.
*/
public static getImportPath() {
return '/dicom-microscopy-viewer/dicomMicroscopyViewer.min.js';
}
/**
* Get the nearest ROI from the mouse click point
@ -94,9 +87,8 @@ class DicomMicroscopyViewport extends Component {
// you should only do this once.
async installOpenLayersRenderer(container, displaySet) {
const loadViewer = async metadata => {
await import(
/* webpackIgnore: true */ DicomMicroscopyViewport.getImportPath());
const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = (window as any).dicomMicroscopyViewer;
const dicomMicroscopyModule = await this.microscopyService.importDicomMicroscopyViewer();
const { viewer: DicomMicroscopyViewer, metadata: metadataUtils } = dicomMicroscopyModule;
const microscopyViewer = DicomMicroscopyViewer.VolumeImageViewer;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { CommandsManager, ExtensionManager } from '@ohif/core';
import type { Types } from '@ohif/core';
import { useViewportGrid } from '@ohif/ui';
import MicroscopyPanel from './components/MicroscopyPanel/MicroscopyPanel';
@ -12,11 +12,7 @@ export default function getPanelModule({
commandsManager,
extensionManager,
servicesManager,
}: {
servicesManager: AppTypes.ServicesManager;
commandsManager: CommandsManager;
extensionManager: ExtensionManager;
}) {
}: Types.Extensions.ExtensionParams) {
const wrappedMeasurementPanel = () => {
const [{ activeViewportId, viewports }] = useViewportGrid();

View File

@ -44,6 +44,7 @@ const extension: Types.Extensions.Extension = {
* that is provided by the Cornerstone extension in OHIF.
*/
getViewportModule({ servicesManager, extensionManager, commandsManager }) {
/**
*
* @param props {*}

View File

@ -22,8 +22,8 @@ export default class MicroscopyService extends PubSubService {
return {
name: 'microscopyService',
altName: 'MicroscopyService',
create: ({ configuration = {} }) => {
return new MicroscopyService(servicesManager);
create: (props) => {
return new MicroscopyService(props);
},
};
};
@ -36,9 +36,10 @@ export default class MicroscopyService extends PubSubService {
selectedAnnotation = null;
pendingFocus = false;
constructor(servicesManager) {
constructor({ servicesManager, extensionManager }) {
super(EVENTS);
this.servicesManager = servicesManager;
this.peerImport = extensionManager.appConfig.peerImport;
this._onRoiAdded = this._onRoiAdded.bind(this);
this._onRoiModified = this._onRoiModified.bind(this);
this._onRoiRemoved = this._onRoiRemoved.bind(this);
@ -69,6 +70,10 @@ export default class MicroscopyService extends PubSubService {
});
}
public importDicomMicroscopyViewer(): Promise<any> {
return this.peerImport("dicom-microscopy-viewer");
}
/**
* Observes when a ROI graphic is added, creating the correspondent annotation
* with the current graphic and view state.

View File

@ -2,7 +2,6 @@ import dcmjs from 'dcmjs';
import DCM_CODE_VALUES from './dcmCodeValues';
import toArray from './toArray';
import DicomMicroscopyViewport from '../DicomMicroscopyViewport';
const MeasurementReport = dcmjs.adapters.DICOMMicroscopyViewer.MeasurementReport;
@ -24,7 +23,7 @@ export default async function loadSR(
microscopySRDisplaySet.isLoaded = true;
const { rois, labels } = await _getROIsFromToolState(naturalizedDataset, FrameOfReferenceUID);
const { rois, labels } = await _getROIsFromToolState(microscopyService, naturalizedDataset, FrameOfReferenceUID);
const managedViewer = managedViewers[0];
@ -45,12 +44,11 @@ export default async function loadSR(
}
}
async function _getROIsFromToolState(naturalizedDataset, FrameOfReferenceUID) {
async function _getROIsFromToolState(microscopyService, naturalizedDataset, FrameOfReferenceUID) {
const toolState = MeasurementReport.generateToolState(naturalizedDataset);
const tools = Object.getOwnPropertyNames(toolState);
// Does a dynamic import to prevent webpack from rebuilding the library
await import(/* webpackIgnore: true */ DicomMicroscopyViewport.getImportPath());
const DICOMMicroscopyViewer = (window as any).dicomMicroscopyViewer;
const DICOMMicroscopyViewer = await microscopyService.importDicomMicroscopyViewer();
const measurementGroupContentItems = _getMeasurementGroups(naturalizedDataset);

View File

@ -32,8 +32,8 @@
"start": "yarn run dev"
},
"peerDependencies": {
"@cornerstonejs/core": "^1.81.6",
"@cornerstonejs/tools": "^1.81.6",
"@cornerstonejs/core": "^1.82.0",
"@cornerstonejs/tools": "^1.82.0",
"@ohif/core": "3.9.0-beta.58",
"@ohif/extension-cornerstone-dicom-sr": "3.9.0-beta.58",
"@ohif/ui": "3.9.0-beta.58",

View File

@ -102,16 +102,17 @@ module.exports = (env, argv) => {
to: `${DIST_DIR}/app-config.js`,
},
// Copy Dicom Microscopy Viewer build files
{
from: '../../../node_modules/dicom-microscopy-viewer/dist/dynamic-import',
to: DIST_DIR,
globOptions: {
ignore: ['**/*.min.js.map'],
},
// The dicom-microscopy-viewer is optional, so if it doeesn't get
// installed, it shouldn't cause issues.
noErrorOnMissing: true,
},
// This is in pluginCOnfig.json now
// {
// from: '../../../node_modules/dicom-microscopy-viewer/dist/dynamic-import',
// to: DIST_DIR,
// globOptions: {
// ignore: ['**/*.min.js.map'],
// },
// // The dicom-microscopy-viewer is optional, so if it doeesn't get
// // installed, it shouldn't cause issues.
// noErrorOnMissing: true,
// },
// Copy dicom-image-loader build files
{
from: '../../../node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import',

View File

@ -66,6 +66,18 @@ function getRuntimeLoadModesExtensions(modules) {
);
modules.forEach(module => {
const packageName = extractName(module);
if (!packageName) {
return;
}
if (module.importPath) {
dynamicLoad.push(
` if( module==="${packageName}") {`,
` const imported = await window.browserImportFunction('${module.importPath}');`,
' return ' + (module.globalName ? `window["${module.globalName}"];` : `imported["${module.importName || 'default'}"];`),
' }'
);
return;
}
dynamicLoad.push(
` if( module==="${packageName}") {`,
` const imported = await import("${packageName}");`,
@ -73,8 +85,9 @@ function getRuntimeLoadModesExtensions(modules) {
' }'
);
});
// TODO - handle more cases for import than just default
dynamicLoad.push(
' return (await import(/* webpackIgnore: true */ module)).default;',
' return (await window.browserImportFunction(module)).default;',
'}\n',
'// Import a list of items (modules or string names)',
'// @return a Promise evaluating to a list of modules',
@ -144,6 +157,7 @@ function writePluginImportsFile(SRC_DIR, DIST_DIR) {
pluginImportsJsContent += getRuntimeLoadModesExtensions([
...pluginConfig.extensions,
...pluginConfig.modes,
...pluginConfig.public,
]);
fs.writeFileSync(`${SRC_DIR}/pluginImports.js`, pluginImportsJsContent, { flag: 'w+' }, err => {

View File

@ -88,6 +88,12 @@
"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"
}
]
}

View File

@ -210,6 +210,12 @@
rel="preload"
as="style"
/>
<script>
function browserImportFunction(moduleId) {
return import(moduleId);
}
</script>
<!-- EXTENSIONS -->
<!-- <script type="text/javascript" src="path/to/some-extension.js"></script>

View File

@ -24,7 +24,7 @@ import {
// utils,
} from '@ohif/core';
import loadModules from './pluginImports';
import loadModules, { loadModule as peerImport } from './pluginImports';
/**
* @param {object|func} appConfigOrFunc - application configuration, or a function that returns application configuration
@ -42,9 +42,11 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
const appConfig = {
...(typeof appConfigOrFunc === 'function'
? await appConfigOrFunc({ servicesManager, loadModules })
? await appConfigOrFunc({ servicesManager, peerImport })
: appConfigOrFunc),
};
// Default the peer import function
appConfig.peerImport ||= peerImport;
const extensionManager = new ExtensionManager({
commandsManager,

View File

@ -37,7 +37,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.3",
"@cornerstonejs/codec-openjph": "^2.4.5",
"@cornerstonejs/dicom-image-loader": "^1.81.6",
"@cornerstonejs/dicom-image-loader": "^1.82.0",
"@ohif/ui": "3.9.0-beta.58",
"cornerstone-math": "0.1.9",
"dicom-parser": "^1.8.21"

View File

@ -31,6 +31,7 @@ export interface ExtensionParams extends ExtensionConstructor {
servicesManager: AppTypes.ServicesManager;
serviceProvidersManager: ServiceProvidersManager;
configuration?: ExtensionConfiguration;
peerImport: (moduleId: string) => Promise<any>;
}
/**
@ -88,6 +89,7 @@ export default class ExtensionManager extends PubSubService {
private dataSourceDefs: Record<string, any>;
private defaultDataSourceName: string;
private activeDataSource: string;
private peerImport: (moduleId) => Promise<any>;
constructor({
commandsManager,
@ -116,6 +118,7 @@ export default class ExtensionManager extends PubSubService {
this.dataSourceDefs = {};
this.defaultDataSourceName = appConfig.defaultDataSourceName;
this.activeDataSource = appConfig.defaultDataSourceName;
this.peerImport = appConfig.peerImport;
}
public setActiveDataSource(dataSource: string): void {
@ -608,6 +611,10 @@ export default class ExtensionManager extends PubSubService {
);
});
};
public get appConfig() {
return this._appConfig;
}
}
/**

View File

@ -122,13 +122,14 @@ declare global {
onConfiguration?: (dicomWebConfig: any, options: any) => any;
dataSources?: any;
oidc?: any;
peerImport?: (moduleId: string) => Promise<any>;
studyPrefetcher: {
enabled: boolean;
displaySetsCount: number;
maxNumPrefetchRequests: number;
order: 'closest' | 'downward' | 'upward';
}
}
}
export interface Test {
services?: Services;

View File

@ -35,6 +35,9 @@ What's Changing?
</Tabs>
### Run newer yarn version
You must be running a newer yarn version for react 18.
It isn't clear the exact yarn required.
### Update React version:
In your custom extensions and modes, change the version of react and react-dom to ^18.3.1.
@ -160,6 +163,57 @@ To disable it, remove the configuration from the `initToolGroups` in your mode.
<br/>
## External Libraries
Some libraries are loaded via dynamic import. You can provide a global function
`browserImport` the allows loading of dynamic imports without affecting the
webpack build. This import looks like:
```
<script>
function browserImportFunction(moduleId) {
return import(moduleId);
}
</script>
```
and belongs in the root html file for your application.
You then need to remove `dependencies` on the external import, and add a reference
to the external import in your `pluginConfig.json` file.
### Example plugin config for `dicom-microscopy-viewer`
The example below imports the `dicom-microscopy-viewer` for use as an external
dependency. The example is part of the default `pluginConfig.json` file.
```
"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"
}
]
```
This defines two directory modules, whose contents are copied unchanged to the
output build directory. It then defines the `dicom-microscopy-viewer` using
the `packageName` element as being a module which is imported dynamically.
Then, the import path passed into the browserImportFunction above is
specified, and then how to access the import itself, via the `window.dicomMicroscopyViewer`
global name reference.
### Referencing External Imports
The appConfig either defines or has a default peerImport function which can be
used to load references to the modules defined in the pluginConfig file. See
the example in `init.tsx` for the cornerstone extension for how this is passed
into CS3D for loading the whole slide imaging library.
### Usage of Dynamic Imports
## BulkDataURI Configuration
We've updated the configuration for BulkDataURI to provide more flexibility and control. This guide will help you migrate from the old configuration to the new one.

View File

@ -0,0 +1,11 @@
const path = require('path');
const webpackCommon = require('./../../../.webpack/webpack.base.js');
const SRC_DIR = path.join(__dirname, '../src');
const DIST_DIR = path.join(__dirname, '../dist');
const ENTRY = {
app: `${SRC_DIR}/index.ts`,
};
module.exports = (env, argv) => {
return webpackCommon(env, argv, { SRC_DIR, DIST_DIR, ENTRY });
};

View File

@ -0,0 +1,60 @@
const { merge } = require('webpack-merge');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const webpackCommon = require('./../../../.webpack/webpack.base.js');
const pkg = require('./../package.json');
const ROOT_DIR = path.join(__dirname, './..');
const SRC_DIR = path.join(__dirname, '../src');
const DIST_DIR = path.join(__dirname, '../dist');
const ENTRY = {
app: `${SRC_DIR}/index.ts`,
};
const outputName = `ohif-${pkg.name.split('/').pop()}`;
module.exports = (env, argv) => {
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR, ENTRY });
return merge(commonConfig, {
stats: {
colors: true,
hash: true,
timings: true,
assets: true,
chunks: false,
chunkModules: false,
modules: false,
children: false,
warnings: true,
},
optimization: {
minimize: true,
sideEffects: false,
},
output: {
path: ROOT_DIR,
library: 'ohif-ui',
libraryTarget: 'umd',
filename: pkg.main,
},
externals: [
/\b(dcmjs)/,
/\b(gl-matrix)/,
{
react: 'React',
'react-dom': 'ReactDOM',
},
],
plugins: [
new MiniCssExtractPlugin({
filename: `./dist/${outputName}.css`,
chunkFilename: `./dist/${outputName}.css`,
}),
// new BundleAnalyzerPlugin({}),
],
});
};

View File

@ -2,9 +2,22 @@
"name": "@ohif/ui-next",
"version": "3.9.0-beta.58",
"description": "Next version of OHIF Viewers UI, more customizable using shadcn/ui",
"main": "index.ts",
"main": "dist/ohif-ui-next.umd.js",
"module": "src/index.ts",
"publishConfig": {
"access": "public"
},
"files": [
"dist",
"README.md"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"clean": "rm -rf node_modules/.cache/storybook && shx rm -rf dist",
"clean:deep": "yarn run clean && shx rm -rf node_modules",
"start": "yarn run build --watch",
"test": "echo \"Error: no test specified\" && exit 1",
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
"build:package": "yarn run build"
},
"exports": {
"./tailwind.config": "./tailwind.config.ts",

1701
yarn.lock

File diff suppressed because it is too large Load Diff