Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

module import/export issue #2265

Closed
paddotk opened this issue Nov 3, 2021 · 59 comments · Fixed by #2281
Closed

module import/export issue #2265

paddotk opened this issue Nov 3, 2021 · 59 comments · Fixed by #2281
Labels

Comments

@paddotk
Copy link

paddotk commented Nov 3, 2021

Marked version:
4.0.0

Describe the bug
I updated marked in our project from ^3.0.2 to 4.0.0 (before it worked fine), and after the update I get an error marked__WEBPACK_IMPORTED_MODULE_5___default(...) is not a function when using it. It seems that the module is no longer exported properly,
I tried to change the import import { marked } from 'marked' as well as using marked.parse() as shown in the readme, but that doesn't seem to help.

To Reproduce
Steps to reproduce the behavior:
Use a webpack/npm project, import by means of import marked from 'marked'. Use the marked() function.

@UziTech
Copy link
Member

UziTech commented Nov 3, 2021

It looks like somewhere in your code you are trying to import the default export like import marked from 'marked'.

Make sure you replace all occurrences with import { marked } from 'marked'

@AlanMorel
Copy link

I'm using TypeScript and can also confirm that I am also experiencing the same issue on 4.0.0. I am importing it using import { marked } from "marked"; but getting 'marked' can only be imported using 'import marked = require("marked")' or a default import.. It is possible that I just need to wait until @types/marked is bumped up a major version though.

@paddotk
Copy link
Author

paddotk commented Nov 4, 2021

@UziTech I tried that but didn't work...
@AlanMorel From the error it looks like a Webpack issue. It also shows in my unit tests which are .js files.

@AlanMorel
Copy link

It seems unlikely to be a webpack-specific issue because the project I'm using Marked on is not using webpack at all.

@maurelio1234
Copy link

It is possible that I just need to wait until @types/marked is bumped up a major version though.

I have the same problem and @types/marked is still in 3.X

@UziTech
Copy link
Member

UziTech commented Nov 4, 2021

@types/marked v4 should be released soon

@AlanMorel
Copy link

Great, I believe that update to @types/marked will resolve my issue, so I will wait for that, thanks!

Side question though: any reason marked itself is not providing the typings for the library? It would both eliminate needing a separate @types/marked dependency while also ensuring that you can bump both the library and typings at the same time. Not a huge deal though, just curious.

@rtjtc
Copy link

rtjtc commented Nov 4, 2021

Also waiting for @types/marked ... Do you guys have a workaround or maybe I should go back to previous stable version?

@AlanMorel
Copy link

Pretty sure your only options are wait for the updated types (which should be coming soon) or use a previous version.

@paddotk
Copy link
Author

paddotk commented Nov 5, 2021

Ok, thanks. If it is the typings that cause the issue though, is there any way to omit the blocking error for now? Such as placing a // @ts-ignore comment somewhere?

@jfcere
Copy link

jfcere commented Nov 7, 2021

@paddotk If you are in a hurry you can always use gitpkg.now.sh and get an NPM package from the latest commit of UziTech's PR while waiting for it to be merged.

"@types/marked": "https://gitpkg.now.sh/UziTech/DefinitelyTyped/types/marked?415785793c958a98fa8902c482fe8be7959f86f6"

@AlanMorel
Copy link

The types have been merged and it's looking good on my end now

@boazy
Copy link

boazy commented Nov 9, 2021

It seems like v4.0.0 still doesn't work with Webpack. It looks like Webpack is trying to import lib/marked.cjs as an ES6 module. If I manually remove the "browser" settings in package.json or set it to be the same as "main", webpack works.
I guess this stems from the pre-ES6 module PR #1661, but I think it's safe to at least revert this PR for the short term until a better solution is available, if it causes webpack to not work at all...

@UziTech
Copy link
Member

UziTech commented Nov 9, 2021

looks like webpack suggests this fix.

@boazy if you want to test that out and create a PR for that we could get it merged in.

@scottbert
Copy link

I'm also having issues. I'm not using webpack, typescript, babel or anything, just using ESM module to run my code in Express.

v3 works correctly, if I upgrade to v4 and switch my import from import marked from 'marked'; to import { marked } from 'marked'; I get the following error trying to run it:

/<path>/app/shared/text/format.js:1
Error [ERR_REQUIRE_ESM]: require() of ES Module /<path>/node_modules/marked/lib/marked.esm.js not supported.
Instead change the require of marked.esm.js in null to a dynamic import() which is available in all CommonJS modules.

@rfgamaral
Copy link

I also have the same issue when using marked in CodeSandbox.

When using marked@4.0.0, and trying to import { marked } from 'marked (using the latest @types/marked@4.0.0), marked is undefined. For now I've resorted to using marked@3.0.8 with import marked from 'marked. But it would e nice to have this fixed.

@webstech
Copy link
Contributor

marked 4.0.1 has been released that may help with ESM instead of commonJS issues. The main entry in package.json now points to the commonJS code.

Real node ESM modules using babel will need to configure for it (unrelated to first comment).

@scottbert
Copy link

It seems to fix my issue, thanks!

@rfgamaral
Copy link

@webstech This still doesn't work for me:

const INITIAL_MARKED_OPTIONS = {
    gfm: false,
    headerIds: false,
}

// Reset Marked to the defaults and set custom options
marked.setOptions({
    ...marked.getDefaults(),
    ...INITIAL_MARKED_OPTIONS,
})

image

@webstech
Copy link
Contributor

@webstech This still doesn't work for me:

Did you restart the editor? The types change requires that for some setups (vscode/eslint in my case). Are you getting compile errors? Pasted your code into mine and there were no complaints. _marked.marked does not show up in a search. Do you know where this is coming from?

@rfgamaral
Copy link

@webstech

I was actually working on CodeSandbox. Tried a couple of times but couldn't get it working.

Here's a demo:

I tried to download the sandbox (File → Export to ZIP), and did the following:

  • npm install
  • npm run start

But I got this:

Failed to compile.

./src/Application.tsx
Attempted import error: 'marked' is not exported from 'marked'.
/home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/chokidar.js:17
throw new Error(
^

Error: No version of chokidar is available. Tried chokidar@2 and chokidar@3.
You could try to manually install any chokidar version.
chokidar@3: Error: Cannot find module 'chokidar'
Require stack:
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/chokidar.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/DirectoryWatcher.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/watcherManager.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/watchpack.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/webpack/lib/node/NodeWatchFileSystem.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/webpack/lib/node/NodeEnvironmentPlugin.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/webpack/lib/webpack.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/react-scripts/scripts/start.js
chokidar@2: Error: Cannot find module 'watchpack-chokidar2'
Require stack:
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/chokidar.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/DirectoryWatcher.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/watcherManager.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/watchpack.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/webpack/lib/node/NodeWatchFileSystem.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/webpack/lib/node/NodeEnvironmentPlugin.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/webpack/lib/webpack.js
- /home/Ricardo/Workspace/Playground/g0bw2/node_modules/react-scripts/scripts/start.js

    at Object.<anonymous> (/home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/chokidar.js:17:7)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:94:18)
    at Object.<anonymous> (/home/Ricardo/Workspace/Playground/g0bw2/node_modules/watchpack/lib/DirectoryWatcher.js:9:16)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)

Proceeded with npm install chokidar@3 and then npm run start again, and now I got just this:

Failed to compile.

./src/Application.tsx
Attempted import error: 'marked' is not exported from 'marked'.

The development server was launched, and a browser window opened with this:

image

image

@webstech
Copy link
Contributor

I was actually working on CodeSandbox. Tried a couple of times but couldn't get it working.

Sorry, I missed that. Tracked this down to a different change in package.json. This line:

"browser": "./lib/marked.cjs",

is causing the problem for react apps and possibly anyone using webpack. If it is removed or points to ./lib/marked.esm.js, your react app builds and runs (obviously I did not do this on CodeSandBox).

Found a possible solution .

  "browser": {
    "./lib/marked.cjs": "./lib/marked.cjs",
    "./lib/marked.esm.js": "./lib/marked.esm.js"
  },

Ran some tests (react and marked repo) with no problems.
@benmccann Do you have any thoughts on this?

I do not have a test case where the commonJS file would be used for the browser.

@webstech
Copy link
Contributor

Related to the previous solution link, there is a mention of using exports to resolve this. vscode says exports/browser is an unknown property and it does not appear to have any affect on webpack (invalid target mappings do not cause an error). Finished chasing this angle.

@NicolasCARPi
Copy link

For me #2276 broke marked. The ts compiler just couldn't find marked library anymore!! 4.0.0 is fine, but 4.0.1 doesn't work in my setup (typescript + webpack). I would be in favor of reverting that change or finding a fix that works for everyone.

@benmccann
Copy link
Contributor

I think the current setup is pretty confusing because the .cjs file isn't strictly CJS, but is UMD. I sent a PR to make that clearer without making any other changes: #2281

As far as the issues people are having here, it's really difficult to tell what's going wrong without more details. I'd encourage anyone who is having an issue to create and share a repository to reproduce the issue

It may be impossible to support all combinations of bundlers and CDNs since so many do weird things. I think the folks that are having trouble with Webpack are most likely using Webpack 4, which is somewhat broken in the way it does resolution. If you use Webpack 5, I expect it will work.

@NicolasCARPi
Copy link

@benmccann I tried your branch (by cloning it directly into the node_modules/marked dir). I still have an issue:

  • webpack: 5.64.0
    webpack-cli: 4.9.1

In the code (targetting the browser):

import { marked } from 'marked';

This gives the error: TS2307: Cannot find module 'marked' or its corresponding type declarations. (works fine with 4.0.0)

Trying import { marked } from 'marked/lib/marked.umd' gives: Module not found: Error: Package path ./lib/marked.umd is not exported from package /elabftw/node_modules/marked (see exports field in /elabftw/node_modules/marked/package.json), but in the editor there is no error with this import, only with the bundler.

I'm not that familiar with the export part of the package.json, but maybe it's missing something? Anyway, thanks for trying to fix this! :)

If needed, I'll try and make a reproducible small repo. Right now files are here: import line and webpack config.

@emilmuller
Copy link

I just did this for now

// @ts-ignore
import { marked } from "marked/lib/marked.esm.js"; // Using full path to library

@laustdeleuran
Copy link

laustdeleuran commented Mar 2, 2023

I'm also experiencing this issue on Webpack 5. I'm importing marked in a package that just compiles to JS. That compilation changes the import statement from import to require.

That package is then imported by my Webpack 5 library, that correctly installs marked as a dependency, but throws the TypeError: Cannot read properties of undefined (reading 'use') error.

If I manually change the import to point at the esm module it works. If I use Webpack's resolve functionality to point to the version I need and remove the exports declaration from the marked package, it works. That's not a workable solution, though, since the exports clause limits me to import it directly.

Any chance you could expose all the files in the lib folder in the exports clause to sidestep this issue? That would allow us to use @emilmuller's workaround with Webpack 5.

@UziTech
Copy link
Member

UziTech commented Mar 2, 2023

@laustdeleuran are you importing with import { marked } from 'marked'?

@laustdeleuran
Copy link

@UziTech sure am:

import { marked } from 'marked';

marked.use({
  ...
});

@benmccann
Copy link
Contributor

@laustdeleuran it's hard to understand what might be wrong in your case because you're using an intermediate package and I can't see the source of that package. Could you please share it? It's quite likely the issue may be there

@laustdeleuran
Copy link

laustdeleuran commented Mar 2, 2023

@benmccann , that's fair, I wish I had a more reproducible setup.

In short, we have a monorepo using pnpm. I have a package in that repo that uses marked. The file in question looks something like:

import DOMPurify from 'isomorphic-dompurify';
import { marked } from 'marked';

marked.use({
  renderer: {
    /* ...some options here */
  },
});

export const format = (markdown: string) =>
  DOMPurify.sanitize(marked.parse(markdown, { breaks: true }));

That package compiles that to CJS, which ends up looking something like:

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.format = void 0;

var _isomorphicDompurify = _interopRequireDefault(require("isomorphic-dompurify"));

var _marked = require("marked");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

_marked.marked.use({
  renderer: {
    /* ...some options here */
  }
});

const format = markdown => _isomorphicDompurify.default.sanitize(_marked.marked.parse(markdown, {
  breaks: true
}));

exports.format = format;

That module then gets imported in another project in the monorepo, which is a create-react-app. I'm trying to upgrade the react-scripts in that project, which means I'm also upgrading from Webpack 4 to Webpack 5. That upgrade is going smoothly, except for the above file now throwing the TypeError: Cannot read properties of undefined (reading 'use') error.

@laustdeleuran
Copy link

laustdeleuran commented Mar 2, 2023

@benmccann, if I get rid of the exports clause in marked's package.json, or expand it to include the individual builds, I can resolve this error by overriding the webpack import using resolve:

    "alias": {
      "marked": "marked/lib/marked.esm.js",
    },

Which in effect applies @emilmuller's fix to Webpack 5.

@laustdeleuran
Copy link

Put up a basic stab at that fix in #2747.

@benmccann
Copy link
Contributor

@laustdeleuran does it work any better if you change this:

import { marked } from 'marked';

marked.use({
  renderer: {
    /* ...some options here */
  },
});

To this?

import { use } from 'marked';

use({
  renderer: {
    /* ...some options here */
  },
});

Or maybe this?

import * as marked from 'marked';

marked.use({
  renderer: {
    /* ...some options here */
  },
});

There's still not enough info here to really understand what's going on. What's the package.json in the intermediate package, how is the intermediate package being bundled, etc.?

@laustdeleuran
Copy link

import { use } from 'marked';

As far as I can tell, marked doesn't export use directly? This just gets me a TS error:

Screenshot 2023-03-02 at 16 14 56

import * as marked from 'marked';

This just gets me the same result, as it just compiles to the same thing in CJS.


There's still not enough info here to really understand what's going on. What's the package.json in the intermediate package, how is the intermediate package being bundled, etc.?

Fair, but I don't really know how to make a small repro for you. Here's the subpackage's package.json:

{
  "private": true,
  "main": "./dist/src/index.js",
  "types": "./dist/src/index.d.ts",
  "dependencies": {
    "@babel/cli": "^7.14.8",
    "@babel/core": "^7.15.0",
    "@babel/preset-env": "^7.15.0",
    "@babel/preset-typescript": "^7.15.0",
    "@types/handlebars": "^4.1.0",
    "@types/marked": "^4.0.8",
    "babel-plugin-module-resolver": "^4.1.0",
    "date-fns": "^2.29.3",
    "handlebars": "^4.7.7",
    "imask": "^6.3.0",
    "isomorphic-dompurify": "^0.19.0",
    "lodash": "^4.17.21",
    "marked": "^4.2.12",
    "mockdate": "^3.0.2",
    "pluralize": "^8.0.0",
    "tsc-alias": "^1.3.9",
    "typescript": "^4.3.5"
  },
  "devDependencies": {
    "@types/jest": "^27.4.1",
    "@types/node": "^16.7.1",
    "@typescript-eslint/eslint-plugin": "^4.29.2",
    "@typescript-eslint/parser": "^4.29.2",
    "babel-jest": "^27.0.6",
    "eslint": "^7.32.0",
    "eslint-config-airbnb-base": "^14.2.1",
    "eslint-config-airbnb-typescript": "^13.0.1",
    "eslint-config-prettier": "^8.3.0",
    "eslint-import-resolver-typescript": "^2.5.0",
    "eslint-plugin-import": "^2.24.1",
    "eslint-plugin-jest-dom": "^3.9.0",
    "eslint-plugin-prettier": "^3.4.0",
    "eslint-plugin-testing-library": "^4.11.0",
    "jest": "^27.5.1",
    "prettier": "^2.5.1"
  },
  "scripts": {
    "lint": "pnpm run lint:eslint && pnpm run lint:tsc",
    "lint:eslint": "eslint . --cache",
    "lint:tsc": "tsc --noEmit",
    "test": "TZ='Etc/UTC' jest",
    "build": "tsc --project tsconfig.build.json --emitDeclarationOnly && tsc-alias --project tsconfig.build.json -s && babel . --out-dir dist --extensions .ts,.tsx --ignore 'node_modules,dist,**/*.test.ts'",
    "install": "pnpm run build"
  }
}

@laustdeleuran
Copy link

@benmccann

I managed to make a minimal-ish repo that reproduces the error:
https://github.com/laustdeleuran/marked-2265-module-import-export-issue

@UziTech
Copy link
Member

UziTech commented Mar 4, 2023

This seems like a bug in webpack. This is how webpack compiles marked in your minimal repo (Thanks for that by the way 💯). Than tries to call String.marked.use which throws the error.

/***/ "../node_modules/.pnpm/marked@4.2.12/node_modules/marked/lib/marked.cjs":
/*!******************************************************************************!*\
  !*** ../node_modules/.pnpm/marked@4.2.12/node_modules/marked/lib/marked.cjs ***!
  \******************************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";
module.exports = __webpack_require__.p + "static/media/marked.79f9f27bbd94805ba150.cjs";

/***/ }),

@UziTech
Copy link
Member

UziTech commented Mar 4, 2023

Or there is some webpack configuration that needs to be changed. I am not a webpack expert but it might be helpful to create an issue in their repo to see if someone has seen this before and has an easy fix.

@laustdeleuran
Copy link

Okay. Thanks for looking into it. I've opened an issue in Webpack's issue tracker here, so we'll see what they say.

@laustdeleuran
Copy link

laustdeleuran commented Mar 4, 2023

Webpack has a lot of open issues, though, so wondering if they'll have he resources to look into it. I looked in the issue tracker for create-react-app as well, and didn't see anything that looked related, outside of maybe facebook/create-react-app#12100.

Which, in concert with @UziTech's comment about configurations, made me wonder if it's something in create-react-app's configuration that is interacting badly with how marked is compiled when used in a subpackage. Ack, there's so many interlocking tools here that's it's difficult to detangle.

@laustdeleuran
Copy link

laustdeleuran commented Mar 4, 2023

I looked into the repo @LukeNotable mentioned above, and it looks remarkably similar to mine. Seems like it at least rules out pnpm as the culprit.

@laustdeleuran
Copy link

@UziTech @benmccann, my confidence in the Webpack maintainers getting back to us in a timely manner on this is decreasing.

According to @UziTech's analysis, it seems like @benmccann's earlier PR might have been on the right track. I wonder if it makes sense to see if that's a viable path forward, instead of waiting on @webpack to look at the issue on their end?

@UziTech
Copy link
Member

UziTech commented Mar 9, 2023

That PR won't help in your case because webpack is not using main. It is using the require export from

"default": "./lib/marked.cjs"

If we change that to esm than no one could use marked as a commons module. I think the correct solution here is to fix it in webpack and use webpack v4 until it is fixed.

@UziTech
Copy link
Member

UziTech commented Mar 9, 2023

Actually it looks like this might actually be a create-react-app issue instead of webpack. facebook/create-react-app#12700

Either way working around it in marked doesn't seem like the right way to go.

There is a work around in the cra issue. I haven't tried it but that looks like a better work around.

@laustdeleuran
Copy link

Looping back around. I can confirm that this looks to be an issue in create-react-app.

There's some more context in facebook/create-react-app#12700, including a couple of PRs to solve the issue, as well as a couple of workarounds.

@daniel-bergmann
Copy link

It looks like somewhere in your code you are trying to import the default export like import marked from 'marked'.

Make sure you replace all occurrences with import { marked } from 'marked'

This solved it for me

@scharf
Copy link

scharf commented Aug 4, 2023

I am using Meteor, which has its own build system. Long story short: the only way I made it work was:

// @ts-ignore
import { marked } from 'marked/lib/marked.esm';

Not very satisfying, but it works.

@LassiterPrime
Copy link

LassiterPrime commented Oct 6, 2023

Late to the party here, but ran into the same thing. The issue was the last 3 lines of marked.d.ts

Make the following changes:

Original

    export type * from "MarkedOptions";
    export type * from "rules";
    export type * from "Tokens";

Corrected

    export type { MarkedOptions } from "MarkedOptions";
    export type { Rules } from "rules";
    export type { Tokens } from "Tokens";

@davidsandoz
Copy link

I'm using marked with Nuxt.js v2 and also had some trouble importing the module after upgrading from v5.1.2 to v9.1.0.

I was importing the module in a Nuxt plugin with

import {marked} from 'marked';

And during the build I got

ERROR in ./node_modules/marked/lib/marked.umd.js 253:15
Module parse failed: Unexpected token (253:15)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|      */
|     class _Tokenizer {
>         options;
|         // TODO: Fix this rules type
|         rules;
 @ ./plugins/markdown.ts 4:13-30
 @ ./.nuxt/index.js
 @ ./.nuxt/client.js
 @ multi ./node_modules/@nuxt/components/lib/installComponents.js ./.nuxt/client.js

After trying out a lot of different potential solutions, what ended up making it work was to add marked to the transpile array of the build option in nuxt.config.ts:

build: {
  transpile: ['marked']
}

@mazemax
Copy link

mazemax commented Oct 25, 2023

Thanks @davidsandoz, following line solved this issue:

build: {
  transpile: ['marked']
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet