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

ES6 default imports are broken in ParcelJS #21

Open
johnhaley81 opened this issue Nov 5, 2018 · 5 comments
Open

ES6 default imports are broken in ParcelJS #21

johnhaley81 opened this issue Nov 5, 2018 · 5 comments

Comments

@johnhaley81
Copy link

👋

Thanks for the bindings.

I tried to use them in a project that was bundled with ParcelJS and it wasn't able to use the bindings as they are defined. The default export is not pulled in correctly. For example, changing a binding from:

[@bs.module] external reactClass: ReasonReact.reactClass = "antd/lib/button";

to:

[@bs.module "antd/lib/button"] external reactClass: ReasonReact.reactClass = "default";

Fixed the issue.

@thangngoc89
Copy link
Owner

I think this is Parcel not working correctly. antd/lib/button is a commonjs module by all means

@johnhaley81
Copy link
Author

It looks like it is using ES6 import/export syntax

And according to parcel-bundler/parcel#1584 (comment) that import shouldn't work as it is not to spec.

@thangngoc89
Copy link
Owner

@johnhaley81 you need to check the generated source. antd/lib/button is a commonjs module. I can't remember why I chose commonjs format of antd instead of es6 (it ships both format)

@johnhaley81
Copy link
Author

So I did some more research on what was happening and came across some madness.

How Import is breaking

I'm using "module": "es6" in my bsconfig.json which is outputting ES6 code.

This gives me an Antd_Button.js with:

// Generated by BUCKLESCRIPT VERSION 4.0.6, PLEASE EDIT WITH CARE

import * as Js_option from "bs-platform/lib/es6/js_option.js";
import * as Js_mapperRt from "bs-platform/lib/es6/js_mapperRt.js";
import * as ReasonReact from "reason-react/src/ReasonReact.js";
import * as Js_primitive from "bs-platform/lib/es6/js_primitive.js";
import * as Button from "antd/lib/button";

When we import antd/lib/button with the wildcard * the ES6 import spec says that you must get back an object. ParcelJS will force the module to be compliant to this if it is not an ES6 module. It checks this by looking at __esModule like so:

function _interopRequireWildcard(obj) { 
  if (obj && obj.__esModule) { 
    return obj; 
  } else { 
    var newObj = {}; 
    if (obj != null) { 
      for (var key in obj) { 
        if (Object.prototype.hasOwnProperty.call(obj, key)) { 
          var desc = Object.defineProperty && Object.getOwnPropertyDescriptor 
            ? Object.getOwnPropertyDescriptor(obj, key) 
            : {}; 
          if (desc.get || desc.set) { 
            Object.defineProperty(newObj, key, desc); 
          } else { 
            newObj[key] = obj[key]; 
          } 
        } 
      } 
    } 
    newObj.default = obj; 
    return newObj; 
  } 
}

Now, this is breaking because antd/lib/button already went through the conversion and is a commonjs file as you correctly asserted earlier:

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _button = require('./button');

var _button2 = _interopRequireDefault(_button);

var _buttonGroup = require('./button-group');

var _buttonGroup2 = _interopRequireDefault(_buttonGroup);

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

_button2['default'].Group = _buttonGroup2['default'];
exports['default'] = _button2['default'];
module.exports = exports['default'];

Note the last line where module.exports = exports['default'] So ParcelJS is correctly seeing a commonjs file and is converting that back into an ES6 module since the code generated by bsb is expecting an ES6 module. Thus, when Button is referenced inside of Antd_Button.js it is actually the object of the ES6 module.

Conclusion

Currently, additional steps are required if the user is using bsb to compile to es6.

Workaround

Currently you can fix this by bringing in babel-plugin-import@^1.6.3, babel-preset-env@^1.6.1, babel-preset-react!^6.24.1 and set your .babelrc to use them. This will have ParcelJS force all of your code into commonjs. This seems a little convoluted however and it would be easier to just not use "module": "es6" at all unless you had to.

Possible fix?

Would it be possible to switch the bindings to all use antd/es6/*? Would that break bs modules that use commonjs?

@Enalmada
Copy link
Collaborator

Enalmada commented May 6, 2019

@johnhaley81 Does jsx3 help this situation at all? Enalmada#2

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

No branches or pull requests

3 participants