FormidableLabs / inspectpack

An inspection tool for Webpack frontend JavaScript bundles.
MIT License
592 stars 20 forks source link

Feature: Enhance `--action=parse --suspect-parses` to infer multiple ES6 exports. #14

Closed ryan-roemer closed 8 years ago

ryan-roemer commented 8 years ago

of this form:

/* 243 */
/*!************************************!*\
  !*** ./~/react-redux/lib/index.js ***!
  \************************************/
/***/ function(module, exports, __webpack_require__) {

    'use strict';

    exports.__esModule = true;
    exports.connect = exports.Provider = undefined;

    var _Provider = __webpack_require__(/*! ./components/Provider */ 244);

    var _Provider2 = _interopRequireDefault(_Provider);

    var _connect = __webpack_require__(/*! ./components/connect */ 246);

    var _connect2 = _interopRequireDefault(_connect);

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

    exports.Provider = _Provider2["default"];
    exports.connect = _connect2["default"];

/***/ }

Task:

Add a new MULTIPLE_EXPORTS_ES key with parse to detect this common form.

/cc @divmain

divmain commented 8 years ago

Without digging into it, it seems that this would involve:

It may also be possible to recursively examine scope when certain conditions are met, but this seems like it would perform poorly.

That should solve the case you've outlined above. However, it would not account for destructured imports/exports, which is probably equally likely to occur, and which could add significant complexity. I can't remember how Babel transpiles those references - it may be moduleName.exportName which seems doable at first glance.

Keep in mind that adding a second parse-and-traverse step will worsen performance. If you can detect as part of the same parse-and-traverse, that would be ideal. However, if that's not an option, you may be able to at least cache that AST to avoid the second (or third) parse.

ryan-roemer commented 8 years ago

@divmain -- Maybe we just simplify the problem space to a heuristic of detecting just this instead:

    exports.Provider = _Provider2["default"];
    exports.connect = _connect2["default"];

OR

    exports.Provider = _Provider2.default;
    exports.connect = _connect2.default;

So basically:

    exports.Foo = Foo.default;
    exports.Bar = Bar["default"];

How much effort would that take?

divmain commented 8 years ago

That would be much easier, so long as

  1. you won't require support for named imports,
  2. you don't care too much about the possibility of false-positives, and
  3. you don't care about whether you're doubling up on a single module (exporting two things from a single import).

If that's the case, I can't imagine it would take more than a couple of hours. The last issue should be mitigable if you track the source variables (_Provider2 and _connect2 in your example), given a bit more time.

One other thing to note is that I'm unsure of the stability of the ES6-require interop code. Its definitely not an externally-facing API, so there's the risk of this silently breaking on you down the line.

ryan-roemer commented 8 years ago

Released in inspectpack@0.4.1