partridgejiang / Kekule.js

A Javascript cheminformatics toolkit.
http://partridgejiang.github.io/Kekule.js
MIT License
248 stars 61 forks source link

Issue with vite builder for React app #308

Closed JackDra closed 1 year ago

JackDra commented 1 year ago

Our app needed to update from webpack 4 to vite, and I am having trouble trying to get Kekule imported into our application.

Any import Kekule (version 1.0.0) is throwing the exception:

 FAIL  src/.../Molecule3DViewer.test.jsx
  ● Test suite failed to run

    TypeError: Invalid URL: /PATH_TO_APP/node_modules/kekule/dist/kekule.moduleEnvInits.cm.js

      19 | import * as THREE from "three";
    > 20 | import { Kekule } from 'kekule';
         | ^
      21 |

      at new URLImpl (node_modules/whatwg-url/lib/URL-impl.js:21:13)
      at Object.exports.setup (node_modules/whatwg-url/lib/URL.js:54:12)
      at new URL (node_modules/whatwg-url/lib/URL.js:115:22)
      at setEnvFromModuleUrl (node_modules/kekule/dist/kekule.moduleEnvInits.cm.js:20:11)
      at node_modules/kekule/dist/kekule.moduleEnvInits.cm.js:34:3
      at Object.<anonymous> (node_modules/kekule/dist/kekule.moduleEnvInits.cm.js:48:3)
      at Object.<anonymous> (node_modules/kekule/dist/kekule.cm.js:1:36)
      at Object.require (src/components/Reagents/Molecule3DViewer.jsx:20:1)
      at Object.require (src/components/Reagents/Molecule3DViewer.test.jsx:13:1)

I can fix the import by modifying this line https://github.com/partridgejiang/Kekule.js/blob/153e75b46379f4aba99ce5129ffdf96a1625b9b2/src/kekule.moduleEnvInits.cm.js#L30 to be:

var moduleUrl = `file://${__filename}`;

so that it can be parsed by URL. But after doing this, the 3D viewer fails when painting:

failing lines:

    // initiate Kekule drawBridge and context
    const drawBridge = new Kekule.Render.ThreeRendererBridge();
    const context = drawBridge.createContext(
      this.structViewer.current,
      800,
      400
    );

    // create painter and draw
    const painter = new Kekule.Render.ChemObjPainter3D(mole, drawBridge);
    const configObj = Kekule.Render.Render3DConfigs.getInstance();
    const options = Kekule.Render.RenderOptionUtils.convertConfigsToPlainHash(
      configObj
    );

Where initialized:

this.structViewer = React.createRef();

Traceback:

index-478e4689.js:40 TypeError: Cannot read properties of undefined (reading 'WebGLRenderer')
    at C0.createContext (index-478e4689.js:63476:181438)
    at KekuleStructureViewer.painterDraw (index-478e4689.js:63495:3377)
    at KekuleStructureViewer.draw (index-478e4689.js:63495:2080)
    at KekuleStructureViewer.componentDidUpdate (index-478e4689.js:63495:4574)
    at lk (index-478e4689.js:40:34394)
    at jk (index-478e4689.js:40:34070)
    at ik (index-478e4689.js:40:33576)
    at Xk (index-478e4689.js:40:44194)
    at Qk (index-478e4689.js:40:43502)
    at Hk (index-478e4689.js:40:38614)
    at J0 (index-478e4689.js:25:1727)
    at MessagePort.T0 (index-478e4689.js:25:2139)
partridgejiang commented 1 year ago

Hi @JackDra, have you import three.js in your project? Without it, the ThreeRendererBridge will fail to create the context. Perhaps the following code will do you some help:

import * as THREE from 'three';
import { Kekule } from 'kekule';
Kekule.externalResourceManager.register('three.js', THREE);
JackDra commented 1 year ago

Hi @JackDra, have you import three.js in your project? Without it, the ThreeRendererBridge will fail to create the context. Perhaps the following code will do you some help:

import * as THREE from 'three';
import { Kekule } from 'kekule';
Kekule.externalResourceManager.register('three.js', THREE);

That did the trick.

I think there was an older version that was doing some kind of hack with:

// This is the trick for using Kekule 3D renderer
// THREE is defined as a component in Window object by kekule
window["THREE"] = THREE;

But replacing it with the register method worked. Thanks!