svgdotjs / svgdom

Straightforward DOM implementation to make SVG.js run headless on Node.js
MIT License
269 stars 53 forks source link

Compatibility issue when using SVG DOM 0.1.19 in CommonJS projects. #117

Closed banujan6 closed 9 months ago

banujan6 commented 9 months ago

I have been using svgdom: 0.1.14 in my typescript project which eventually gets compiled to CommonJS. After updating svgdom to 0.1.19, I lost the support to CommonJS and it throws the following error after a successful build.

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/banujan/Projects/external-diagram-import/node_modules/svgdom/main-module.js from /dist/services/svg/abstract-svg.svc.js not supported.
Instead change the require of main-module.js in /dist/services/svg/abstract-svg.svc.js to a dynamic import() which is available in all CommonJS modules.

NOTE: Due to some reasons I can't switch to ESM. Also since I have used svgdom in export abstract class as a type reference, I cannot even use dynamic import().

Then noticed that the package.json has been set to export esm version for both the export and require even tho cjs is available in dist/ directory.

"exports": {
    "import": "./main-module.js",
    "require": "./main-module.js"
 }

I could solve the issue by updating the package.json as follows,

"exports": {
    "import": "./main-module.js",
    "require": "./dist/main-require.cjs"
}

Is there any special reason to serve esm for both require and import? It would be great if we get both support.

Fuzzyma commented 9 months ago

That the cjs version is still available in dist is a mistake and it is an outdated version. The move to esm was done to reduce the burden of maintenance of this package.

If you need types of a dynamically imported module, you can use this syntax:

type MyType = import('svgdom').Node

Also consider using bun which can reolve esm and cjs imports without using any async import(). In that case you dont even need to transpile the file

banujan6 commented 9 months ago

I tried async load too

const { createSVGWindow } = await import( 'svgdom' );

global.window = createSVGWindow();
global.document = global.window.document;

registerWindow(window, document);

It generated the following code:

const { createSVGWindow } = yield Promise.resolve().then(() => __importStar(require('svgdom'))); // line 51
global.window = createSVGWindow();
global.document = global.window.document;
(0, svg_js_1.registerWindow)(window, document);

Still, this error occurs when loading the module.

Error [ERR_REQUIRE_ESM]: require() of ES Module /node_modules/svgdom/main-module.js from /dist/services/svg-split.svc.js not supported. Instead change the require of main-module.js in /dist/services/svg-split.svc.js to a dynamic import() which is available in all CommonJS modules. at /dist/services/svg-split.svc.js:51:89 { code: 'ERR_REQUIRE_ESM' }

Fuzzyma commented 9 months ago

So it converts the import to a require call? try to ts-ignore that line

banujan6 commented 9 months ago

Well, I fixed it. Since it is a back-end service, There is no point of building it. I could directly run it with ts-node instead of building. Thank you for your support.

Fuzzyma commented 9 months ago

that works! If you use ts-node anyway, you might wanna try tsx or bun as alternatives