webpack-contrib / mini-css-extract-plugin

Lightweight CSS extraction plugin
MIT License
4.65k stars 390 forks source link

Webpack 5 - TypeError: The 'compilation' argument must be an instance of Compilation #631

Closed owap closed 3 years ago

owap commented 3 years ago

Expected Behavior

Actual Behavior

image

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! 👍

alexander-akait commented 3 years ago

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

alexander-akait commented 3 years ago

Can you run npm ls webpack?

owap commented 3 years ago

Hi @evilebottnawi, thanks for the quick response!

$ npm ls webpack

@blacksky/sso-ui@10.0.11 /Users/apierce/code/work/SSO-UI
└─┬ @blacksky/app@15.0.0-webpack9
  └── webpack@5.1.3

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 🤔

owap commented 3 years ago

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... 🤔

alexander-akait commented 3 years ago

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

owap commented 3 years ago

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

zy0228 commented 3 years ago

I get same error, how to resolve

pmcelhaney commented 3 years ago

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.

Christian24 commented 3 years ago

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.

alexander-akait commented 3 years ago

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

Christian24 commented 3 years ago

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.

alexander-akait commented 3 years ago

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

Christian24 commented 3 years ago

No, the issue remains the same.

alexander-akait commented 3 years ago

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

alexander-akait commented 3 years ago

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

Christian24 commented 3 years ago

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.

alexander-akait commented 3 years ago

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

alexander-akait commented 3 years ago

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

Christian24 commented 3 years ago

I understand.

A few things come to my mind right now:

alexander-akait commented 3 years ago

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

Christian24 commented 3 years ago

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

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.

alexander-akait commented 3 years ago

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

alexander-akait commented 3 years ago

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

Christian24 commented 3 years ago

Cool :)

alexander-akait commented 3 years ago

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

Christian24 commented 3 years ago

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.

alexander-akait commented 3 years ago

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

Psychosynthesis commented 3 years ago

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 ...