plotly / react-cytoscapejs

React component for Cytoscape.js network visualisations
MIT License
470 stars 69 forks source link

Next.js uses cjs module loader resulting in SyntaxError: Cannot use import statement outside a module #107

Closed JJ-udith closed 1 year ago

JJ-udith commented 1 year ago

Operating System: Platform: darwin Arch: x64 Version: Darwin Kernel Version 20.6.0: Mon Aug 29 04:31:06 PDT 2022; root:xnu-7195.141.39~2/RELEASE_X86_64 Binaries: Node: 16.18.0 npm: 8.19.2 Yarn: 1.22.17 pnpm: N/A Relevant packages: next: 12.3.1 eslint-config-next: 12.3.1 react: 18.2.0 react-dom: 18.2.0

Hello!

I tried to import CytoscapeComponent from "react-cytoscapejs" and get the follwoing error:

SyntaxError: Cannot use import statement outside a module pointing to Object.react-cytoscapejs.

If i manually add "type": "module" in the package.json of node_module react-cytoscapejs the error is gone. Now my problem is, that it works locally but deployment (vercel) leads to the same error.

I may have discovered a similar error here with an answer from nextjs.

If i missed something here, please let me know if i can fix it somehow. Thank you and best regards

Graph.js:

import React, { useContext, useEffect, useState } from "react";
import CytoscapeComponent from "react-cytoscapejs";
import { DataContext } from "../../pages";
import cytoscape from "cytoscape";
import dagre from "cytoscape-dagre";

cytoscape.use(dagre);

const Graph = ({ elements }) => {
  const style = [
    {
      selector: "node",
      css: {
        content: "data(name)",
        "text-valign": "center",
        "text-halign": "center",
        shape: "data(shape)",
        "border-color": "data(bordercolor)",
        "border-width": "3",
        padding: "20",
      },
    },
    {
      selector: ":parent",
      css: {
        "text-valign": "top",
        "text-halign": "center",
      },
    },
    {
      selector: "edge",
      css: {
        content: "data(name)",
        "text-margin-y": -17,
        "curve-style": "bezier",
        "target-arrow-shape": "triangle",
        "line-color": "data(color)",
      },
    },
  ];

  const layout = { name: "dagre" };

  return (
    <div>
      <CytoscapeComponent
        elements={elements}
        stylesheet={style}
        style={{ width: "600px", height: "600px" }}
        layout={layout}
      />
    </div>
  );
};

export default Graph;

Error:


/vercel/path0/node_modules/react-cytoscapejs/dist/react-cytoscape.modern.js:1
--
17:44:27.321 | import e from"react";import t from"prop-types";import n from"cytoscape";const{string:o,array:l,object:s,number:a,bool:i,oneOfType:r,any:c,func:u}=t,d={id:o,className:o,style:r([o,s]),elements:r([l,c]),stylesheet:r([l,c]),layout:r([s,c]),pan:r([s,c]),zoom:a,panningEnabled:i,userPanningEnabled:i,minZoom:a,maxZoom:a,zoomingEnabled:i,userZoomingEnabled:i,boxSelectionEnabled:i,autoungrabify:i,autolock:i,autounselectify:i,get:u,toJson:u,diff:u,forEach:u,cy:u,headless:i,styleEnabled:i,hideEdgesOnViewport:i,textureOnViewport:i,motionBlur:i,motionBlurOpacity:a,wheelSensitivity:a,pixelRatio:r([o,s])},p=(e,t)=>{if(((e,t)=>null==e\|\|null==t)(e,t)&&(null!=e\|\|null!=t))return!0;if(e===t)return!1;if("object"!=typeof e\|\|"object"!=typeof t)return e!==t;const n=Object.keys(e),o=Object.keys(t),l=n=>e[n]!==t[n];return n.length!==o.length\|\|!(!n.some(l)&&!o.some(l))},m=(e,t)=>null!=e?e[t]:null,y={diff:p,get:m,toJson:e=>e,forEach:(e,t)=>e.forEach(t),elements:[{data:{id:"a",label:"Example node A"}},{data:{id:"b",label:"Example node B"}},{data:{id:"e",source:"a",target:"b"}}],stylesheet:[{selector:"node",style:{label:"data(label)"}}],zoom:1,pan:{x:0,y:0}},h=(e,t,n,o)=>n(m(e,o),m(t,o)),b=(e,t,n,o,l,s,a)=>{e.batch(()=>{(o===p\|\|h(t,n,o,"elements"))&&x(e,m(t,"elements"),m(n,"elements"),l,s,a,o),h(t,n,o,"stylesheet")&&E(e,m(t,"stylesheet"),m(n,"stylesheet"),l),["zoom","minZoom","maxZoom","zoomingEnabled","userZoomingEnabled","pan","panningEnabled","userPanningEnabled","boxSelectionEnabled","autoungrabify","autolock","autounselectify"].forEach(s=>{h(t,n,o,s)&&f(e,s,m(t,s),m(n,s),l)})}),h(t,n,o,"layout")&&g(e,m(t,"layout"),m(n,"layout"),l)},f=(e,t,n,o,l)=>{e[t](l(o))},g=(e,t,n,o)=>{const l=o(n);null!=l&&e.layout(l).run()},E=(e,t,n,o)=>{const l=e.style();null!=l&&l.fromJson(o(n)).update()},x=(e,t,n,o,l,s,a)=>{const i=[],r=e.collection(),c=[],u={},d={},p=e=>l(l(e,"data"),"id");s(n,e=>{const t=p(e);d[t]=e}),null!=t&&s(t,t=>{const n=p(t);u[n]=t,(e=>null!=d[e])(n)\|\|r.merge(e.getElementById(n))}),s(n,e=>{const t=p(e),n=(e=>u[e])(t);(e=>null!=u[e])(t)?c.push({ele1:n,ele2:e}):i.push(o(e))}),r.length>0&&e.remove(r),i.length>0&&e.add(i),c.forEach(({ele1:t,ele2:n})=>O(e,t,n,o,l,a))},O=(e,t,n,o,l,s)=>{const a=l(l(n,"data"),"id"),i=e.getElementById(a),r={};["data","position","selected","selectable","locked","grabbable","classes"].forEach(e=>{const a=l(n,e);s(a,l(t,e))&&(r[e]=o(a))});const c=l(n,"scratch");s(c,l(t,"scratch"))&&i.scratch(o(c)),Object.keys(r).length>0&&i.json(r)};class w extends e.Component{static get propTypes(){return d}static get defaultProps(){return y}static normalizeElements(e){if(null!=e.length)return e;{let{nodes:t,edges:n}=e;return null==t&&(t=[]),null==n&&(n=[]),t.concat(n)}}constructor(t){super(t),this.displayName="CytoscapeComponent",this.containerRef=e.createRef()}componentDidMount(){const e=this.containerRef.current,{global:t,headless:o,styleEnabled:l,hideEdgesOnViewport:s,textureOnViewport:a,motionBlur:i,motionBlurOpacity:r,wheelSensitivity:c,pixelRatio:u}=this.props,d=this._cy=new n({container:e,headless:o,styleEnabled:l,hideEdgesOnViewport:s,textureOnViewport:a,motionBlur:i,motionBlurOpacity:r,wheelSensitivity:c,pixelRatio:u});t&&(window[t]=d),this.updateCytoscape(null,this.props)}updateCytoscape(e,t){const n=this._cy,{diff:o,toJson:l,get:s,forEach:a}=t;b(n,e,t,o,l,s,a),null!=t.cy&&t.cy(n)}componentDidUpdate(e){this.updateCytoscape(e,this.props)}componentWillUnmount(){this._cy.destroy()}render(){const{id:t,className:n,style:o}=this.props;return e.createElement("div",{ref:this.containerRef,id:t,className:n,style:o})}}export{w as default};
17:44:27.321 | ^^^^^^
17:44:27.321 |  
17:44:27.321 | SyntaxError: Cannot use import statement outside a module
17:44:27.321 | at Object.compileFunction (node:vm:352:18)
17:44:27.322 | at wrapSafe (node:internal/modules/cjs/loader:1033:15)
17:44:27.322 | at Module._compile (node:internal/modules/cjs/loader:1069:27)
17:44:27.322 | at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
17:44:27.322 | at Module.load (node:internal/modules/cjs/loader:981:32)
17:44:27.322 | at Function.Module._load (node:internal/modules/cjs/loader:822:12)
17:44:27.322 | at Module.require (node:internal/modules/cjs/loader:1005:19)
17:44:27.323 | at require (node:internal/modules/cjs/helpers:102:18)
17:44:27.323 | at Object.49 (/vercel/path0/.next/server/pages/index.js:207:52)
17:44:27.323 | at __webpack_require__ (/vercel/path0/.next/server/webpack-runtime.js:25:42)
JJ-udith commented 1 year ago

Fixed by adding 'next-transpile-modules' package to the project and in next.config.js:

/** @type {import('next').NextConfig} */
const withTM = require('next-transpile-modules')(['react-cytoscapejs']);

const nextConfig = {
  reactStrictMode: true,
}

module.exports = withTM(nextConfig)
colodenn commented 1 year ago

All features of next-transpile-modules are now natively built-in Next.js 13.1. No need to install next-transpile-modules anymore.

Adding transpilePackages: ["react-cytoscapejs"] to next.config.js fixed the issue for me.

const config = {
  reactStrictMode: true,
  transpilePackages: ["react-cytoscapejs"],
};

https://nextjs.org/blog/next-13-1#built-in-module-transpilation-stable