Open arpitdalal opened 11 months ago
Thanks for sharing this issue. However, could you please share a repository with a minimal reproducing example so that I can easily investigate?
@ValentinH Thanks for looking into this
Here's minimal reproducing example, clone it, run cp .env.example .env
, run npm run setup
and then npm run dev
to run the dev server. Everything will run with flying colors. You can go to localhost:3000
to see the app running locally, you can log in with kody/kodylovesyou
(username/password) and then go to localhost:3000/settings/profile/photo
, then click Change
button to change the image and select any image then you'll see the Cropper
component to crop the picture that you've selected, you can click the save
button and it'll actually crop the image and save it in the db. Functionally everything works!!
The only issue is when you build the app. Run npm run build
to build the app > run npm start
to start in prod mode and then you'll see the error on your console, this is what I get:
(node:52258) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
SyntaxError: Cannot use import statement outside a module
/mre-react-easy-crop/node_modules/react-easy-crop/index.module.js:1
import { __assign, __extends } from 'tslib';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at internalCompileFunction (node:internal/vm:73:18)
at wrapSafe (node:internal/modules/cjs/loader:1178:20)
at Module._compile (node:internal/modules/cjs/loader:1220:27)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
at Module.load (node:internal/modules/cjs/loader:1119:32)
at Function.Module._load (node:internal/modules/cjs/loader:960:12)
at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:169:29)
at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
I believe it has to do with the module.js
extension maybe š¤·āāļø
Also, in the editor if you go to /app/routes/settings+/profile.photo.tsx
file, you'll see the TS error that I mentioned in the issue:
JSX element type 'Cropper' does not have any construct or call signatures.ts(2604)
temp fix with patch-package:
diff --git a/node_modules/react-easy-crop/index.module.js b/node_modules/react-easy-crop/index.module.js
index 11cf90c..f50b7dd 100644
--- a/node_modules/react-easy-crop/index.module.js
+++ b/node_modules/react-easy-crop/index.module.js
@@ -1,7 +1,30 @@
-import { __assign, __extends } from 'tslib';
import React from 'react';
import normalizeWheel from 'normalize-wheel';
+function extendStatics(d, b) {
+ extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+ return extendStatics(d, b);
+};
+
+function __extends(d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+}
+
+function __assign () {
+ __assign = Object.assign || function __assign(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+ }
+ return t;
+ }
+ return __assign.apply(this, arguments);
+}
+
/**
* Compute the dimension of the crop area based on media size,
* aspect ratio and optionally rotation
diff --git a/node_modules/react-easy-crop/package.json b/node_modules/react-easy-crop/package.json
index c807ad1..059d843 100644
--- a/node_modules/react-easy-crop/package.json
+++ b/node_modules/react-easy-crop/package.json
@@ -1,6 +1,7 @@
{
"name": "react-easy-crop",
"version": "5.0.2",
+ "type": "module",
"description": "A React component to crop images/videos with easy interactions",
"homepage": "https://ValentinH.github.io/react-easy-crop/",
"keywords": [
Essentially what is changes is that I added type: module
to the package.json and then removed the import from tslib in index.module.js
and declared the relevant functions in the file itself. This fix works for me and my use case, I HAVEN'T tested every function and every way you can use react-easy-crop
, so test this solution for your use case
Thanks for sharing this. I'm sorry I haven't found the time to look into this so far. To be honest, these kinds of issues are pretty complex to deal with as a lib maintainer because there are so many frameworks that behave differently in the way they consume packages. I might fix it for your use case and break it for others...
It's not just my use case, it doesn't work with Remix at all, here's a minimal application of remix and react-easy-crop: https://stackblitz.com/edit/remix-run-remix-mryppq?file=app%2Froutes%2F_index.tsx
Thanks for submitting this minimal reproduction.
I had a look and so far I don't know what should I change to have this working on Remix š
This could be solved by providing an ESM build.
This is already the case.
Ah, I looked at the wrong dist file.
You have a misconfiguration in the package.json. Please consider fixing this small bug that makes the library hard to use with some frameworks.
Please have a look at the lint error/warnings for the library here https://publint.dev/react-easy-crop@5.0.6 and here https://arethetypeswrong.github.io/?p=react-easy-crop%405.0.6
./index.module.js is written in ESM, but is interpreted as CJS. Consider using the .mjs extension, e.g. ./index.module.mjs ([More info](https://publint.dev/rules.html#file_invalid_format)) The types is not exported. Consider adding pkg.exports["."].import.types to be compatible with TypeScript's "moduleResolution": "bundler" compiler option. Note that you cannot use "./index.d.ts" because it has a mismatching format. Instead, you can duplicate the file and use the .mts extension, e.g. pkg.exports["."].import.types: "./index.d.mts" ([More info](https://publint.dev/rules.html#types_not_exported))
[Resolution failed](https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/NoResolution.md) Import failed to resolve to type declarations or JavaScript files.
For anyone using Remix V2 with Vite you can fix this bug by adding the ssr.noExternal option in the vite.config.js (https://remix.run/docs/en/main/future/vite#esm--cjs):
import { vitePlugin as remix } from "@remix-run/dev";
import { installGlobals } from "@remix-run/node";
import { defineConfig } from "vite";
import path from "path"
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
installGlobals();
export default defineConfig({
ssr: {
noExternal: ['react-easy-crop', 'tslib']
},
plugins: [
remix(),
],
resolve: {
alias: {
"~": path.resolve(__dirname, "./app")
}
}
});
And when importing Cropper like this import Cropper from 'react-easy-crop' gives this error when using it
JSX element type 'Cropper' does not have any construct or call signatures.ts(2604)
This is fixed with the PR #523
Thank you @lww for digging into the root cause and proposing the solution ā¤ļø
That's great news! I like fixing bugs without wanting to š¤£
Oh sorry, I didn't communicate clearly. The part of this issue is fixed. The one that would give an error in the code editor is fixed, but not the terminal error when starting the app in prod mode.
@lww's suggestion is correct here, .mjs
extension should be used instead of .js
Alright I'll try this then
Could you please try 5.0.7--canary.2940c18.0
and let me know if it solves your issues? (I'm not really confident that it does)
Just tried it, didn't fix the issue. This is the console error:
SyntaxError: Named export '__assign' not found. The requested module 'tslib' 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 'tslib';
const { __assign, __extends } = pkg;
file:///Users/arpit.dalal/personal/xman/node_modules/react-easy-crop/index.module.mjs:1
import { __assign, __extends } from 'tslib';
^^^^^^^^
SyntaxError: Named export '__assign' not found. The requested module 'tslib' 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 'tslib';
const { __assign, __extends } = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:132:21)
at ModuleJob.run (node:internal/modules/esm/module_job:214:5)
at ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at getBuild (file:///Users/arpit.dalal/personal/xman/server/index.ts:204:4)
at file:///Users/arpit.dalal/personal/xman/server/index.ts:218:34
I tried the suggested solution in the error message by importing tslib
as import tslib from "tslib"
and import * as tslib from "tslib"
but none of these worked. I got TypeError: tslib.__extends is not a function
with these both alternatives.
Thanks for working on this @ValentinH. I am not too well versed in building a package for both CJS and ESM, so I am unfortunately out of ideas. Luckily, @lww's workaround of adding tslib
and react-easy-crop
to the ssr.noExternal
option in the vite.config.js
works fine.
based on the docs https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseCJS.md the import should be
"import": {
"types": "./index.d.mts",
"default": "./index.mjs"
},
notice the missing m in index.d.mts
I'm actually wondering if we should just get rid of tslib. I don't even recall why it was added in the first place and it's something I haven't seen used elsewhere.
based on the docs https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseCJS.md the import should be
"import": { "types": "./index.d.mts", "default": "./index.mjs" },
notice the missing m in index.d.mts
I tried that but it requires more changes to the index.m.ts file and the files it imports. However, I couldn't find how to do it with bili
, the tool we use to build the lib and that is not maintained anymore.
We need to revamp the build pipeline from scratch to have something we can control. However, the fact that the Cropper component imports some non- js files (css) makes it more tricky. Last but not least, this is the most boring and painful to get right topic.
Actually, this works
"exports": {
".": {
"import": {
"types": "./index.module.d.mts", <-- "index.module.d.mts" instead of "index.d.ts"
"default": "./index.module.mjs"
},
"require": {
"types": "./index.d.ts",
"default": "./index.js"
}
},
"./react-easy-crop.css": {
"import": "./react-easy-crop.css",
"require": "./react-easy-crop.css"
}
}
The index.module.d.mts
is already being generated in the canary version
So, I believe it's just changing the file name for "imports.types" instead of generating a new file. I am not sure if and how that can be configured in bili
I tried that but https://arethetypeswrong.github.io/?p=react-easy-crop%405.0.7--canary.527.82deecf.0 is even worse.
Can you try react-easy-crop@5.0.7--canary.527.82deecf.0 please?
Surprisingly, that worked. I don't see index.d.mts
in the build output on npm though. I am not sure how that works.
I think it should be index.module.d.mts
since that exists in the build output on npm.
I'm too tired š
Please try react-easy-crop@5.0.7--canary.527.1aad632.0
even if we still have the same result on https://arethetypeswrong.github.io/?p=react-easy-crop%405.0.7--canary.527.1aad632.0:
It think it expects ./Cropper
to be something like ./Cropper.d.mts
nvm, sorry, I tried the canary 5.0.7--canary.527.82deecf.0
with ssr.noExternal
in the vite config. Without ssr.noExternal
in the vite config, it fails on start.
Failing with react-easy-crop@5.0.7--canary.527.1aad632.0
too š
Sorry dude, I know it's a hard problem. Thanks for trying to figure this out, I don't have anything else to suggest here.
I'll try to move the build pipeline to plain Rollup when I get some motivation. š¤
Running into the same issue. Is there anything we can help with to solve it?
I'm stuck on this topic. Ideally, someone with good knowledge around bundling would jump in to fix this š
I'm getting this in Remix as well.
Edit: This fixed for me: https://github.com/ValentinH/react-easy-crop/issues/490#issuecomment-2034722747
Same for me while using AstroJs and react
Describe the bug I'm getting
Cannot use import statement outside a module
when building it for prod, dev just works fine. I'vetype: module
in my package.json and here's my tsconfigAnd when importing
Cropper
like thisimport Cropper from 'react-easy-crop'
gives this error when using itThis project did build successfully before with these exact configs but after adding
react-easy-crop
, it doesn'tFull error:
Expected behavior It should build successfully with these configs and shouldn't throw an error when using the
Cropper
component