aurelia / webpack-plugin

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

HookWebpackError: __webpack_modules__ is not defined when importing css/scss in typescript file #197

Closed marekpetak closed 2 years ago

marekpetak commented 2 years ago

Only see this issue in newly created Aurelia V1 project using Webpack 5. Older versions, using webpack 4 work fine.

Probably related to #196

to reproduce:

  1. New Aurelia V1 project via au new appName → options typescript,htmlmin,sass,vscode
  2. Add bootstrap and bootswatch via npm install.
  3. import "bootswatch/dist/yeti/bootstrap.min.css"; in main.ts
  4. au run --watch
  5. error:
ERROR in ./node_modules/bootswatch/dist/yeti/bootstrap.min.css
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
HookWebpackError: __webpack_modules__ is not defined
    at tryRunOrWebpackError (D:\src_csharp\e3app\e3web\node_modules\webpack\lib\HookWebpackError.js:88:9)
    at __webpack_require_module__ (D:\src_csharp\e3app\e3web\node_modules\webpack\lib\Compilation.js:4963:12)
    at D:\src_csharp\e3app\e3web\node_modules\webpack\lib\Compilation.js:4987:11
    at symbolIterator (D:\src_csharp\e3app\e3web\node_modules\neo-async\async.js:3485:9)
    at timesSync (D:\src_csharp\e3app\e3web\node_modules\neo-async\async.js:2297:7)
    at Object.eachLimit (D:\src_csharp\e3app\e3web\node_modules\neo-async\async.js:3463:5)
    at D:\src_csharp\e3app\e3web\node_modules\webpack\lib\Compilation.js:4863:16
    at symbolIterator (D:\src_csharp\e3app\e3web\node_modules\neo-async\async.js:3485:9)
    at done (D:\src_csharp\e3app\e3web\node_modules\neo-async\async.js:3527:9)
    at D:\src_csharp\e3app\e3web\node_modules\webpack\lib\Compilation.js:4778:8
-- inner error --
ReferenceError: __webpack_modules__ is not defined
    at webpack/runtime/Aurelia expose webpack internal:1:50
    at D:\src_csharp\e3app\e3web\node_modules\webpack\lib\javascript\JavascriptModulesPlugin.js:460:11
    at Hook.eval [as call] (eval at create (D:\src_csharp\e3app\e3web\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:9:1)
    at Hook.CALL_DELEGATE [as _call] (D:\src_csharp\e3app\e3web\node_modules\tapable\lib\Hook.js:14:14)
    at D:\src_csharp\e3app\e3web\node_modules\webpack\lib\Compilation.js:4965:39
    at tryRunOrWebpackError (D:\src_csharp\e3app\e3web\node_modules\webpack\lib\HookWebpackError.js:83:7)
    at __webpack_require_module__ (D:\src_csharp\e3app\e3web\node_modules\webpack\lib\Compilation.js:4963:12)
    at D:\src_csharp\e3app\e3web\node_modules\webpack\lib\Compilation.js:4987:11
    at symbolIterator (D:\src_csharp\e3app\e3web\node_modules\neo-async\async.js:3485:9)
    at timesSync (D:\src_csharp\e3app\e3web\node_modules\neo-async\async.js:2297:7)

Generated code for webpack/runtime/Aurelia expose webpack internal
1 | __webpack_require__.m = __webpack_require__.m || __webpack_modules__;
2 | __webpack_require__.c = __webpack_require__.c || __webpack_module_cache__;
 @ ./src/main.ts 4:0-48
 @ ./node_modules/aurelia-webpack-plugin/runtime/empty-entry.js

webpack 5.61.0 compiled with 1 error in 428 ms

As suggested on Discord, I have tried

new MiniCssExtractPlugin({
        experimentalUseImportModule: false
      })

This seems to work when importing css, but ends with different error import in scss (import './styles/main.scss';).

ERROR in Conflict: Multiple assets emit different content to the same filename app.e16c2cd50df05725ea54.bundle.map

ERROR in Conflict: Multiple assets emit different content to the same filename vendors-node_modules_aurelia-testing_dist_native-modules_aurelia-testing_js-node_modules_aure-857593.e16c2cd50df05725ea54.bundle.map

webpack 5.61.0 compiled with 2 errors in 526 ms
3cp commented 2 years ago

@bigopon webpack5 is not happy about this injected line. https://github.com/aurelia/webpack-plugin/blob/2a5c95f07c1c29214001e7d5a0749a719c9b4b11/src/AureliaPlugin.ts#L362

It looks like __webpack__modules__ is not visible at that runtime moment. It's probably not a global var anymore.

3cp commented 2 years ago

I am pretty sure we don't need that AureliaExposeWebpackInternal anymore. It looks like a patch to normalise few old webpack versions, but the latest aurelia-webpack-plugin only supports webpack v5 anyway.

I tried removing it locally, it's getting better. Now I see a different error:

ERROR in Conflict: Multiple assets emit different content to the same filename app.ce168d8682b7c349aad8.bundle.map
3cp commented 2 years ago

The last conflict error can be bypassed by removing output.sourceMapFilename in the webpack config file. Not sure what went wrong here.

output: {
    path: outDir,
    publicPath: baseUrl,
    filename: production ? '[name].[chunkhash].bundle.js' : '[name].[fullhash].bundle.js',
    // sourceMapFilename: production ? '[name].[chunkhash].bundle.map' : '[name].[fullhash].bundle.map',
    chunkFilename: production ? '[name].[chunkhash].chunk.js' : '[name].[fullhash].chunk.js'
  },
bigopon commented 2 years ago

@3cp I think the "__webpack_require__.m = __webpack_require__.m || __webpack_modules__;" exposure is to make the plugin work with the loader, since the loader relies on the internal module map to work. Or are you saying that we have a way to configure webpack to output this?

3cp commented 2 years ago

From the code, I can guess that's a patch for old version of webpack when __webpack_require__.m is not available. That's why I say it's not needed anymore since we only target one version v5 now.

3cp commented 2 years ago

FYI I removed the sourceMapFilename from v1 skeleton. It's not needed anyway in webpack v5, as webpack now syncs source map filename with js filename.

3cp commented 2 years ago

@bigopon I was wrong. You have to find a way to get to the modules list.

Unhandled Promise Rejection: TypeError: undefined is not an object (evaluating '__webpack_require__.m[moduleId]')

I see, __webpack_require__.m and __webpack_require__.c are variables created by us.

3cp commented 2 years ago

I did more testing. @bigopon this is even more pressing. It's not scss or css.

The __webpack_modules__ is not visible in any context, not even in JS. So everything fails with latest webpack v5. They must have stopped expose __webpack_modules__ variable (at least to user land code). My bad, false alarm.

3cp commented 2 years ago

First clue: webpack v5.52.0 is the first version having this issue, v5.51.2 works fine.

3cp commented 2 years ago

The observation is: In webpack v5.52.0+, with combination of MiniCssExtractPlugin, in the place that our webpack-plugin injects __webpack_plugin__.m, somehow __webpack_modules__ is not visible.

Although the error log is not very clear where it happened, I am guessing the issue only happens when writing the css bundle file.

ll dist/
total 3432
-rw-r--r--  1 huocp  staff   580B  4 Nov 10:48 app.4a181df29a49a1b40e2c.bundle.css (this one I am guessing)
-rw-r--r--  1 huocp  staff   206B  4 Nov 10:48 app.4a181df29a49a1b40e2c.bundle.css.map
-rw-r--r--  1 huocp  staff   821K  4 Nov 10:48 app.4a181df29a49a1b40e2c.bundle.js
-rw-r--r--  1 huocp  staff   862K  4 Nov 10:48 app.4a181df29a49a1b40e2c.bundle.js.map
-rw-r--r--  1 huocp  staff    15K  4 Nov 10:48 favicon.ico
-rw-r--r--  1 huocp  staff   492B  4 Nov 10:48 index.html

Following fix bypasses this issue:

class AureliaExposeWebpackInternal extends Webpack.RuntimeModule {
    constructor() {
        super("Aurelia expose webpack internal");
    }
    /**
     * @returns {string} runtime code
     */
    generate() {
        return Webpack.Template.asString([
            "if (typeof __webpack_modules__ !== 'undefined') {",
            "__webpack_require__.m = __webpack_require__.m || __webpack_modules__;",
            "__webpack_require__.c = __webpack_require__.c || __webpack_module_cache__;",
            "}"
        ]);
    }
}

But better solution should be only apply AureliaExposeWebpackInternal for JS bundle files.

compiler.hooks.compilation.tap('AureliaPlugin', (compilation, params) => {
            compilation.hooks.runtimeRequirementInTree
                .for(Webpack.RuntimeGlobals.require)
                .tap('AureliaPlugin', (chunk) => {
// Somehow, ignore CSS chunk if possible.
// I could not find a signature on the chunk object to separate them.
                compilation.addRuntimeModule(chunk, new AureliaExposeWebpackInternal());
            });
        });
3cp commented 2 years ago

The info in MiniCssExtractPlugin mentioned webpack 5.52.0. Use a new webpack API to execute modules instead of child compilers might be the reason of hitting our injection code.


experimentalUseImportModule Type: Boolean Default: undefined

Enabled by default if not explicitly enabled (i.e. true and false allow you to explicitly control this option) and new API is available (at least webpack 5.52.0 is required). Boolean values are available since version 5.33.2, but you need to enable experiments.executeModule (not required from webpack 5.52.0).

Use a new webpack API to execute modules instead of child compilers. This improves performance and memory usage a lot.

ghiscoding commented 2 years ago

hey guys I get this error too after bumping mini-css and just to provide a bit more info, downgrading mini-css to an older versions fixes this issue "mini-css-extract-plugin": "~2.3.0" so there is really something different with this new version and my WebPack was upgraded to the latest which is currently at "webpack": "^5.61.0".

Also as a side note, I got another project/lib Slickgrid-Universal using latest WebPack and mini-css (same config) and I'm not having that issue on that repo, so it's really only with Aurelia that I have this issue.

pylgrym commented 2 years ago

A note here for future visitors: The issue discussed here, was apparently resolved in aurealia-webpack-plugin version 5.0.3. I ran into this issue because I was on version 5.0.0, and had a combination of the factors mentioned above (webpack5, aurelia, and mini-css-extract-plugin).

bigopon commented 2 years ago

Thanks for the discussion & resolution.