CarlosNZ / json-edit-react

React component for editing/viewing JSON/object data
https://carlosnz.github.io/json-edit-react/
MIT License
173 stars 17 forks source link

adding default exported package as cjs breaks esm usage #128

Open roger-tbg opened 2 weeks ago

roger-tbg commented 2 weeks ago

Describe the bug import { JsonEditor, LinkCustomNodeDefinition } from "json-edit-react"; ^^^^^^^^^^ SyntaxError: Named export 'JsonEditor' not found. The requested module 'json-edit-react' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:

import pkg from 'json-edit-react'; const { JsonEditor, LinkCustomNodeDefinition } = pkg;

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Online demo Please try and reproduce problem using a fork of this sandbox, and post the link here. If you can't reproduce the problem there, it's likely to be due to something outside of the component itself.

loichu commented 1 week ago

Hi ! I have the same problem...

Here's how I fixed it: In the module's package.json (located in node_modules/json-edit-react/package.json), I added type: "module":

{
  "name": "json-edit-react",
  "version": "1.17.1",
  "description": "React component for editing or viewing JSON/object data",
  "main": "build/index.cjs.js",
  "module": "build/index.esm.js",
  "type": "module",
  ....
}

But then I still had to import it this way:

import * as JsonEditorPkg from 'json-edit-react'

And as my app is SSR, I had to wrap it with Suspense because the module is accessing document which is obviously not available on the server.

In the end this is how I call the editor in my page:

<Suspense fallback={<Progress size='xs' isIndeterminate />}>
  <JsonEditorPkg.JsonEditor
    data={jsonData}
  />
</Suspense>

It's a bit of workaround and monkey patch but it works for me. As I will always need to make that change in the package.json, I might switch to an alternative library or just get rid of this feature in my app. It's too bad because beside of that the library looks really good, thanks to the author !

CarlosNZ commented 1 week ago

Thanks for the info. I'll have a play around with it and try and update to something that works easier.

I didn't realise how much of a headache it is to configure it so it works seamlessly with every type of environment. If anyone has any expertise in this area, I'd very much appreciate the assistance :)

Just out of interest @loichu and @roger-tbg -- would you mind trying it with version 1.16.0 ? That's the last version before I started poking round with the package.json, so would be interested to see if that makes a difference for your environments.

loichu commented 1 week ago

Hi @CarlosNZ !

I just tried with 1.16.0 and funny thing: I had to remove type: "module" from node_modules/json-edit-react/package.json to build...

I had this error:

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/my-app/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

Maybe my setup is a little bit weird I don't know but it handles most libraries...

My setup is Refine with Remix and I use the default dev server, bundler etc... But while trying to reproduce my setup for testing I noticed that I made a little change:

Default setup

npm create refine-app@latest -- --example with-remix-headless my-refine-remix-app

It didn't compile with one lib that I really need but I tried just with json-edit-react, I got other errors

Add a bit of code to bundle the lib

app/root.tsx

// All imports

import { JsonEditor } from "json-edit-react"

// Code...

return (
    // html...
   <body>
        <JsonEditor
          data={{hello: "world"}}
        />
   </body>
)

json-edit-react

In 1.17.1

Error: Cannot find module '/my-refine-remix-app/node_modules/json-edit-react/dist/index.cjs.js'

image

Here I think that if the file was existing like written in the package.json, it could work

In 1.16.0

Error [ERR_REQUIRE_ESM]: require() of ES Module /my-refine-remix-app/node_modules/json-edit-react/build/index.cjs.js from /my-refine-remix-app/build/index.js not supported.
index.cjs.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead either rename index.cjs.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /my-refine-remix-app/node_modules/json-edit-react/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

    at Object.<anonymous> (/my-refine-remix-app/build/index.js:144:30)
    at async run (/my-refine-remix-app/node_modules/@remix-run/serve/dist/cli.js:112:15)

Reproduce error mentioned by the issue

Node: v20.8.1 json-edit-react: 1.17.1

I changed this is the config (it makes the one lib I really need working):

import { JsonEditor } from "json-edit-react";
         ^^^^^^^^^^
SyntaxError: Named export 'JsonEditor' not found. The requested module 'json-edit-react' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'json-edit-react';
const { JsonEditor } = pkg;

Fix the build error (quickly)

Change import statement and component call app/root.tsx

// All imports

import * as  JsonEditorPkg from "json-edit-react"

// Code...

return (
    // html...
   <body>
        <JsonEditorPkg.JsonEditor
          data={{hello: "world"}}
        />
   </body>
)
(node:1280997) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.

blablabla...

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:73:18)
    at wrapSafe (node:internal/modules/cjs/loader:1153:20)
    at Module._compile (node:internal/modules/cjs/loader:1205:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Function.Module._load (node:internal/modules/cjs/loader:938:12)
    at cjsLoader (node:internal/modules/esm/translators:284:17)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:234:7)
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at ModuleLoader.import (node:internal/modules/esm/loader:316:24)

Add "type": "module" in node_modules/json-edit-react/package.json

It builds !

I don't really know how all this works, I never maintained a lib it seems complicated to please all frameworks out there haha

Note on SSR

The problem is that document is referenced in the lib, I'm not totally sure but I think that with React there must be way around that... No other lib that I use made me use Suspense...