cornerstonejs / cornerstone3D

Cornerstone is a set of JavaScript libraries that can be used to build web-based medical imaging applications. It provides a framework to build radiology applications such as the OHIF Viewer.
https://cornerstonejs.org
MIT License
522 stars 270 forks source link

Vite run example code with problem #594

Open pzq123456 opened 1 year ago

pzq123456 commented 1 year ago
sedghi commented 1 year ago

I'm not following what you are saying here. Do you get an error when installing cornerstone3d?

pzq123456 commented 1 year ago

- I simply run the code using vite (`npm run dev`), but the medical image was not displayed (just the background), and the console showed the following error message:
![](https://user-images.githubusercontent.com/82391775/235963261-506846fb-d138-4e49-9f23-147d7fc7de34.jpg)
kasoushu commented 1 year ago

i have this error

[vite] Internal server error: Failed to resolve entry for package "@cornerstonejs/dicom-image-loader". The package may have incorrect main/module/exports specified in its package.json.
sedghi commented 1 year ago

@pzq123456 Do you have a repo to share? I can't debug this with one file that you shared

kasoushu commented 1 year ago

@sedghi I follow what he says,and get same error,here is all code shared by google drive, image

system enviroment image

https://drive.google.com/file/d/1sUDJ9auKSB9LfvoOAvE6UsLpmJ9cLm7P/view?usp=sharing

sedghi commented 1 year ago

@kasoushu it looks like the webworkers are not getting correctly recognized by vite. we have this in OHIF that we copy them into the dist but not sure what is the equivalent in vite

sedghi commented 1 year ago

@pzq123456 I'm getting errors regarding element-plus in your master branch

Error: The following dependencies are imported but could not be resolved:

element-plus/es/locale (imported by /Users/alireza/dev/forks/MIP/MIP_project/src/views/Table.vue?id=0)

pzq123456 commented 1 year ago

@pzq123456 I'm getting errors regarding element-plus in your master branch

Error: The following dependencies are imported but could not be resolved:

element-plus/es/locale (imported by /Users/alireza/dev/forks/MIP/MIP_project/src/views/Table.vue?id=0)

This respository just foucs on the problem.

pzq123456 commented 1 year ago

New problem after solving the first one

When I find those missing files, I put them in the src folder and run the code again. The error is like this:

decodeImageFrame.ts:266  Uncaught (in promise) ReferenceError: SharedArrayBuffer is not defined

    at decodeImageFrame.ts:266:51
    at U (decodeImageFrame.ts:154:25)
    at async Object.handler (decodeTask.ts:51:9)

In :

sedghi commented 1 year ago

I guess that is one way, but you shouldn't need to do that and vite should be able to locate them and for some reason it can't. for the SharedArrayBuffer error you need to set some headers to enable them for security purposes

https://developer.chrome.com/blog/enabling-shared-array-buffer/#cross-origin-isolation

you can look into our webpack configuration

devServer: {
    hot: true,
    open: false,
    port: 3000,
    historyApiFallback: true,
    headers: {
      "Cross-Origin-Embedder-Policy": "require-corp",
      "Cross-Origin-Opener-Policy": "same-origin"
    }
  },

specifically

headers: { "Cross-Origin-Embedder-Policy": "require-corp", "Cross-Origin-Opener-Policy": "same-origin" }

pzq123456 commented 1 year ago

I guess that is one way, but you shouldn't need to do that and vite should be able to locate them and for some reason it can't. for the SharedArrayBuffer error you need to set some headers to enable them for security purposes

https://developer.chrome.com/blog/enabling-shared-array-buffer/#cross-origin-isolation

you can look into our webpack configuration

devServer: {
    hot: true,
    open: false,
    port: 3000,
    historyApiFallback: true,
    headers: {
      "Cross-Origin-Embedder-Policy": "require-corp",
      "Cross-Origin-Opener-Policy": "same-origin"
    }
  },

specifically

headers: { "Cross-Origin-Embedder-Policy": "require-corp", "Cross-Origin-Opener-Policy": "same-origin" }

This works for me. Thanks for your help.

sedghi commented 1 year ago

can you post the solution for the final vite config here please for future references

pzq123456 commented 1 year ago

can you post the solution for the final vite config here please for future references

// vite.config.js
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      '@cornerstonejs/dicom-image-loader': '@cornerstonejs/dicom-image-loader/dist/dynamic-import/cornerstoneDICOMImageLoader.min.js',
    }
  },
  // config settings for dev server
  server: {
    headers: {
      'Cross-Origin-Opener-Policy': 'same-origin',
      'Cross-Origin-Embedder-Policy': 'require-corp',
    },

    //
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    }
  },
})
pzq123456 commented 1 year ago

cornerstone3D-vite config problem and one possible solution

Thanks for the help from sedghi There must be some more elegant solutions, but this is the one worked for me. If you have any better ideas, please let me know in the issue or PR.

Background

see the related issue in cornerstone3D-beta. When we use vite to run the example code, we can't get the webworker-file and the error is like this:

:5173/src/index.worker.ea71efba2ce63c499055.worker.js:1 
Failed to load resource: the server responded with a status of 404 (Not Found)
:5173/src/index.worker.ea71efba2ce63c499055.worker.js:1 

It looks like the vite can't find the webworker-file. In the dicom-image-loader package, we can find that the worker files have been built in the dynamic-import folder.

New problem after solving the first one

When I find those missing files, I put them in the src folder and run the code again. The error is like this:

decodeImageFrame.ts:266  Uncaught (in promise) ReferenceError: SharedArrayBuffer is not defined
    at decodeImageFrame.ts:266:51
    at U (decodeImageFrame.ts:154:25)
    at async Object.handler (decodeTask.ts:51:9)

Project Setup

npm install

Compile and Hot-Reload for Development

npm run dev

Compile and Minify for Production

npm run build
obiyoag commented 1 year ago

I've got another way to fix this while keeping the src folder clean.

  1. Find the file node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/cornerstoneDICOMImageLoader.min.js.
  2. Locate the line with string "index.worker.ea71efba2ce63c499055.worker.js".
  3. Change the code from
    return new Worker(r.p+"index.worker.ea71efba2ce63c499055.worker.js";

    to

    return new Worker("http://localhost:5173/node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/"+"index.worker.ea71efba2ce63c499055.worker.js";
schopdekar commented 1 year ago

@pzq123456 I am stuck with this issue stating "Uncaught_ReferenceError" whenever I am running the docker image for the code cloned from your repo https://github.com/pzq123456/viteProblem

It is working fine on localhost. Also there are no errors while building the docker.

Can you please help??

I am creating a docker image using attached docker file and default.conf file.

image image

Zip file for docker file and default.conf file. Archive.zip

Steps to Reproduce:

  1. Clone the code from the given github branch
  2. Add the given Dockerfile and default.conf file
  3. execute docker build command and then docker run command docker build: docker build -t wb_tool_frontend:wb_tool_frontend . docker run: docker run -it -d -p 8080:80 wb_tool_frontend:wb_tool_frontend
schopdekar commented 1 year ago

@sedghi Regarding the above issue. While troubleshooting I found that even if I comment the other steps and just run the initDemo() function it start giving this issue. If I comment the entire run function, related imports and just create html elements the docker works fine.

schopdekar commented 1 year ago

Hi Folks,

I was finally able to solve the referenceError issue by manually changing the index.js file in the dist folder created after build. Couldn't find the root cause. I changed the sequence of variable declaration and usage to solve the error. Modified the docker file to copy local dist folder which is updated.

After fixing, this I got a new error with the web worker. Apparently the index.worker.js is getting the index.html file and is throwing an unexpected token error. I moved the webworker files and corresponding wasm files in the dist assets folder which solved this issue.

Currently I am facing the same "SharedArrayBuffer not defined" issue mentioned earlier in this chain. I am using ngninx in my docker file which looks like this:

FROM node:lts-alpine as build-stage

WORKDIR /app COPY . . COPY ./dist /app/dist

FROM nginx:stable-alpine as production-stage COPY --from=build-stage /app/dist /usr/share/nginx/html COPY default.conf /etc/nginx/conf.d/ EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]

default.conf looks like this:

server { listen 80; listen [::]:80; server_name localhost;

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
}
error_page   500 502 503 504  /50x.html;
location = /50x.html {
    root   /usr/share/nginx/html;
}

}

As mentioned earlier the vite config is already implemented as per the give solution.

@sedghi can you please help with this one?

schopdekar commented 1 year ago

Hello,

Issue Resolved!!

Thanks @sedghi

Adding this lines to the default config of the nginx solved the issue. add_header Cross-Origin-Opener-Policy same-origin; add_header Cross-Origin-Embedder-Policy require-corp;

Reference docs: https://docs.ohif.org/deployment/cors https://docs.ohif.org/deployment/docker

This is how default.conf file looks now:

server { listen 80; listen [::]:80; server_name localhost;

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    add_header "Access-Control-Allow-Origin"  *;
    add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS, HEAD";
    add_header "Access-Control-Allow-Headers" "Authorization, X-Authorization, Origin, X-Requested-With, Content-Type, Accept";
    add_header Cross-Origin-Opener-Policy same-origin;
    add_header Cross-Origin-Embedder-Policy require-corp;
    try_files $uri $uri/ /index.html;
}

error_page   500 502 503 504  /50x.html;
location = /50x.html {
    root   /usr/share/nginx/html;
}

}

wolixx commented 1 year ago

I've got another way to fix this while keeping the src folder clean.

  1. Find the file node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/cornerstoneDICOMImageLoader.min.js.
  2. Locate the line with string "index.worker.ea71efba2ce63c499055.worker.js".
  3. Change the code from
return new Worker(r.p+"index.worker.ea71efba2ce63c499055.worker.js";

to

return new Worker("http://localhost:5173/node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/"+"index.worker.ea71efba2ce63c499055.worker.js";

Excuse me, do you have any other correct solution, without polluting src?

wolixx commented 1 year ago

I've got another way to fix this while keeping the src folder clean.

  1. Find the file node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/cornerstoneDICOMImageLoader.min.js.
  2. Locate the line with string "index.worker.ea71efba2ce63c499055.worker.js".
  3. Change the code from
return new Worker(r.p+"index.worker.ea71efba2ce63c499055.worker.js";

to

return new Worker("http://localhost:5173/node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/"+"index.worker.ea71efba2ce63c499055.worker.js";

@sedghi Hello, I'd like to know why xxx.worker.js in the src directory in Vite,but in webpack, it's under static/js.How did you decide that?What is r.p?

sedghi commented 1 year ago

in webpack we have copy plugin to copy web workers to the build directory, maybe that is something you need to figure out in vite

https://github.com/cornerstonejs/cornerstone3D/blob/main/utils/ExampleRunner/template-config.js#L46-L54

wolixx commented 1 year ago

1.Firstly, I have successfully in another project(React with Webpack),and it requested /static/js/index.worker.xxx.worker.js. image

2.I also succeeded here(React with Vite),but it requested /src/index.worker.xxx.worker.js. image

3.After I pnpm run build the project,the index.worker.xxx.worker.js appear at src/... , so it will be ok,i can get the worker.js.But it pollute the src.

4.So,how can I solve this problem? And ,why the 'worker.js' it will be get /static/js or src/ ???

sedghi commented 1 year ago

I'm not sure about your setup and why you need it to be at dist/static/js it doesn't makes sense to me if you are serving it from /

In any how your dev server (similar for prod) should have the worker

as below for http://localhost:3000/webpack-dev-server

similarly for wasm files too

image

qlingsu commented 10 months ago

1.Firstly, I have successfully in another project(React with Webpack),and it requested /static/js/index.worker.xxx.worker.js. image

2.I also succeeded here(React with Vite),but it requested /src/index.worker.xxx.worker.js. image

3.After I pnpm run build the project,the index.worker.xxx.worker.js appear at src/... , so it will be ok,i can get the worker.js.But it pollute the src.

4.So,how can I solve this problem? And ,why the 'worker.js' it will be get /static/js or src/ ???

I use it like this: viteStaticCopy({ targets: [ { src: './src/libs/cornerstone3D/dicomImageLoader/dist/dynamic-import/**', dest: "./src" }, ], }), it worked .but when I download workers it encouter net::ERR_BLOCKED_BY_RESPONSE. so I make a directionary "src" in "public" and copy all files which in dicomImageLoader/dist/dynamic-import/ to “public/src”, it worked

shunia commented 9 months ago

I believe I have found the ultimate solution for both development and production environments without the hassels:

For dev:

// vite.config.ts
export default defineConfig({
   // your other configs 
  ...{},
  // modify server to add cross-origin related headers
  ...{
    server: {
      headers: {
        "Cross-Origin-Embedder-Policy": "require-corp",
        "Cross-Origin-Opener-Policy": "same-origin",
      }
    }
  },
  // modify proxy server to delegate request to dynamic loaded assets to node_modules
  ...{
    proxy: {
      // this will cover all the dynamic loaded assets cornerstone requires for image-loader to work
      ...["^/.wasm/", "^/worker.js/", "/src/index.worker"].reduce(
          (prev, current) => {
            prev[current] = {
              // remember to modify the port according to your dev server config
              target: "http://localhost:5173/node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import",
              rewrite(path) {
                // the /src pathname will be appended to the proxied url, which has to be removed
                return path.replace(/^\/src/, "");
              },
            };
            return prev;
          },
          {}
        )
    }
  }
});

For prod:

// I've compared some alternative copy plugins and find out that this might be the best fit here
import cp from 'vite-plugin-cp';

export default defineConfig({
   // your other configs 
  ...{},
  // add a copy plugin to re-locate the dynamic assets into the dist folder
  ...{
    plugins: [
      // your original plugins
      ...[],
      // use cp to re-locate the files
      cp({
        targets: [
          {
            src: "node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/*",
            dest: "dist",
          },
        ],
      }),
    ],
  }
});

Feel free to modify the variables like port and dist folder accordingly.

And make sure you don't provide a partial config to webWorkerManager.initialize like I did by following the README.md in packages/dicomImageLoader.

sedghi commented 2 months ago

I'm working on cornerstone3D 2.x and have made progress in removing circular dependencies and publishing the types for the DICOM image loader. I'm trying to make it work with Vite, but there are numerous issues with Vite in dev mode, which are not directly related to Cornerstone. Multiple mentions of Vite problems with import.meta.url, web workers, and WebAssembly can be found on the Vite GitHub repository:

https://github.com/vitejs/vite/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+import.meta.url

I have started a template project for Vite, React, and cornerstone3D beta 2.x here. I appreciate your help in making it work.

https://github.com/cornerstonejs/vite-react-cornerstone3d

kenny-reyes commented 1 month ago

Workaorund this here