Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue-loader was used without the corresponding plugin and You forgot to add 'mini-css-extract-plugin' plugin problem #184

Closed
869288142 opened this issue Dec 25, 2021 · 1 comment

Comments

@869288142
Copy link

869288142 commented Dec 25, 2021

Webpack 5 fails as soon as I smp.wrap() my config, with the following error:

vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config

ERROR in ..../Error.scss
Module build failed (from ../../node_modules/mini-css-extract-plugin/dist/loader.js):
Error: You forgot to add 'mini-css-extract-plugin' plugin (i.e. `{ plugins: [new MiniCssExtractPlugin()] }`), please read https://github.com/webpack-contrib/mini-css-extract-plugin#getting-started
    at Object.pitch (.../node_modules/mini-css-extract-plugin/dist/loader.js:50:14)

webpack.config.js

const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const { VueLoaderPlugin } = require("vue-loader");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = smp.wrap({
  mode: "development",
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      {
        test: /\.vue$/,
        loader: "vue-loader",
      },
    ],
  },

  plugins: [new VueLoaderPlugin(), new MiniCssExtractPlugin()],
});

package.json

  "devDependencies": {
    "css-loader": "^6.5.1",
    "mini-css-extract-plugin": "^2.4.5",
    "speed-measure-webpack-plugin": "^1.5.0",
    "vue-loader": "^15.9.8",
    "vue-template-compiler": "^2.6.14",
    "webpack": "5.65.0",
    "webpack-cli": "^4.9.1"
  },

problem

webpack5 now use NormalModule.getCompilationHooks(compilation).loader instead of Compilation.hooks.normalModuleLoader, so speed-measure-webpack-plugin can not proxy it.

vue-loader

 compiler.hooks.compilation.tap(id, compilation => {
      const normalModuleLoader = normalModule.getCompilationHooks(compilation).loader
      normalModuleLoader.tap(id, loaderContext => {
        loaderContext[NS] = true
      })
    })

mini-css-extract-plugin

    compiler.hooks.compilation.tap(pluginName, compilation => {
      const {
        loader: normalModuleHook
      } = NormalModule.getCompilationHooks(compilation);
      normalModuleHook.tap(pluginName, loaderContext => {
        // eslint-disable-next-line no-param-reassign
        loaderContext[pluginSymbol] = {
          experimentalUseImportModule: this.options.experimentalUseImportModule
        };
      });

NormalModule.getCompilationHooks(compilation)

       const compilationHooksMap = new WeakMap();
	static getCompilationHooks(compilation) {
		if (!(compilation instanceof Compilation)) {
			throw new TypeError(
				"The 'compilation' argument must be an instance of Compilation"
			);
		}
		let hooks = compilationHooksMap.get(compilation);
		if (hooks === undefined) {
			hooks = {
				loader: new SyncHook(["loaderContext", "module"]),
				beforeLoaders: new SyncHook(["loaders", "module", "loaderContext"]),
				beforeParse: new SyncHook(["module"]),
				beforeSnapshot: new SyncHook(["module"]),
				// TODO webpack 6 deprecate
				readResourceForScheme: new HookMap(scheme => {
					const hook = hooks.readResource.for(scheme);
					return createFakeHook(
						/** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer>} */ ({
							tap: (options, fn) =>
								hook.tap(options, loaderContext =>
									fn(loaderContext.resource, loaderContext._module)
								),
							tapAsync: (options, fn) =>
								hook.tapAsync(options, (loaderContext, callback) =>
									fn(loaderContext.resource, loaderContext._module, callback)
								),
							tapPromise: (options, fn) =>
								hook.tapPromise(options, loaderContext =>
									fn(loaderContext.resource, loaderContext._module)
								)
						})
					);
				}),
				readResource: new HookMap(
					() => new AsyncSeriesBailHook(["loaderContext"])
				),
				needBuild: new AsyncSeriesBailHook(["module", "context"])
			};
			compilationHooksMap.set(compilation, hooks);
		}
		return hooks;
	}

when call NormalModule.getCompilationHooks(compilation) in vue-loader or mini-css-extract-plugin, smp.wrap pass proxy
compilation param, it be assign to compilationHooksMap, but webpack inner compilation is not proxy compilation , so cause that NormalModule.getCompilationHooks(compilation) is not execute

solution

so far ,i have not idea to fix this plugin. but you can modify vue-loader or mini-css-extract-plugin in node_modules

vue-loader

 compiler.hooks.compilation.tap(id, compilation => {
     compilation .hooks.normalModuleLoader.tap(id, , loaderContext => {
        loaderContext[NS] = true
      })
    })

mini-css-extract-plugin

    compiler.hooks.compilation.tap(pluginName, compilation => {
     compilation .hooks.normalModuleLoader.tap(pluginName, , loaderContext => {
          loaderContext[pluginSymbol] = {
          experimentalUseImportModule: this.options.experimentalUseImportModule
        };
      })
    })
@ryan-sherpa
Copy link

Same issue here. Thanks for reporting so thoroughly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants