aurelia / webpack-plugin

A plugin for webpack that enables bundling Aurelia applications.
MIT License
90 stars 36 forks source link

[Webpack 5] Exports are not preserved for some plugins, which causes the DI to crash due to lack of configure() #183

Closed graycrow closed 3 years ago

graycrow commented 3 years ago

I'm submitting a bug report

Please tell us about your environment:

Current behavior:

As I mentioned in https://github.com/aurelia/webpack-plugin/issues/181#issuecomment-876436789, I have some issues after changing the module type to ESNext.

An attempt to inject some plugins ends up with the following runtime error: Error: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?

I found that all the plugins giving this error were not configured with configure() because it does not exist in the webpack-generated build.

Here is an example, let's take 2 plugins, aurelia-store 1.7.0 and aurelia-dialog 2.0.0 They are registered in the main.ts, nothing special:

aurelia.use
.plugin(PLATFORM.moduleName("aurelia-store"), {
            initialState,
            history: {
                undoable: false,
                limit: 4,
            },
        })
.plugin(PLATFORM.moduleName("aurelia-dialog"), (config) => {
            config.useDefaults();
            config.useCSS("");
        })

Webpack (using config from #181 with turned off minification) bundled them as following:

/***/ "aurelia-store":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "yh": () => (/* binding */ Store),
  "bZ": () => (/* binding */ connectTo)
});

// UNUSED EXPORTS: DEFAULT_LOCAL_STORAGE_KEY, LogLevel, LoggerIndexed, MiddlewarePlacement, PerformanceMeasurement, UnregisteredActionError, applyLimits, configure, dispatchify, executeSteps, getLogType, isStateHistory, jump, localStorageMiddleware, logMiddleware, nextStateHistory, rehydrateFromLocalStorage

and

/***/ "aurelia-dialog":
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "DialogController": () => (/* reexport safe */ _chunk_js__WEBPACK_IMPORTED_MODULE_0__.d),
/* harmony export */   "DefaultDialogSettings": () => (/* binding */ DefaultDialogSettings),
/* harmony export */   "DialogConfiguration": () => (/* binding */ DialogConfiguration),
/* harmony export */   "DialogService": () => (/* binding */ DialogService),
/* harmony export */   "configure": () => (/* binding */ configure)
/* harmony export */ });
/* harmony import */ var _chunk_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6066);
/* harmony import */ var aurelia_pal__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7504);
/* harmony import */ var aurelia_dependency_injection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3361);
/* harmony import */ var aurelia_templating__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8791);

As you can see, aurelia-dialog properly exported as harmony module, but aurelia-store has mangled names and unused configure(). Some plugins are fine, and some (store and i18n are the notable examples) are broken, and I cannot find the pattern yet.

If I set webpack optimization option mangleExports to false, it restores the function names and usedExports: false solves the issue, but in the cost of broken tree-shaking and huge bundle size.

I have a feeling that it has something to do with the PreserveExportsPlugin, but unfortunately I was not able to trace the origin of the problem.

graycrow commented 3 years ago

Can confirm, issue has been fixed. Big thanks!