function-plot icon indicating copy to clipboard operation
function-plot copied to clipboard

Package does not compile due to potential mismatch of "require" and "import" syntax

Open mmartinezluis opened this issue 1 year ago • 13 comments

I'm using Nextjs V12. When trying to use the function-plot library via import statement, the library does not work. I get the below error:

isse_compiling

There seems to be an import mismatch between the d3-shape dependency and the chart.js dependency. I would appreciate help on solving this issue.

mmartinezluis avatar Feb 14 '24 00:02 mmartinezluis

Thanks for the report, which version of function-plot are you using?

mauriciopoppe avatar Feb 14 '24 02:02 mauriciopoppe

I'm using the latest version, 1.24.4

mmartinezluis avatar Feb 14 '24 03:02 mmartinezluis

I think it's happening because the dist files in dist/ emitted in v1.24.4 use CommonJS and the d3-* libraries use JS modules. So the flow is: JS Module (your app) -> CommonJS (function plot) -> JS Module (d3)

As a workaround try this import which uses a bundled version of function-plot which is the entire library in a single file:

import functionPlot from 'function-plot/dist/function-plot'

For the real solution the flow above needs to be JS Module (your app) -> JS Modlue (function plot) -> JS Module (d3). I switched to use JS modules in the master branch so you should be able to do import functionPlot from 'function-plot' in a future release.

mauriciopoppe avatar Feb 14 '24 03:02 mauriciopoppe

Thank you for the response. I tried the work around, but it does not work: error on importing library

error on importing library terminal

It seems that this is a breaking change.

mmartinezluis avatar Feb 14 '24 04:02 mmartinezluis

Since the documentaiton for Function-plot is solely written using JS Module syntax (and hence the users of Function-plot are more likely using ESM imports), I think that a new release for this seemingly breaking change should not be that difficult, given that you already updated the master branch for chart.js. I'll be looking forward to the release/fix. Thank you.

mmartinezluis avatar Feb 14 '24 04:02 mmartinezluis

I tried the following in a hello world parcel app and it did work:

import functionPlot from 'function-plot/dist/function-plot'

functionPlot({
  target: '#playground',
  data: [{ fn: 'x^2', graphType: 'polyline' }]
})

I suspect this might be a problem between the integration of the NextJS bundler and this library.


There's a dev build not ready for production usage that already uses JS modules, could you please try with this module? npm install [email protected]

mauriciopoppe avatar Feb 14 '24 04:02 mauriciopoppe

Related issue in a NextJS app https://github.com/mauriciopoppe/function-plot/issues/217 that I think was never solved.

mauriciopoppe avatar Feb 14 '24 04:02 mauriciopoppe

I've reproduced this issue with the following steps:

  • Follow this guide https://vercel.com/guides/create-hello-world-react-app-nextjs to create a hello world app
  • Install function-plot v1.24.4
  • Case 1: with the following setup I see the following error
import functionPlot from "function-plot";
⨯ ./node_modules/function-plot/dist/chart.js:7:19
Module not found: ESM packages (d3-shape) need to be imported. Use 'import' to reference the package instead. https://nextjs.org/docs/messages/import-esm-externals

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./node_modules/function-plot/dist/index.js
./src/app/page.js
  • Case 2: if src/app/page.js look like this:
import functionPlot from "function-plot/dist/function-plot";
⨯ node_modules/function-plot/dist/function-plot.js (1:205) @ self
 ⨯ ReferenceError: self is not defined
    at eval (webpack-internal:///(rsc)/./node_modules/function-plot/dist/function-plot.js:4:3)
    at (rsc)/./node_modules/function-plot/dist/function-plot.js (/private/var/folders/c1/clfklx952gg7v4tjck2t8j640000gn/T/tmp.TNCiGCJfdr/hello-world/.next/server/vendor-chunks/function-plot.js:20:1)
    at __webpack_require__ (/private/var/folders/c1/clfklx952gg7v4tjck2t8j640000gn/T/tmp.TNCiGCJfdr/hello-world/.next/server/webpack-runtime.js:33:42)
    at eval (webpack-internal:///(rsc)/./src/app/page.js:9:90)
    at (rsc)/./src/app/page.js (/private/var/folders/c1/clfklx952gg7v4tjck2t8j640000gn/T/tmp.TNCiGCJfdr/hello-world/.next/server/app/page.js:194:1)
    at Function.__webpack_require__ (/private/var/folders/c1/clfklx952gg7v4tjck2t8j640000gn/T/tmp.TNCiGCJfdr/hello-world/.next/server/webpack-runtime.js:33:42)
    at runNextTicks (node:internal/process/task_queues:60:5)
    at listOnTimeout (node:internal/timers:540:9)
    at process.processTimers (node:internal/timers:514:7)

mauriciopoppe avatar Feb 14 '24 04:02 mauriciopoppe

With dev build version 1.25.0, the package loads:

loads

However, a new error shows on the application page: default key not last one

The fix for the above error seems to be moving the "default" key from "exports" to the last place, as shown below:

move default key

mmartinezluis avatar Feb 14 '24 05:02 mmartinezluis

Thanks for the investigation, yes I saw a similar answer online, in addition I had to make a few changes to the dependencies included.

Anyways, first install the latest alpha version (not production ready yet) npm install [email protected].

The toy app I have looks like this:

"use client";

import React, { useRef, useEffect } from "react";
import functionPlot from "function-plot";
import styles from "./page.module.css";

export const FunctionPlot = React.memo(
  ({ options }) => {
    const rootEl = useRef(null);
    useEffect(() => {
      try {
        functionPlot(Object.assign({}, options, { target: rootEl.current }));
      } catch (e) {}
    });
    return <div ref={rootEl} />;
  },
  () => false,
);

export default function Home() {
  const options = {
    data: [{ fn: "x^2", graphType: "polyline" }],
  };
  return (
    <main className={styles.main}>
      <FunctionPlot options={options} />
    </main>
  );
}

mauriciopoppe avatar Feb 14 '24 05:02 mauriciopoppe

Hi @mauriciopoppe ,

Thank you for the code. I just tested the code, and it shows an error:

import error

The error comes at the "import" line:

import functionPlot from 'function-plot';

mmartinezluis avatar Feb 18 '24 03:02 mmartinezluis

it has been a month and will there any update for this in near future?

SnowyField1906 avatar Mar 18 '24 03:03 SnowyField1906

I tried the changes in https://github.com/mauriciopoppe/function-plot/issues/278#issuecomment-1943097069 and they work for me, here's my setup:

cd $(mktemp -d)
npx create-next-app@latest
cd my-app
npm install [email protected]
cat <<EOF > src/app/page.js
"use client";

import React, { useRef, useEffect } from "react";
import functionPlot from "function-plot";
import styles from "./page.module.css";

export const FunctionPlot = React.memo(
  ({ options }) => {
    const rootEl = useRef(null);
    useEffect(() => {
      try {
        functionPlot(Object.assign({}, options, { target: rootEl.current }));
      } catch (e) {}
    });
    return <div ref={rootEl} />;
  },
  () => false,
);

export default function Home() {
  const options = {
    data: [{ fn: "x^2", graphType: "polyline" }],
  };
  return (
    <main className={styles.main}>
      <FunctionPlot options={options} />
    </main>
  );
}
EOF
npm run dev

When I open the dev webpage I see no errors image

mauriciopoppe avatar Mar 20 '24 03:03 mauriciopoppe