bs-ant-design
bs-ant-design copied to clipboard
ES6 default imports are broken in ParcelJS
👋
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.
I think this is Parcel not working correctly. antd/lib/button is a commonjs module by all means
It looks like it is using ES6 import/export syntax
And according to https://github.com/parcel-bundler/parcel/issues/1584#issuecomment-403265873 that import shouldn't work as it is not to spec.
@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)
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?
@johnhaley81 Does jsx3 help this situation at all? https://github.com/Enalmada/bs-ant-design/pull/2