Parcel: How to import node module with mixed CJS and ES imports

Created on 20 Jun 2018  ·  2Comments  ·  Source: parcel-bundler/parcel

❔ Question

How do you import node modules which were compiled using Webpack and have mixed ES and CommonJS imports?

This causes errors for me and I can't find a working workaround.

🔦 Context

Here's a more detailed example of my problem. In my code, I try to import a node module A:

import A from 'A';

In node_modules/A/index.js it looks like this:

import * as B from 'B';
B();

And node_modules/B/index.js:

module.exports = function () {};

At runtime, an error is thrown at B() because B actually looks like { default: function () {} }.

As far as I can tell, it looks like Parcel uses Babel to transpile the imports into require()s. Babel treats module.exports as the default export, which is why import * as returns an object, but Webpack treats module.exports as the object containing all exports (with module.exports.default being the default export).

I don't know of any spec for importing CommonJS modules from ES modules and Babel seems to follow Node's implementation (instead of Webpack's) so it's not necessarily a bug but it would be nice if Parcel could handle this case since it's preventing me from using a node module which is critical for my project (and hence I can't use Parcel for the project).

Right now I'm looking for any solution at all. Even if that means writing a Babel plugin for the Webpack importing logic (though I can't see how to replace Babel's helper plugin without modifying Parcel).

💻 Code Sample

https://github.com/jakzo/parcel-import-problem

Run yarn webpack then yarn parcel to see the issue.

🌍 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.9.2
| Node | 10.1.0
| npm/Yarn | Yarn 1.6.0
| Operating System | Mac OS X

Question

Most helpful comment

import * as B from 'B';
B();

This is not valid ES6 code. typeof B === 'object' is guaranteed by the spec, you can fix this by using import default instead :

import B from 'B';
B();

You don't have access to the module, so you can use Parcel's alias feature as a workaround :

  • package.json
{
  ...,
  "alias": {
    "b": "./src/b-es6"
  }
}
  • src/b-es6.js
module.exports = require('../node_modules/b')
module.exports.__esModule = true

All 2 comments

@jakzo You can enable hosting and treeshake by --experimental-scope-hoisting flag. I tried and it is working.

import * as B from 'B';
B();

This is not valid ES6 code. typeof B === 'object' is guaranteed by the spec, you can fix this by using import default instead :

import B from 'B';
B();

You don't have access to the module, so you can use Parcel's alias feature as a workaround :

  • package.json
{
  ...,
  "alias": {
    "b": "./src/b-es6"
  }
}
  • src/b-es6.js
module.exports = require('../node_modules/b')
module.exports.__esModule = true
Was this page helpful?
0 / 5 - 0 ratings

Related issues

jzimmek picture jzimmek  ·  3Comments

urbanhop picture urbanhop  ·  3Comments

termhn picture termhn  ·  3Comments

philipodev picture philipodev  ·  3Comments

algebraic-brain picture algebraic-brain  ·  3Comments