Mini-css-extract-plugin: Misleading error, when used with `html-webpack-plugin`

Created on 3 Jan 2020  ·  37Comments  ·  Source: webpack-contrib/mini-css-extract-plugin

Error thrown that lead to something meaningful (still not sure what actually goes wrong)

Actual Behavior

Thrown the error in some third-party lib

% npm run build -- --mode development

> [email protected] build /Users/user/foo
> webpack "--mode" "development"

/Users/user/foo/node_modules/neo-async/async.js:16
    throw new Error('Callback was already called.');
    ^

Error: Callback was already called.
    at throwError (/Users/user/foo/node_modules/neo-async/async.js:16:11)
    at /Users/user/foo/node_modules/neo-async/async.js:2818:7
    at process._tickCallback (internal/process/next_tick.js:61:11)

Code

https://gist.github.com/ogonkov/2e23941414d6f0b3d5328bd80cba5674

How Do We Reproduce?

  1. Checkout gist above
  2. npm i
  3. npm run build

Most helpful comment

CSS-related issues in html-webpack-plugin:

it's probably mini-css-extract-plugin issue

Issues in mini-css-extract-plugin:

it's probably html-webpack-plugin issue

All 37 comments

Looks like problem in HTMLWebpackPlugin

Without MCEP loader it works correctly, but didn't emit CSS chunk

@evilebottnawi should this config actually work? Or MCEP is not intended to emit CSS chunks together with HWP?

@ogonkov i think something wrong in HWP, i will look at this in near future

Should i add this MCEP+HWP usage to tests?

CSS-related issues in html-webpack-plugin:

it's probably mini-css-extract-plugin issue

Issues in mini-css-extract-plugin:

it's probably html-webpack-plugin issue

I believe that importing same template from JS didn't throw error, so probably @evilebottnawi could be right here (still don't know how to debug this issue, to make sure).

At [email protected] error is different:


Console output

% npm run build

> example@ build /Users/user/Projects/example
> webpack

Hash: 0b6c02dcf3c69eca1876
Version: webpack 4.41.5
Time: 633ms
Built at: 01/10/2020 8:55:50 AM
 2 assets
Entrypoint main = main.js
[0] ./src/index.js 35 bytes {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

ERROR in   Error: Child compilation failed:
  Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
  TypeError: this[MODULE_TYPE] is not a function

  - loader.js:170 childCompiler.runAsChild
    [isomorphic-example]/[mini-css-extract-plugin]/dist/loader.js:170:24

  - Compiler.js:343 compile
    [isomorphic-example]/[webpack]/lib/Compiler.js:343:11

  - Compiler.js:681 hooks.afterCompile.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compiler.js:681:15


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compiler.js:678 compilation.seal.err
    [isomorphic-example]/[webpack]/lib/Compiler.js:678:31


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1423 hooks.optimizeAssets.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1423:35


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1414 hooks.optimizeChunkAssets.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1414:32


  - index.js:321 taskRunner.run
    [isomorphic-example]/[terser-webpack-plugin]/dist/index.js:321:9

  - TaskRunner.js:48 TaskRunner.run
    [isomorphic-example]/[terser-webpack-plugin]/dist/TaskRunner.js:48:7

  - index.js:227 TerserPlugin.optimizeFn
    [isomorphic-example]/[terser-webpack-plugin]/dist/index.js:227:18


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1409 hooks.additionalAssets.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1409:36


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1405 hooks.optimizeTree.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1405:32


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1342 Compilation.seal
    [isomorphic-example]/[webpack]/lib/Compilation.js:1342:27

  - Compiler.js:675 compilation.finish.err
    [isomorphic-example]/[webpack]/lib/Compiler.js:675:18

  - Compilation.js:1261 hooks.finishModules.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1261:4


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1253 Compilation.finish
    [isomorphic-example]/[webpack]/lib/Compilation.js:1253:28

  - Compiler.js:672 hooks.make.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compiler.js:672:17


  - Compilation.js:1185 _addModuleChain
    [isomorphic-example]/[webpack]/lib/Compilation.js:1185:12

  - Compilation.js:1097 processModuleDependencies.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1097:9


  - TypeError: this[MODULE_TYPE] is not a function

  - compiler.js:79 childCompiler.runAsChild
    [isomorphic-example]/[html-webpack-plugin]/lib/compiler.js:79:16

  - Compiler.js:343 compile
    [isomorphic-example]/[webpack]/lib/Compiler.js:343:11

  - Compiler.js:681 hooks.afterCompile.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compiler.js:681:15


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compiler.js:678 compilation.seal.err
    [isomorphic-example]/[webpack]/lib/Compiler.js:678:31


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1423 hooks.optimizeAssets.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1423:35


  - Hook.js:154 AsyncSeriesHook.lazyCompileHook
    [isomorphic-example]/[tapable]/lib/Hook.js:154:20

  - Compilation.js:1414 hooks.optimizeChunkAssets.callAsync.err
    [isomorphic-example]/[webpack]/lib/Compilation.js:1414:32


  - index.js:321 taskRunner.run
    [isomorphic-example]/[terser-webpack-plugin]/dist/index.js:321:9

  - TaskRunner.js:48 TaskRunner.run
    [isomorphic-example]/[terser-webpack-plugin]/dist/TaskRunner.js:48:7


Child html-webpack-plugin for "index.html":
     1 asset
    Entrypoint undefined = index.html
    [0] ./node_modules/html-webpack-plugin/lib/loader.js!./index.ejs 282 bytes {0} [built]
    [2] (webpack)/buildin/global.js 472 bytes {0} [built]
    [3] (webpack)/buildin/module.js 497 bytes {0} [built]
    [4] ./item.css 4.76 KiB {0} [built] [failed] [1 error]
        + 1 hidden module

    ERROR in ./item.css
    Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
    TypeError: this[MODULE_TYPE] is not a function
        at childCompiler.runAsChild (/Users/user/Projects/example/node_modules/mini-css-extract-plugin/dist/loader.js:170:24)
        at compile (/Users/user/Projects/example/node_modules/webpack/lib/Compiler.js:343:11)
        at hooks.afterCompile.callAsync.err (/Users/user/Projects/example/node_modules/webpack/lib/Compiler.js:681:15)
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
        at AsyncSeriesHook.lazyCompileHook (/Users/user/Projects/example/node_modules/tapable/lib/Hook.js:154:20)
        at compilation.seal.err (/Users/user/Projects/example/node_modules/webpack/lib/Compiler.js:678:31)
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
        at AsyncSeriesHook.lazyCompileHook (/Users/user/Projects/example/node_modules/tapable/lib/Hook.js:154:20)
        at hooks.optimizeAssets.callAsync.err (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1423:35)
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
        at AsyncSeriesHook.lazyCompileHook (/Users/user/Projects/example/node_modules/tapable/lib/Hook.js:154:20)
        at hooks.optimizeChunkAssets.callAsync.err (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1414:32)
        at _err0 (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
        at taskRunner.run (/Users/user/Projects/example/node_modules/terser-webpack-plugin/dist/index.js:321:9)
        at TaskRunner.run (/Users/user/Projects/example/node_modules/terser-webpack-plugin/dist/TaskRunner.js:48:7)
        at TerserPlugin.optimizeFn (/Users/user/Projects/example/node_modules/terser-webpack-plugin/dist/index.js:227:18)
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:7:1)
        at AsyncSeriesHook.lazyCompileHook (/Users/user/Projects/example/node_modules/tapable/lib/Hook.js:154:20)
        at hooks.additionalAssets.callAsync.err (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1409:36)
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
        at AsyncSeriesHook.lazyCompileHook (/Users/user/Projects/example/node_modules/tapable/lib/Hook.js:154:20)
        at hooks.optimizeTree.callAsync.err (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1405:32)
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
        at AsyncSeriesHook.lazyCompileHook (/Users/user/Projects/example/node_modules/tapable/lib/Hook.js:154:20)
        at Compilation.seal (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1342:27)
        at compilation.finish.err (/Users/user/Projects/example/node_modules/webpack/lib/Compiler.js:675:18)
        at hooks.finishModules.callAsync.err (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1261:4)
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:24:1)
        at AsyncSeriesHook.lazyCompileHook (/Users/user/Projects/example/node_modules/tapable/lib/Hook.js:154:20)
        at Compilation.finish (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1253:28)
        at hooks.make.callAsync.err (/Users/user/Projects/example/node_modules/webpack/lib/Compiler.js:672:17)
        at _err0 (eval at create (/Users/user/Projects/example/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
        at _addModuleChain (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1185:12)
        at processModuleDependencies.err (/Users/user/Projects/example/node_modules/webpack/lib/Compilation.js:1097:9)
        at process._tickCallback (internal/process/next_tick.js:61:11)
     @ ./index.ejs (./node_modules/html-webpack-plugin/lib/loader.js!./index.ejs) 4:10-31
    Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js??ref--4-1!item.css:
        Entrypoint mini-css-extract-plugin = *
        [0] ./node_modules/css-loader/dist/cjs.js??ref--4-1!./item.css 67 bytes {0} [built]
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! example@ build: `webpack`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the example@ build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/user/.npm/_logs/2020-01-10T05_55_50_213Z-debug.log

Looks like problem mutated?

I believe bug (with misleading error) was introduced in #448

I believe that error thrown from webpack/lib/Compilation

https://github.com/webpack/webpack/blob/45ecebc9f0486c43efc7b56f2c31426d94a55264/lib/Compilation.js#L849

Callback is first called in catch on line 829, then in addModuleDependencies it called again around https://github.com/webpack/webpack/blob/45ecebc9f0486c43efc7b56f2c31426d94a55264/lib/Compilation.js#L1020

If i put console log on 1020 it shows that css file come here twice.

Second invocation is seems to come from loader child compiler callback invocation (redundant?)

@evilebottnawi did you have a chance to look to this issue?

I ended up just moving all my <link href="..."> references to the entry js file as import '...';s, since this plugin does not seem to work with html without Callback was already called error even on a plain minimal test case for me. Even though docs are implying that it is supposed to...

Try to find time in near future, a lot of work, sorry

If this helps, I created one more minimal test case:
https://github.com/klesun-misc/mcep_issue_489
(this one without ejs, just plain html)

Hit that issue as well, cost me a few hours already :-( Thanks @ogonkov for reporting with reproducer.

@klesun a viable workaround (works for me) might be to replace MiniCssExtractPlugin by a simple file-loader :

      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'file-loader',
            options: {
              esModule: false,
            },
          },
          'extract-loader',
          {
            loader: 'css-loader',
            options: {
              esModule: false,
            },
          }
        ],
      },

If you also have regular JS imports then of course 2 distinct CSS rules are required.

UPDATE: just found that stackoverflow entry... ;-) Hopefully still useful to have the workaround detailed here.

@geonanorch Though, as I found later, extract-loader has unresolved bugs too sadly...

@ogonkov sorry for delay, a lot of work, can you send a PR?

@evilebottnawi I have no idea how to fix it. May be you can give some hint to what is going wrong?

no problems on webpack@5 :confused:

Yep, bug on html-webpack-plugin https://github.com/jantimon/html-webpack-plugin/blob/master/lib/child-compiler.js#L105

need to change on

new SingleEntryPlugin(childCompiler.context, `!!${template}`, `HtmlWebpackPlugin_${index}`).apply(childCompiler);

/cc @jantimon Why we don't use !!? Without it webpack run nested child compilation again, you can see what we use !! here too to avoid it https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/src/loader.js#L101

With !! we would not able to make use of configured loaders..

See the "Template language support" section of https://dev.to/jantimon/html-webpack-plugin-4-has-been-released-125d

I have filed another bug in html-webpack-plugin repo. I hope we can find solution.

@jantimon something wrong in design html-webpack-plugin, it should use !! and pitch loader to modify something from webpack, otherwise you create recursive child compilations

But we will probably need child compilations for ssr.

Isn't !! only to exclude loaders?

@jantimon

But we will probably need child compilations for ssr.

pitch phase do not break SSR

Isn't !! only to exclude loaders?

Yes, it is exclude pre loader and normal loader, but because you will use pitch it will run loader anyway because you will pass them in a string require/import, you can look how mini-css-extract-plugin work

@evilebottnawi, I think this is still a problem of MCEP. Simply say, MCEP do not support child compilation.

HWP use child compilation to parse html and its dependencies, and MCEP didn't add the CssDependency (& factory) to childCompilation.dependencyFactories. Of course, when a html has a css dependency, then the problem.

Maybe, change the hook of thisCompilation to compilation will solve this, mini-css-extract-plugin/src/index.js#L63.

If child compilation exists, should not MCEP support it?

@zhenhen yes, but in theory other nested child compilations can be used, there are problem in html-webpack-plugin and invalid architecture in some places, but I think we solve it in the future

@evilebottnawi, I think this is still a problem of MCEP. Simply say, MCEP do not support _child compilation_.

HWP use child compilation to parse html and its dependencies, and MCEP didn't add the CssDependency (& factory) to childCompilation.dependencyFactories. Of course, when a html has a css dependency, then the problem.

Maybe, change the hook of thisCompilation to compilation will solve this, mini-css-extract-plugin/src/index.js#L63.

If _child compilation_ exists, should not MCEP support it?

I can confirm that changing thisCompilation to compilation fixed the error when compiling svelte generated css from 2 different entry points. I'm not using html-webpack-plugin.

As a dirty hack I'm using apply-patch to modify the dist code to do this automatically

@IgnusG can you provide minimum reproducible test repo?

I’ll try and reduce the build code and create a playground repo. Will probably take me some time

Unfortunately spoke too soon. Changing the hook indeed fixes the compilation and all files are properly emitted but the identifier inside the requiring file gets changed from the original .js file (which generates the css) into a .css file instead (the emitted file) 😔

I've narrowed the problem down to spawn-loader creating new "entry chunks" dynamically. The wrong css name reference was because it uses the first file name - compilation ... value.chunks[0].files[0] as the result.

I've modified this behaviour to always use the last one (excluding source maps) - honestly have no idea what implications that has - but now (together with changing thisCompilation to compilation in MCEP) the file names are correct and the compilation succeeds.

I assume spawn-loader is causing the same error in MCEP as html-webpack-plugin does - not sure why changing thisCompilation to compilation works though

When I use style-loader I get "ReferenceError: document is not defined".
When I use MiniCssExtractPlugin I get "Error: Callback was already called.

With all the latest packages installed this error is not appear anymore. But CSS is not emitted either. I think i will recreate this issue, because original error is gone.

Was this page helpful?
0 / 5 - 0 ratings