Parcel: Parcel reports "Export 'X' is not defined" if a ESM module tries to export a `function`

Created on 20 Mar 2019  路  16Comments  路  Source: parcel-bundler/parcel

馃悰 bug report

If in an ESM module the export statement refers to a function, this consistently fails the build.

馃帥 Configuration (.babelrc, package.json, cli command)

To reproduce, clone: https://github.com/mweststrate/parcel-bug, yarn install, yarn build

This happens with an out-of-the-box configuration with parcel, no .babelrc, package.json:

{
  "name": "parcel-bug",
  "version": "1.0.0",
  "main": "index.js",
  "author": "Michel Weststrate <[email protected]>",
  "license": "MIT",
  "devDependencies": {
    "parcel-bundler": "^1.12.2"
  },
  "scripts": {
    "build": "parcel public/index.html"
  },
  "dependencies": {
    "immer": "^2.1.4"
  }
}

馃 Expected Behavior

The project should build without error, even when an export statement references a function

馃槸 Current Behavior

Build failure, any referred function is reported as Export '...' is not defined

When using the immer package with parcel I consistently get the following build error:

馃毃  /home/michel/Dropbox/presentaties/parcel-bug/node_modules/immer/dist/immer.module.js:1065:113: Export 'original' is not defined (1065:113)
  1063 | 
  1064 | export default produce;
> 1065 | export { produce, setAutoFreeze, setUseProxies, applyPatches$1 as applyPatches, createDraft, finishDraft, Immer, original, isDraft, isDraftable, NOTHING as nothing, DRAFTABLE as immerable };
       |                                                                                                                 ^
  1066 | 
  1067 | 

The package does bundle correctly when original, isDraft and isDraftable are removed from the export statement. Unlike all other exports, which are defined as var, these three are defined as functions in the module scope in node_modules/immer/dist/immer.module.js, like:

function original(value) {
  if (value && value[DRAFT_STATE]) {
    return value[DRAFT_STATE].base;
  } // otherwise return undefined
}

馃拋 Possible Solution

馃敠 Context

I'm converting a CRA app to parcel, however this is withholding me from that.

馃捇 Code Sample

https://github.com/mweststrate/parcel-bug

馃實 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.12.2 |
| Node | 6.4.1 |
| npm/Yarn | 1.12.3 |
| Operating System | Linux x250 4.18.0-15-generic #16-Ubuntu SMP Thu Feb 7 10:56:39 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux |

Stale babel 鉁栵笍 Non-Parcel bug

Most helpful comment

Following the lead from @Zero2key, the babel parser seems to be the culprit and just doing this package gets our builds working for now (as a workaround until a fix is introduced):
"@babel/parser": "<7.4.0",

All 16 comments

Got the same thing with mobx-react: node_modules/mobx-react/index.module.js:1450:53: Export 'observer' is not defined (1450:53)

Also got the same thing withredux:node_modules/redux/es/redux.js:636:9: Export 'createStore' is not defined (636:9)

Same issue here:

[...]node_modules/react-router-dom/esm/react-router-dom.js:247:42: Export 'NavLink' is not defined (247:42)

Also got the same thing withredux:node_modules/redux/es/redux.js:636:9: Export 'createStore' is not defined (636:9)

I lock these package version parcel used, @babel/* < 7.4.0. Now resolve this problem.
Seems @babel/*
@7.4.0 problem, it have breaking change babel/babel#7646 (comment)

    "@babel/core": "<7.4.0",
    "@babel/plugin-transform-runtime": "<7.4.0",
    "@babel/preset-env": "<7.4.0",
    "@babel/code-frame": "<7.4.0",
    "@babel/generator": "<7.4.0",
    "@babel/parser": "<7.4.0",
    "@babel/plugin-transform-flow-strip-types": "<7.4.0",
    "@babel/plugin-transform-modules-commonjs": "<7.4.0",
    "@babel/plugin-transform-react-jsx": "<7.4.0",
    "@babel/template": "<7.4.0",
    "@babel/traverse": "<7.4.0",
    "@babel/types": "<7.4.0",

I use typescript, no babel in project, but it hurts my current build with mobx-react :(

Following the lead from @Zero2key, the babel parser seems to be the culprit and just doing this package gets our builds working for now (as a workaround until a fix is introduced):
"@babel/parser": "<7.4.0",

Confirmed that adding just the following to package.json works as a work around (not sure what other things it breaks obviously)

  "resolutions": {
    "@babel/parser": "7.3.0"
  },

@mweststrate confirm it HELPS ME A LOT!!!

There is no matching babel issue open, correct? (which isn't strange since 7.4.0 was only released yesterday).

Maintainers: does this mean a new issue should be opened on babel? Or is it an API compatibility issue with the latest babel version?

I find this @babel/parser PR Allow any reserved word in export {} from specifiers #9616, maybe this PR cause problem, but I don't confirm.

It triggered by this line in Parcel.

Setting strictMode to null (which seems to be the default) or true works. false fails with that error.

https://github.com/parcel-bundler/parcel/blob/32f332782e830036c775dc7ad2631b5801719dc3/packages/core/parcel-bundler/src/assets/JSAsset.js#L56-L64

Reproduction using only Babel:

const parser = require("@babel/parser");

const code = `
function original(value) {
  if (value) {
    return value.base;
  }
}

export { original };
`;

console.log(parser.parse(code, {
  strictMode: false, // <-------------------- works with `true` or `null`
  sourceType: 'module',
}));

So I guess it's a Babel bug?

Just released parcel v1.12.3 which downgrades Babel to <7.4 while we figure this out.

Filed this issue with babel: https://github.com/babel/babel/issues/9720

Fixed in Babel 7.4.2

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

davidnagli picture davidnagli  路  3Comments

adamreisnz picture adamreisnz  路  3Comments

Niggler picture Niggler  路  3Comments

termhn picture termhn  路  3Comments

466023746 picture 466023746  路  3Comments