Mini-css-extract-plugin: Webpack 5 - TypeError: The 'compilation' argument must be an instance of Compilation

Created on 20 Oct 2020  ยท  28Comments  ยท  Source: webpack-contrib/mini-css-extract-plugin

  • Operating System: OSX Catalina 10.15.6
  • Node Version: 14.11.0
  • NPM Version: 6.14.8
  • webpack Version: 5.1.3
  • mini-css-extract-plugin Version: 1.1.1

Expected Behavior

  • No Errors when including .scss files
  • .scss files are transformed to css and output in dist directory

Actual Behavior

  • Using MiniCssExtractPlugin.loader results in webpack errors for every .scss file:
    > "TypeError: The 'compilation' argument must be an instance of Compilation"

image

  • Replacing MiniCssExtractPlugin.loader with 'style-loader' yields no errors and styles the application as intended, but css is not extracted (obviously). This leads me to suspect the issue has something to do with this plugin ๐Ÿค”

Code

Versions:

"css-loader": "5.0.0",
"html-webpack-plugin": "5.0.0-alpha.6",
"mini-css-extract-plugin": "1.1.1",
"sass-loader": "10.0.3",
"style-loader": "2.0.0",
"webpack": "5.1.3",
"webpack-cli": "4.1.0",

Results in errors:

// weback config
plugins: [
    // ...
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.(s)?css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
      },
      // ...
    ]
  }

No errors, no extract:

// webpack config
 module: {
    rules: [
      {
        test: /\.(s)?css$/i,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
      // ...
    ]
  }

Is there anything obvious from this configuration that could yield errors with the compilation argument? Has anybody seen this before? I'm working on creating a small repo to reproduce the issue, but if you see a stupid mistake in here or have clarifying questions for me, please ask right away!

Thanks very much for your help! ๐Ÿ‘

Most helpful comment

Looks like MiniExtractCssPlugin works fine as long as I don't npm link to my library. I've got symlinks: false in the resolve section of my webpack config, but it still misbehaves.

I've worked around this issue for now by changing my webpack config to use style-loader in development and MiniCssExtractPlugin in production.

To clarify: MiniCssExtractPlugin works in both development and production modes as long as I don't npm link to the library that lists MiniCssExtractPlugin as a dependency. If I run npm install and then start the app without linking, it works great. If you npm link, you get the compilation TypeErrors

All 28 comments

You have two versions of webpack, webpack@4 and webpack@5

Can you run npm ls webpack?

Hi @evilebottnawi, thanks for the quick response!

$ npm ls webpack

@blacksky/[email protected] /Users/apierce/code/work/SSO-UI
โ””โ”€โ”ฌ @blacksky/[email protected]
  โ””โ”€โ”€ [email protected]

My application inherits most of its dependencies from our "@blacksky/app" library that we use as a base for most of our webapps. webpack is listed as a dependency (rather than a devDependency) in our "app" library to ensure that all of our applications use the same version of webpack, babel, etc.

I've got a minimal library going trying to reproduce it locally, but so far it imports scss files just fine. Could it have something to do with the fact that we're deriving our dependencies from a child library?

The other thing worth mentioning is that I have an npm run clean script that does the following:

touch node_modules package-lock.json && rm -rf node_modules package-lock.json && npm install

... so I doubt I've got any kind of weird caching going on ๐Ÿค”

A clue!!

When I npm i -DE mini-css-extract-plugin in our application (rather than inherit it from our library), it works fine.

Something about the fact that it's a dependency of another dependency causes it to misbehave... ๐Ÿค”

I've got a minimal library going trying to reproduce it locally, but so far it imports scss files just fine. Could it have something to do with the fact that we're deriving our dependencies from a child library?

Yes, maybe you can provide link, will be great to look at structure

Looks like MiniExtractCssPlugin works fine as long as I don't npm link to my library. I've got symlinks: false in the resolve section of my webpack config, but it still misbehaves.

I've worked around this issue for now by changing my webpack config to use style-loader in development and MiniCssExtractPlugin in production.

To clarify: MiniCssExtractPlugin works in both development and production modes as long as I don't npm link to the library that lists MiniCssExtractPlugin as a dependency. If I run npm install and then start the app without linking, it works great. If you npm link, you get the compilation TypeErrors

I get same error, how to resolve

I'm getting the same error. The object is an instance of _a_ Compilation. It's just not an instance of _the_ Compilation. Two different copies of the Compilation class are loaded, and even if the code is identical, JS sees two different objects. I ran into a similar problem with LitElement's TemplateResult class recently, which is described here:

https://stackoverflow.com/a/63576099/437

I don't have a solution yet, but hopefully this helps.

I've got a minimal library going trying to reproduce it locally, but so far it imports scss files just fine. Could it have something to do with the fact that we're deriving our dependencies from a child library?

Yes, maybe you can provide link, will be great to look at structure

@alexander-akait I am running into the same issue. Are you still looking for a reproduction? I might be able to get something going if you need it still.

Yep, let's do it and I will look at this

Yep, let's do it and I will look at this

There you go: https://github.com/Christian24/mini-css-extract-linking-issue

As always: if you need more info, let me know.

If you disable html-webpack-plugin all works fine?

No, the issue remains the same.

Yep, here interesting limitation/problem, when you use monorepos and have webpack in root package.json and inside some package, you will have multiple webpack (in node_modules and packages/admin/node_modules and packages/login/node_modules), so instanceof will not work

Remove webpack from package.json for packages/admin and packages/logic and test it - all works fine

Yeah, I have had this issue with multiple plugins already. Most of the time I got it fixed by using the same versions of webpack/webpack-cli.

Interestingly, in webpack@4 this worked fine.

Sadly, we are using Git Submodules (imagine login folder in my example would be its own repository), we check it out in during continous integration (like Jenkins).

So, we need both both webpack dependencies, both in the root repository and in the submodule.

There is not webpack problems/bugs, this is how instanceof works

More simple, when you have new MiniCssExtractPlugin({filename: "[name].[contenthash].css"})), in packages/config it will use webpack from node_modules, but when you run npm run build it will use webpack from packages/logic, because you create different Compilations instanceof will not work

You can solve it using --hoist - "postinstall": "lerna bootstrap --hoist", for root package.json https://github.com/lerna/lerna/blob/main/doc/hoist.md

I understand.

A few things come to my mind right now:

  • How is sharing configurations in webpack intended? Is it generally discouraged to share configuration/plugins? What I have done from my point of view is relatively nice, since I only need mini-css-extract-plugin once as a dependency in config.
  • This did not happen in webpack@4. What motivated this change? Maybe there is a different way to do this? Or make the error more clear.
  • I do not think hoisting would solve my problem, since it would alter package.json in both login and admin. This is not something we would want, since we would still want to run login and admin independently on CI without checking out the root.
  • I am more wondering if we could remove the webpack dependency from the root and somehow make it use the one in login for example. Or just putting the root into its own folder, next to login and admin.
  • Or maybe remove the instance creation of mini-css-extract-plugin from config to login and admin.
  • Why is this only happening for some plugins?

Some of the approaches will work, hard to say what is better, because it depends what you need, many developers uses --hoist and it is good for them, but not in your case (as you say).

I am more wondering if we could remove the webpack dependency from the root and somehow make it use the one in login for example. Or just putting the root into its own folder, next to login and admin.

Yes too, you can create helper function like createWebpackConfig and export it from packages/config

Or maybe remove the instance creation of mini-css-extract-plugin from config to login and admin.

Will work

Why is this only happening for some plugins?

Because some plugins require Compilation instance, some of them not

First of all, thanks a lot for the explanation.

Yes too, you can create helper function like createWebpackConfig and export it from packages/config

I am not exactly sure I understand what you mean here. Would you have something similar to
js module.exports = function() { return [loginConfig, adminConfig] }
in packages/config?

I would very much apreciate if the error message specifically mention having multiple instances of webpack, since it seems lots of people run into this issue on all sorts of plugins.

You mean you need to require mini-css-extract-plugin inside packages/logic/webpack.config.js, so packages/config can export utils addCSS/addHTML and etc, where you will require it and modify configuration

I would very much apreciate if the error message specifically mention having multiple instances of webpack, since it seems lots of people run into this issue on all sorts of plugins.

Already talking about it

@Christian24 found solution, how we can solve it, so just wait the next patch release

Cool :)

https://github.com/webpack-contrib/mini-css-extract-plugin/pull/698/, still WIP, it is not easy, hope I will finish it today/tomorrow

Don't worry. I have to focus on other stuff at the moment anyway, so it will probably be a couple days or weeks until I get back to this.

Fixed, release will be today, should fix all problems with compatibility

Hello everybody!

Still have this issue when using Webpack 5 and Next.js.

My package.json deps section:

"dependencies": {
    "@babel/core": "^7.13.0",
    "@googlemaps/markerclustererplus": "^1.0.3",
    "@next/bundle-analyzer": "^9.4.4",
    "@types/dotenv": "^6.1.1",
    "@types/googlemaps": "^3.43.2",
    "@types/lodash.throttle": "^4.1.6",
    "@types/nock": "^10.0.3",
    "@types/node": "^14.0.0",
    "@types/react": "^17.0.0",
    "@types/react-modal": "^3.12.0",
    "@types/react-redux": "^7.0.0",
    "animejs": "^3.2.1",
    "autoprefixer": "^9.6.1",
    "babel-loader": "^8.2.2",
    "babel-plugin-module-resolver": "4.1.0",
    "babel-plugin-transform-define": "^2.0.0",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "babel-preset-react-app": "^10.0.0",
    "clsx": "^1.1.1",
    "cross-env": "^5.2.1",
    "css-loader": "^5.2.0",
    "dotenv": "^8.1.0",
    "eslint": "^7.19.0",
    "file-loader": "6.2.0",
    "isomorphic-unfetch": "^3.0.0",
    "lodash.throttle": "^4.1.1",
    "mini-css-extract-plugin": "^1.4.x",
    "next": "^10.1.0",
    "next-compose-plugins": "^2.2.0",
    "next-images": "^1.7.0",
    "next-seo": "^4.19.0",
    "query-string": "^6.13.8",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-modal": "^3.12.1",
    "react-redux": "^7.2.3",
    "redux": "^4.0.5",
    "redux-devtools-extension": "^2.13.8",
    "redux-thunk": "^2.3.0",
    "sass": "^1.32.x",
    "sass-loader": "^10.0.0",
    "style-loader": "^2.0.0",
    "svg-sprite-loader": "^6.x.x",
    "swiper": "^6.4.10",
    "ts-loader": "^8.0.15",
    "ts-node": "^9.1.1",
    "typescript": "^4.2.0",
    "webpack": "^5.x.x"
},

Webpack config that causes this error:

config.module.rules.push({
    test: new RegExp(`\\.+(scss|sass)$`),
    use: [
        (dev && !isServer) && 'style-loader',
        !dev && {
            loader: MiniCssExtractPlugin.loader,
            options: {
                publicPath: path.resolve(__dirname, 'public/static/css'),
            },
        },
        { loader: 'css-loader', options: { sourceMap: dev }, },
        {
            loader: 'sass-loader',
            options: {
                sassOptions: {
                    includePaths: [
                        path.resolve(__dirname, 'public/static/css'),
                        path.resolve(__dirname, 'src'),
                        path.resolve(__dirname, 'pages')
                    ]
                },
                sourceMap: dev,
            }
        },
    ].filter(Boolean)
});

I cannot remove the webpack from the dependencies - after that, both next build and nodemon (npm run dev runs it for us) stop working for me.

If I install the 4th webpack everything works fine, but we have a goal to update the webpack... but because of this error, the mini-css-extract-plugin prevents us from doing this ...

Was this page helpful?
0 / 5 - 0 ratings