Kitware / itk-vtk-viewer

2D / 3D web image, mesh, and point set viewer using itk-wasm and vtk.js
https://kitware.github.io/itk-vtk-viewer/
BSD 3-Clause "New" or "Revised" License
210 stars 63 forks source link

Importing workers with webpack. #387

Open phcerdan opened 3 years ago

phcerdan commented 3 years ago

I had problems loading the workers:

Loading Worker from “http://localhost:8080/itk/WebWorkers/ImageIO.worker.js” was blocked because of a disallowed MIME type (“text/html”).

Following docs from itkjs, the following works using npm install --save-dev copy-webpack-plugin


const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  // ...
  plugins: [
    new CopyPlugin({
      patterns: [
        {
          from: path.join(__dirname, 'node_modules', 'itk-vtk-viewer', 'dist', 'itk'),
          to: path.join(__dirname, "dist", 'itk')
        },
      ]
    }),
  ],
  // To work with webpack-dev-server:
  devServer: {
    writeToDisk: true,
  },
  // ...

Not sure if this is the standard way of doing it, reporting here just in case it's worth to document, or if there is another solution.

thewtex commented 3 years ago

@phcerdan thanks for the note!

Did you observe this requirement when building itk-vtk-viewer, or building a project that uses itk-vtk-viewer as a node dependency?

phcerdan commented 3 years ago

The later:

building a project that uses itk-vtk-viewer as a node dependency

thewtex commented 3 years ago

We should add documentation for how to use itk-vtk-viewer as a dependency.

@jourdain also has a few good ideas/examples on how to use webpack-chain.

jourdain commented 3 years ago

Ideally we should have the following files inside each project so we can import and use them directly

(Caution: Some path resolution will be wrong if those files get placed in their repo)

itkChain.js

const path = require('path');

const root  = path.resolve(__dirname, '..');
const pathsToCopy = [
  {
    from: path.join(root, 'node_modules', 'itk', 'WebWorkers'),
    to: path.join(root, 'dist', 'itk', 'WebWorkers'),
  },
  {
    from: path.join(root, 'node_modules', 'itk', 'ImageIOs'),
    to: path.join(root, 'dist', 'itk', 'ImageIOs'),
  },
  {
    from: path.join(root, 'node_modules', 'itk', 'MeshIOs'),
    to: path.join(root, 'dist', 'itk', 'MeshIOs'),
  },
  {
    from: path.join(root, 'node_modules', 'itk', 'PolyDataIOs'),
    to: path.join(root, 'dist', 'itk', 'PolyDataIOs'),
  },
  {
    from: path.join(root, 'node_modules', 'itk', 'Pipelines'),
    to: path.join(root, 'dist', 'itk', 'Pipelines'),
  },
  {
    from: path.join(
      root,
      'node_modules', 'itk-vtk-viewer',
      'src',
      'Compression',
      'blosc-zarr',
      'web-build'
    ),
    to: path.join(root, 'dist', 'itk', 'Pipelines'),
  },
  {
    from: path.join(root, 'node_modules', 'itk-vtk-viewer', 'src', 'IO', 'Downsample', 'web-build'),
    to: path.join(root, 'dist', 'itk', 'Pipelines'),
  },
];

module.exports = function chainWebpack(config) {
  config
    .plugin('copy')
    .tap(args => {
      for (let i = 0; i < pathsToCopy.length; i++) {
        args[0].push(pathsToCopy[i]);
      }
      return args;
    });
}

itkVtkViewerChain.js

module.exports = function chainWebpack(config) {
  config.module
    .rule('itk-viewer-js')
    .test(/\.js$/i)
    .include.add(/itk-vtk-viewer[/\\]src/)
    .end()
    .use('babel-loader')
    .loader('babel-loader')
    .end();

  config.module
    .rule('itk-viewer-worker')
    .test(/\.worker\.js$/)
    .include.add(/itk-vtk-viewer[/\\]src/)
    .end()
    .use('worker-loader')
    .loader('worker-loader')
    .options({ inline: true })
    .end();
}

I don't remember why I did not used the one in vtk.js/Utilities/config/chainWebpack

vtkChain.js

module.exports = function chainWebpack(config) {
  config.module
    .rule('vtk-glsl')
    .test(/\.glsl$/i)
    .include.add(/vtk\.js[/\\]Sources/)
    .end()
    .use('shader-loader')
    .loader('shader-loader')
    .end();

  config.module
    .rule('vtk-js')
    .test(/\.js$/i)
    .include.add(/vtk\.js[/\\]Sources/)
    .end()
    .use('babel-loader')
    .loader('babel-loader')
    .end();

  config.module
    .rule('vtk-worker')
    .test(/\.worker\.js$/)
    .include.add(/vtk\.js[/\\]Sources/)
    .end()
    .use('worker-loader')
    .loader('worker-loader')
    .options({ inline: true })
    .end();

  config.module
    .rule('vtk-css')
    .test(/\.css$/)
    .exclude.add(/\.module\.css$/)
    .end()
    .include.add(/vtk\.js[/\\]Sources/)
    .end()
    .use('styles')
    .loader('style-loader')
    .loader('css-loader')
    .loader('postcss-loader')
    .end();

  config.module
    .rule('vtk-svg')
    .test(/\.svg$/)
    .include.add(/vtk\.js[/\\]Sources/)
    .end()
    .use('raw-loader')
    .loader('raw-loader')
    .end();

  config.module
    .rule('svg')
    .exclude.add(/vtk\.js[/\\]Sources/)
    .end();

  config.module
    .rule('vtk-module-css')
    .test(/\.css$/)
    .include.add(/vtk\.js[/\\]Sources/)
    .add(/\.module\.css$/)
    .end()
    .use('styles')
    .loader('style-loader')
    .loader('css-loader')
    .options({
      modules: {
        localIdentName: '[name]-[local]_[sha512:hash:base64:5]',
      },
    })
    .loader('postcss-loader')
    .end();
}

Then in my vue.config.js

// const vtkChainWebpack = require('vtk.js/Utilities/config/chainWebpack');
const itkViewChainWebpack = require('./config/chainItkVtkViewer');
const itkChainWebpack = require('./config/chainItk');
const vtkChainWebpack = require('./config/chainVTK');

module.exports = {
  chainWebpack: (config) => {
    vtkChainWebpack(config);
    itkViewChainWebpack(config);
    itkChainWebpack(config);
  },
};