From 89380353d270cbb89d0c60290a1210f7ac8baa7a Mon Sep 17 00:00:00 2001 From: Erik Ziegler Date: Thu, 26 Sep 2019 11:35:13 +0200 Subject: [PATCH] fix: Add some code splitting for PWA build (#937) * fix: Add some code splitting for PWA build * Fix missing files --- .../cornerstone/.webpack/webpack.prod.js | 6 +++ extensions/cornerstone/src/asyncComponent.js | 37 +++++++++++++ extensions/cornerstone/src/index.js | 4 +- .../dicom-html/.webpack/webpack.prod.js | 6 +++ extensions/dicom-html/src/asyncComponent.js | 37 +++++++++++++ extensions/dicom-html/src/index.js | 10 +++- .../dicom-microscopy/.webpack/webpack.prod.js | 6 +++ .../src/DicomMicroscopyViewport.js | 8 +-- .../dicom-microscopy/src/asyncComponent.js | 37 +++++++++++++ extensions/dicom-microscopy/src/index.js | 8 ++- extensions/vtk/.webpack/webpack.prod.js | 6 +++ extensions/vtk/src/asyncComponent.js | 37 +++++++++++++ extensions/vtk/src/index.js | 6 ++- platform/viewer/.webpack/webpack.commonjs.js | 4 ++ platform/viewer/src/OHIFStandaloneViewer.js | 54 +++++++++++-------- 15 files changed, 236 insertions(+), 30 deletions(-) create mode 100644 extensions/cornerstone/src/asyncComponent.js create mode 100644 extensions/dicom-html/src/asyncComponent.js create mode 100644 extensions/dicom-microscopy/src/asyncComponent.js create mode 100644 extensions/vtk/src/asyncComponent.js diff --git a/extensions/cornerstone/.webpack/webpack.prod.js b/extensions/cornerstone/.webpack/webpack.prod.js index cd89dfcd2..ca612cd37 100644 --- a/extensions/cornerstone/.webpack/webpack.prod.js +++ b/extensions/cornerstone/.webpack/webpack.prod.js @@ -1,3 +1,4 @@ +const webpack = require('webpack'); const merge = require('webpack-merge'); const path = require('path'); const webpackCommon = require('./../../../.webpack/webpack.commonjs.js'); @@ -34,5 +35,10 @@ module.exports = (env, argv) => { libraryExport: 'default', filename: pkg.main, }, + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }), + ], }); }; diff --git a/extensions/cornerstone/src/asyncComponent.js b/extensions/cornerstone/src/asyncComponent.js new file mode 100644 index 000000000..e8f344a35 --- /dev/null +++ b/extensions/cornerstone/src/asyncComponent.js @@ -0,0 +1,37 @@ +/** + * We use this component to leverage "Code Splitting" + * + * Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html + */ + +import React, { Component } from 'react'; + +export default function asyncComponent(importComponent) { + class AsyncComponent extends Component { + constructor(props) { + super(props); + + this.state = { + component: null, + }; + } + + async componentDidMount() { + // Add dynamically loaded component to state + const { default: component } = await importComponent(); + + this.setState({ + component: component, + }); + } + + render() { + const C = this.state.component; + + // Render the loaded component, or null + return C ? : null; + } + } + + return AsyncComponent; +} diff --git a/extensions/cornerstone/src/index.js b/extensions/cornerstone/src/index.js index b148fa2e7..fdca6c28e 100644 --- a/extensions/cornerstone/src/index.js +++ b/extensions/cornerstone/src/index.js @@ -1,7 +1,9 @@ -import OHIFCornerstoneViewport from './OHIFCornerstoneViewport.js'; +import asyncComponent from './asyncComponent.js'; import commandsModule from './commandsModule.js'; import toolbarModule from './toolbarModule.js'; +const OHIFCornerstoneViewport = asyncComponent(() => import( /* webpackChunkName: "OHIFCornerstoneViewport" */ './OHIFCornerstoneViewport.js')); + /** * */ diff --git a/extensions/dicom-html/.webpack/webpack.prod.js b/extensions/dicom-html/.webpack/webpack.prod.js index 8a8a33b08..69daae248 100644 --- a/extensions/dicom-html/.webpack/webpack.prod.js +++ b/extensions/dicom-html/.webpack/webpack.prod.js @@ -1,3 +1,4 @@ +const webpack = require('webpack'); const merge = require('webpack-merge'); const path = require('path'); const webpackCommon = require('./../../../.webpack/webpack.commonjs.js'); @@ -34,5 +35,10 @@ module.exports = (env, argv) => { libraryExport: 'default', filename: pkg.main, }, + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }), + ], }); }; diff --git a/extensions/dicom-html/src/asyncComponent.js b/extensions/dicom-html/src/asyncComponent.js new file mode 100644 index 000000000..e8f344a35 --- /dev/null +++ b/extensions/dicom-html/src/asyncComponent.js @@ -0,0 +1,37 @@ +/** + * We use this component to leverage "Code Splitting" + * + * Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html + */ + +import React, { Component } from 'react'; + +export default function asyncComponent(importComponent) { + class AsyncComponent extends Component { + constructor(props) { + super(props); + + this.state = { + component: null, + }; + } + + async componentDidMount() { + // Add dynamically loaded component to state + const { default: component } = await importComponent(); + + this.setState({ + component: component, + }); + } + + render() { + const C = this.state.component; + + // Render the loaded component, or null + return C ? : null; + } + } + + return AsyncComponent; +} diff --git a/extensions/dicom-html/src/index.js b/extensions/dicom-html/src/index.js index c49488f4c..216b377dd 100644 --- a/extensions/dicom-html/src/index.js +++ b/extensions/dicom-html/src/index.js @@ -1,5 +1,11 @@ +import asyncComponent from './asyncComponent.js'; import OHIFDicomHtmlSopClassHandler from './OHIFDicomHtmlSopClassHandler.js'; -import OHIFDicomHtmlViewport from './OHIFDicomHtmlViewport.js'; + +const OHIFDicomHtmlViewport = asyncComponent(() => + import( + /* webpackChunkName: "OHIFDicomHtmlViewport" */ './OHIFDicomHtmlViewport.js' + ) +); export default { /** @@ -12,5 +18,5 @@ export default { }, getSopClassHandlerModule() { return OHIFDicomHtmlSopClassHandler; - } + }, }; diff --git a/extensions/dicom-microscopy/.webpack/webpack.prod.js b/extensions/dicom-microscopy/.webpack/webpack.prod.js index 8c67e4a18..2bb8aa052 100644 --- a/extensions/dicom-microscopy/.webpack/webpack.prod.js +++ b/extensions/dicom-microscopy/.webpack/webpack.prod.js @@ -1,3 +1,4 @@ +const webpack = require('webpack'); const merge = require('webpack-merge'); const path = require('path'); const webpackCommon = require('./../../../.webpack/webpack.commonjs.js'); @@ -34,5 +35,10 @@ module.exports = (env, argv) => { libraryExport: 'default', filename: pkg.main, }, + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }) + ] }); }; diff --git a/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js b/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js index 50ebaf3ac..0e534c339 100644 --- a/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js +++ b/extensions/dicom-microscopy/src/DicomMicroscopyViewport.js @@ -1,10 +1,7 @@ import React, { Component } from 'react'; import ReactResizeDetector from 'react-resize-detector'; -import { api } from 'dicom-microscopy-viewer'; import debounce from 'lodash.debounce'; -const microscopyViewer = api.VLWholeSlideMicroscopyImageViewer; - class DicomMicroscopyViewport extends Component { state = { error: null, @@ -56,9 +53,12 @@ class DicomMicroscopyViewport extends Component { } return Promise.all(promises); }) - .then(metadata => { + .then(async metadata => { metadata = metadata.filter(m => m); + const { api } = await import(/* webpackChunkName: "dicom-microscopy-viewer" */ 'dicom-microscopy-viewer'); + const microscopyViewer = api.VLWholeSlideMicroscopyImageViewer; + this.viewer = new microscopyViewer({ client: dicomWebClient, metadata, diff --git a/extensions/dicom-microscopy/src/asyncComponent.js b/extensions/dicom-microscopy/src/asyncComponent.js new file mode 100644 index 000000000..e8f344a35 --- /dev/null +++ b/extensions/dicom-microscopy/src/asyncComponent.js @@ -0,0 +1,37 @@ +/** + * We use this component to leverage "Code Splitting" + * + * Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html + */ + +import React, { Component } from 'react'; + +export default function asyncComponent(importComponent) { + class AsyncComponent extends Component { + constructor(props) { + super(props); + + this.state = { + component: null, + }; + } + + async componentDidMount() { + // Add dynamically loaded component to state + const { default: component } = await importComponent(); + + this.setState({ + component: component, + }); + } + + render() { + const C = this.state.component; + + // Render the loaded component, or null + return C ? : null; + } + } + + return AsyncComponent; +} diff --git a/extensions/dicom-microscopy/src/index.js b/extensions/dicom-microscopy/src/index.js index 2ec002069..604b8a0dc 100644 --- a/extensions/dicom-microscopy/src/index.js +++ b/extensions/dicom-microscopy/src/index.js @@ -1,5 +1,11 @@ +import asyncComponent from './asyncComponent.js'; import DicomMicroscopySopClassHandler from './DicomMicroscopySopClassHandler.js'; -import DicomMicroscopyViewport from './DicomMicroscopyViewport.js'; + +const DicomMicroscopyViewport = asyncComponent(() => + import( + /* webpackChunkName: "DicomMicroscopyViewport" */ './DicomMicroscopyViewport.js' + ) +); export default { /** diff --git a/extensions/vtk/.webpack/webpack.prod.js b/extensions/vtk/.webpack/webpack.prod.js index ea474543e..8444e0d2d 100644 --- a/extensions/vtk/.webpack/webpack.prod.js +++ b/extensions/vtk/.webpack/webpack.prod.js @@ -1,3 +1,4 @@ +const webpack = require('webpack'); const merge = require('webpack-merge'); const path = require('path'); const webpackCommon = require('./../../../.webpack/webpack.commonjs.js'); @@ -34,5 +35,10 @@ module.exports = (env, argv) => { libraryExport: 'default', filename: pkg.main, }, + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }), + ], }); }; diff --git a/extensions/vtk/src/asyncComponent.js b/extensions/vtk/src/asyncComponent.js new file mode 100644 index 000000000..e8f344a35 --- /dev/null +++ b/extensions/vtk/src/asyncComponent.js @@ -0,0 +1,37 @@ +/** + * We use this component to leverage "Code Splitting" + * + * Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html + */ + +import React, { Component } from 'react'; + +export default function asyncComponent(importComponent) { + class AsyncComponent extends Component { + constructor(props) { + super(props); + + this.state = { + component: null, + }; + } + + async componentDidMount() { + // Add dynamically loaded component to state + const { default: component } = await importComponent(); + + this.setState({ + component: component, + }); + } + + render() { + const C = this.state.component; + + // Render the loaded component, or null + return C ? : null; + } + } + + return AsyncComponent; +} diff --git a/extensions/vtk/src/index.js b/extensions/vtk/src/index.js index ec2674f72..6f2cfc5ff 100644 --- a/extensions/vtk/src/index.js +++ b/extensions/vtk/src/index.js @@ -1,9 +1,13 @@ -import OHIFVTKViewport from './OHIFVTKViewport.js'; +import asyncComponent from './asyncComponent.js'; import commandsModule from './commandsModule.js'; import toolbarModule from './toolbarModule.js'; // This feels weird // import loadLocales from './loadLocales'; +const OHIFVTKViewport = asyncComponent(() => + import(/* webpackChunkName: "OHIFVTKViewport" */ './OHIFVTKViewport.js') +); + const vtkExtension = { /** * Only required property. Should be a unique value across all extensions. diff --git a/platform/viewer/.webpack/webpack.commonjs.js b/platform/viewer/.webpack/webpack.commonjs.js index 7a2c07e08..f54ebb35e 100644 --- a/platform/viewer/.webpack/webpack.commonjs.js +++ b/platform/viewer/.webpack/webpack.commonjs.js @@ -1,3 +1,4 @@ +const webpack = require('webpack'); const path = require('path'); const merge = require('webpack-merge'); const webpackCommon = require('./../../../.webpack/webpack.commonjs.js'); @@ -54,6 +55,9 @@ module.exports = (env, argv) => { template: `${PUBLIC_DIR}/html-templates/${HTML_TEMPLATE}`, filename: 'index.html', }), + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }) ], }); }; diff --git a/platform/viewer/src/OHIFStandaloneViewer.js b/platform/viewer/src/OHIFStandaloneViewer.js index 9d6bdd685..c7674253f 100644 --- a/platform/viewer/src/OHIFStandaloneViewer.js +++ b/platform/viewer/src/OHIFStandaloneViewer.js @@ -7,13 +7,7 @@ import { CSSTransition } from 'react-transition-group'; import { connect } from 'react-redux'; import { ViewerbaseDragDropContext } from '@ohif/ui'; import { SignoutCallbackComponent } from 'redux-oidc'; -// import asyncComponent from './components/AsyncComponent.js' -import IHEInvokeImageDisplay from './routes/IHEInvokeImageDisplay.js'; -import ViewerRouting from './routes/ViewerRouting.js'; -import ViewerLocalFileData from './connectedComponents/ViewerLocalFileData.js'; -import StudyListRouting from './studylist/StudyListRouting.js'; -import StandaloneRouting from './routes/StandaloneRouting.js'; -import CallbackPage from './routes/CallbackPage.js'; +import asyncComponent from './components/AsyncComponent.js'; import NotFound from './routes/NotFound.js'; import { Bar, Container } from './components/LoadingBar/'; import './OHIFStandaloneViewer.css'; @@ -24,18 +18,32 @@ import './theme-tide.css'; import AppContext from './context/AppContext'; // Dynamic Import Routes (CodeSplitting) -// const IHEInvokeImageDisplay = asyncComponent(() => -// import('./routes/IHEInvokeImageDisplay.js') -// ) -// const ViewerRouting = asyncComponent(() => import('./routes/ViewerRouting.js')) -// const StudyListRouting = asyncComponent(() => -// import('./studylist/StudyListRouting.js') -// ) -// const StandaloneRouting = asyncComponent(() => -// import('./routes/StandaloneRouting.js') -// ) -// const CallbackPage = asyncComponent(() => import('./CallbackPage.js')) -// +const IHEInvokeImageDisplay = asyncComponent(() => + import( + /* webpackChunkName: "IHEInvokeImageDisplay" */ './routes/IHEInvokeImageDisplay.js' + ) +); +const ViewerRouting = asyncComponent(() => + import(/* webpackChunkName: "ViewerRouting" */ './routes/ViewerRouting.js') +); +const StudyListRouting = asyncComponent(() => + import( + /* webpackChunkName: "StudyListRouting" */ './studylist/StudyListRouting.js' + ) +); +const StandaloneRouting = asyncComponent(() => + import( + /* webpackChunkName: "StandaloneRouting" */ './routes/StandaloneRouting.js' + ) +); +const CallbackPage = asyncComponent(() => + import(/* webpackChunkName: "CallbackPage" */ './routes/CallbackPage.js') +); +const ViewerLocalFileData = asyncComponent(() => + import( + /* webpackChunkName: "ViewerLocalFileData" */ './connectedComponents/ViewerLocalFileData.js' + ) +); const reload = () => window.location.reload(); @@ -188,10 +196,14 @@ class OHIFStandaloneViewer extends Component { classNames="fade" unmountOnExit onEnter={() => { - this.setState({ isLoading: true }); + this.setState({ + isLoading: true, + }); }} onEntered={() => { - this.setState({ isLoading: false }); + this.setState({ + isLoading: false, + }); }} > {match === null ? (