Parcel: Tree Shaking claims a library in an applications doesn't export a function

Created on 14 Jun 2018  路  22Comments  路  Source: parcel-bundler/parcel

馃悰 bug report

Running --experimental-scope-hoisting will fail to bundle an app claiming that an library is not exporting a file. I checked node modules to see if this was the case, but it's not. The function is being exported.

Error when bucklescript outputs es modules:
screen shot 2018-06-14 at 2 15 29 pm

Error when bucklescript outputs commonjs:
screen shot 2018-06-14 at 2 27 29 pm

Code the error refers to node_modules/react-infinite-calendar/es/Calendar/withDateSelection.js:

import _withState from 'recompose/withState';
import _withPropsOnChange from 'recompose/withPropsOnChange';
import _withProps from 'recompose/withProps';
import _compose from 'recompose/compose';

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }

import { withDefaultProps } from './';
import { sanitizeDate, withImmutableProps } from '../utils';
import format from 'date-fns/format';
import parse from 'date-fns/parse';

export var enhanceDay = _withPropsOnChange(['selected'], function (props) {
  return {
    isSelected: props.selected === props.date
  };
});

var enhanceYear = _withPropsOnChange(['selected'], function (_ref) {
  var selected = _ref.selected;
  return {
    selected: parse(selected)
  };
});

// Enhancer to handle selecting and displaying a single date
var withDateSelection = _compose(withDefaultProps, withImmutableProps(function (_ref2) {
  var DayComponent = _ref2.DayComponent,
      onSelect = _ref2.onSelect,
      setScrollDate = _ref2.setScrollDate,
      YearsComponent = _ref2.YearsComponent;
  return {
    DayComponent: enhanceDay(DayComponent),
    YearsComponent: enhanceYear(YearsComponent)
  };
}), _withState('scrollDate', 'setScrollDate', function (props) {
  return props.selected || new Date();
}), _withProps(function (_ref3) {
  var _onSelect = _ref3.onSelect,
      setScrollDate = _ref3.setScrollDate,
      props = _objectWithoutProperties(_ref3, ['onSelect', 'setScrollDate']);

  var selected = sanitizeDate(props.selected, props);

  return {
    passThrough: {
      Day: {
        onClick: _onSelect
      },
      Years: {
        onSelect: function onSelect(year) {
          return handleYearSelect(year, { onSelect: _onSelect, selected: selected, setScrollDate: setScrollDate });
        }
      }
    },
    selected: selected && format(selected, 'YYYY-MM-DD')
  };
}));

export { withDateSelection };
function handleYearSelect(date, _ref4) {
  var setScrollDate = _ref4.setScrollDate,
      selected = _ref4.selected,
      onSelect = _ref4.onSelect;

  var newDate = parse(date);

  onSelect(newDate);
  setScrollDate(newDate);
}

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

bsconfig:

{
  "name": "...",
  "bs-dependencies": [
    "reason-react",
    "bs-fetch",
    "@glennsl/bs-json",
    "bs-css",
    "regql"
  ],
  "ppx-flags": ["graphql_ppx/ppx"],
  "reason": {
    "react-jsx": 2
  },
  "refmt": 3,
  "sources": ["vcomponents", "components", "pages", "styles"],
  // "package-specs": ["es6-global"],
  "bsc-flags": ["-bs-super-errors"]
}

package.json:

{
  "name": "....",
  "version": "0.1.0",
  "description": "....",
  "main": "index.js",
  "private": true,
  "dependencies": {
    "@glennsl/bs-json": "^2.0.0",
    "bs-css": "^6.7.0",
    "bs-fetch": "^0.3.0",
    "cross-env": "^5.2.0",
    "graphql_ppx": "^0.2.3",
    "prismjs": "^1.14.0",
    "react-addons-css-transition-group": "^15.6.2",
    "react-infinite-calendar": "^2.3.1",
    "react-markdown": "^3.3.3",
    "reason-react": "0.4.2",
    "regql": "0.5.0-beta.10",
    "serve": "^8.2.0",
    "stijs": "^1.0.0",
    "typeface-catamaran": "^0.0.54",
    "typeface-montserrat": "^0.0.54"
  },
  "devDependencies": {
    "bs-platform": "3.1.5",
    "parcel-bundler": "1.9.0"
  }
}

馃 Expected Behavior

Should bundle application

馃槸 Current Behavior

fails to bundle application

馃敠 Context

Trying to add tree shaking to existing applications using parcel. Hope this helps find bugs in the new scope hoisting feature.

馃實 Your Environment

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.9.0
| Node | 10.4.0
| npm/Yarn | 1.7.0
| Operating System | macOS

Bug 馃尦 Tree Shaking

Most helpful comment

Can confirm, same issue here, using material-ui/core.

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.9.0
| Node | 10.4.0
| npm/Yarn | 1.7.0
| Operating System | macOS

myFile.jsx:
import { Button, CircularProgress, Grid } from '@material-ui/core';

index.es.js from material-ui/core:

...
export { default as Grid } from './Grid';
...
馃毃  ../node_modules/@material-ui/core/index.es.js does not export 'Grid'
    at replaceExportNode (/Users/mirigoyen/Git/projectname/node_modules/parcel/src/scope-hoisting/concat.js:98:13)
    at ReferencedIdentifier (/Users/mirigoyen/Git/projectname/node_modules/parcel/src/scope-hoisting/concat.js:353:20)
    at newFn (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/visitors.js:318:17)
    at NodePath._call (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitMultiple (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/context.js:103:17)
    at TraversalContext.visit (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/context.js:190:19)
    at Function.traverse.node (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/index.js:114:17)

All 22 comments

would be helpful if you could provide some code that reproduces the issue. it will be pretty hard for us to debug otherwise.

@devongovett Sorry issue submitted as I was starting to fill out the issue template. I just finished filling it out now

Can confirm, same issue here, using material-ui/core.

| Software | Version(s) |
| ---------------- | ---------- |
| Parcel | 1.9.0
| Node | 10.4.0
| npm/Yarn | 1.7.0
| Operating System | macOS

myFile.jsx:
import { Button, CircularProgress, Grid } from '@material-ui/core';

index.es.js from material-ui/core:

...
export { default as Grid } from './Grid';
...
馃毃  ../node_modules/@material-ui/core/index.es.js does not export 'Grid'
    at replaceExportNode (/Users/mirigoyen/Git/projectname/node_modules/parcel/src/scope-hoisting/concat.js:98:13)
    at ReferencedIdentifier (/Users/mirigoyen/Git/projectname/node_modules/parcel/src/scope-hoisting/concat.js:353:20)
    at newFn (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/visitors.js:318:17)
    at NodePath._call (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/path/context.js:76:18)
    at NodePath.call (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/path/context.js:48:17)
    at NodePath.visit (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/path/context.js:105:12)
    at TraversalContext.visitQueue (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/context.js:150:16)
    at TraversalContext.visitMultiple (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/context.js:103:17)
    at TraversalContext.visit (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/context.js:190:19)
    at Function.traverse.node (/Users/mirigoyen/Git/projectname/node_modules/babel-traverse/lib/index.js:114:17)

@goyney I was curious to try it out on Material-UI too.

../node_modules/@material-ui/core/index.es.js does not export 'Grid'

Still, we have this line in the index.es.js file:

export { default as Grid } from './Grid';

Going one step deeper, you will find the following in Grid.js:

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/builtin/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
Object.defineProperty(exports, "default", {
  enumerable: true,
  get: function get() {
    return _Grid.default;
  }
});

var _Grid = _interopRequireDefault(require("./Grid"));

mmm looks like Grid is precompiled to compiled commonjs. sounds like an issue with interop between es6 imports and commonjs exports.

@devongovett The current Material-UI tradeoff can seem "broken". We are only providing an esm version of the index.js (index.es.js). We don't do it for the submodules to prevent module duplication in people bundle. The large majority of the packages build on top of Material-UI imports the modules directly. Take this example, libraries do:

import Grid from '@material-ui/core/Grid'

Instead of

import { Grid } from '@material-ui/core'

The current tradeoff doesn't work with how webpack implements tree-shaking.

Same error here, while trying to use Apollo Client:

脳  ..\node_modules\apollo-client\index.js does not export 'ApolloError'
    at replaceExportNode (D:\Dev\new_urelay\shipper\node_modules\parcel-bundler\src\scope-hoisting\concat.js:98:13)
    at ReferencedIdentifier (D:\Dev\new_urelay\shipper\node_modules\parcel-bundler\src\scope-hoisting\concat.js:353:20)
    at newFn (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\visitors.js:318:17)
    at NodePath._call (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\path\context.js:76:18)
    at NodePath.call (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\path\context.js:48:17)
    at NodePath.visit (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\path\context.js:105:12)
    at TraversalContext.visitQueue (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\context.js:150:16)
    at TraversalContext.visitSingle (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\context.js:108:19)
    at TraversalContext.visit (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\context.js:192:19)
    at Function.traverse.node (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\index.js:114:17)
error Command failed with exit code 1.

also happens when using antd

脳  ..\node_modules\antd\es\version\index.js does not export 'default'
    at replaceExportNode (D:\Dev\new_urelay\shipper\node_modules\parcel-bundler\src\scope-hoisting\concat.js:98:13)
    at ReferencedIdentifier (D:\Dev\new_urelay\shipper\node_modules\parcel-bundler\src\scope-hoisting\concat.js:353:20)
    at newFn (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\visitors.js:318:17)
    at NodePath._call (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\path\context.js:76:18)
    at NodePath.call (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\path\context.js:48:17)
    at NodePath.visit (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\path\context.js:105:12)
    at TraversalContext.visitQueue (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\context.js:150:16)
    at TraversalContext.visitSingle (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\context.js:108:19)
    at TraversalContext.visit (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\context.js:192:19)
    at Function.traverse.node (D:\Dev\new_urelay\shipper\node_modules\babel-traverse\lib\index.js:114:17)

@reflog did you try #1542 ?

fix is released in v1.9.1.

@devongovett Awesome.
Still, I have this issue now. I can open an issue if you wish:

Property right of AssignmentExpression expected node to be of a type ["Expression"] but instead got null
at Object.validate (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/babel-types/lib/definitions/index.js:109:13)
at Object.validate (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/babel-types/lib/index.js:505:9)
at NodePath._replaceWith (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/babel-traverse/lib/path/replacement.js:176:7)
at NodePath._remove (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/babel-traverse/lib/path/removal.js:58:10)
at NodePath.remove (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/babel-traverse/lib/path/removal.js:30:8)
at binding.referencePaths.concat.forEach.path (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/parcel-bundler/src/scope-hoisting/shake.js:41:22)
at Array.forEach ()
at Object.keys.forEach.name (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/parcel-bundler/src/scope-hoisting/shake.js:32:10)
at Array.forEach ()
at treeShake (/Users/oliviertassinari/material-ui-next/examples/parcel/node_modules/parcel-bundler/src/scope-hoisting/shake.js:20:33)

import { Grid } from '@material-ui/core';

@oliviertassinari sounds like #1549.

Thanks, yes it's.

@devongovett just tried out the new release, I still come across this same exact error.

Still i have the issue with date-fns on build + tree shake (but it works pretty well with a normal build).

node_modules/date-fns/esm/endOfWeek/index.js does not export 'default'
at replaceExportNode ((...)/node_modules/parcel-bundler/src/scope-hoisting/concat.js:54:13)
at ReferencedIdentifier ((...)/node_modules/parcel-bundler/src/scope-hoisting/concat.js:317:20)
at newFn ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/visitors.js:230:17)
at NodePath._call ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/path/context.js:53:20)
at NodePath.call ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/path/context.js:40:17)
at NodePath.visit ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/path/context.js:88:12)
at TraversalContext.visitQueue ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/context.js:118:16)
at TraversalContext.visitSingle ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/context.js:90:19)
at TraversalContext.visit ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/context.js:146:19)
at Function.traverse.node ((...)/node_modules/parcel-bundler/node_modules/@babel/traverse/lib/index.js:94:17)
error Command failed with exit code 1>

Issue with "@sentry/browser": "^5.4.3",
Throws node_modules/@sentry/browser/esm/sdk.js does not export 'init' when --experimental-scope-hoisting

@baltuonis Can you provide a code sample?

@mturki Which version of date-fns are you using and please provide a code sample.

@mischnic

import * as Sentry from '@sentry/browser'; (fails)
// also tried:
// import { init } from '@sentry/browser'; (fails)
// <...> from '@sentry/browser/dist/sdk; (in this case the init part gets transpiled to ({})   )
// <...> from '@sentry/browser/esm/sdk; (fails)
// <...> from '@sentry/browser/esm/; (fails)
// tried old Sentry v5.0 - and the init get's transpiled to ({})

  Sentry.init({
    dsn: window.SENTRY_DSN,
    environment: window.ENV
  });

Deps:

    "@babel/core": "^7.4.5",
    "@google/markerclusterer": "1.0.3",
    "@types/googlemaps": "^3.36.5",
    "@sentry/browser": "^5.4.3",
    "babel-plugin-transform-remove-console": "6.9.4",
    "choices.js": "^7.0.0",
    "cross-env": "^5.2.0",
    "lazysizes": "^5.1.0",
    "parcel-bundler": "^1.12.3",
    "smooth-scroll": "^16.1.0",
    "typescript": "^3.5.2"

@baltuonis Works fine for me with just that code. Is that a typescript file? What's your tsconfig.json?

@mischnic - yes it's Typescript.
No tsconfig.json (it's parcel ;-))
It was failing both on build server and my machine

Still, can't get it to throw that error: https://github.com/mischnic/parcel-issue-1540

Hi! I'm getting this same error (or maybe just similar) when using "@risingstack/react-easy-state": "^6.3.0".

The error:

馃毃 Build failed.
@parcel/packager-js: nodemodules/@risingstack/react-easy-state/dist/react-platform.js does not export 'unstablebatchedUpdates'
node_modules/@risingstack/react-easy-state/dist/es.es6.js:4:10
  3 | export { unobserve as clearEffect } from '@nx-js/observer-util';
> 4 | import { unstable_batchedUpdates } from './react-platform';
>   |          ^^^^^^^^^^^^^^^^^^^^^^^

This is happening with "parcel": "^2.0.0-beta.1" but also with the v1 when using the experimental tree shaking option. The error log is slightly different, but it's still the same error.

The code in the files referenced:

// nodemodules/@risingstack/react-easy-state/dist/react-platform.js

export * from 'react-dom';
// node_modules/@risingstack/react-easy-state/dist/es.es6.js:4:10

import { useState, memo, useMemo, useEffect, Component } from 'react';
import { observe, unobserve, isObservable, raw, observable } from '@nx-js/observer-util';
export { unobserve as clearEffect } from '@nx-js/observer-util';
import { unstable_batchedUpdates } from './react-platform';

Let me know if you need any other details, or if you have suggestions on how to fix it :)

Was this page helpful?
0 / 5 - 0 ratings