karma-webpack icon indicating copy to clipboard operation
karma-webpack copied to clipboard

Webpack multicompiler support is broken as of karma-webpack@^5.0.0

Open meyer opened this issue 3 years ago • 2 comments

  • Operating System: macOS 11
  • Node Version: 12
  • NPM Version: yarn 1
  • webpack Version: 5
  • karma-webpack Version: 5

Expected Behavior

webpackOptions can (continue to) be an array of webpack configs.

Actual Behavior

I get this error:

WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration has an unknown property '1'. These properties are valid:
   object { amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry?, externals?, infrastructureLogging?, loader?, mode?, module?, name?, node?, optimization?, output?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, recordsOutputPath?, recordsPath?, resolve?, resolveLoader?, serve?, stats?, target?, watch?, watchOptions? }

I suspect a webpack-merge-type operation is turning my array of configs into an object with numbers as keys.

Here’s how v4 managed multiconfigs: https://github.com/ryanclark/karma-webpack/blob/48878eb/src/karma-webpack.js#L64-L69

How Do We Reproduce?

Provide an array of configs as the webpack option in your karma config file.

meyer avatar Jun 22 '21 01:06 meyer

Thanks for opening an issue, would you be interested in working on a test case or fix for this? I can assist you in getting that merged and into a release.

codymikol avatar Jun 22 '21 13:06 codymikol

If I get a sec this week I’ll give it a go. I’m currently evaluating karma replacements at the moment though, so this may end up falling through the cracks.

meyer avatar Jun 28 '21 03:06 meyer

I made a few changes to my fork, to support multiple webpack configs, and i also made changes to allow custom entry points alongside custom output filenames.

i've avoided merging webpack config by passing two configs in an array, one for the 'test' side and one for the 'app' side, i've also added a testWebpack field, to allow to customize the webpack test config, which can allow for example to pass some module.rules that are not needed on the app side.

So in the end, what is passed to webpack field in the karma config, will be forwarded to webpack as is, without any merging, and removing of fields, like output.filename, entry

if it's something you want to do here, i could make PR's for those

see : https://github.com/lk77/karma-webpack/blob/master/lib/karma-webpack/controller.js

class KW_Controller {
  constructor() {
    this.isActive = false;
    this.bundlesContent = {};
    this.hasBeenBuiltAtLeastOnce = false;
    // two separates config, one for tests, the other for the app
    this.testWebpackOptions = DefaultWebpackOptionsFactory.create();
    this.appWebpackOptions = {};
    this.webpackOptions = [];
  }

  updateTestWebpackOptions(newOptions) {
    // for updating the test config
    this.testWebpackOptions = merge(this.testWebpackOptions, newOptions);
  }

  updateAppWebpackOptions(newOptions) {
    // for updating the app config
    if (Array.isArray(newOptions)) {
      // it supports array
      this.appWebpackOptions = newOptions.map((newOption, index) =>
        merge(this.appWebpackOptions[index], newOption)
      );
    } else {
      // it also support object
      this.appWebpackOptions = merge(this.appWebpackOptions, newOptions);
    }
  }

  // at the end we generate an array of webpack configs that will be provided to webpack
  computeWebpackOptions() {
    if (Array.isArray(this.appWebpackOptions)) {
      // if we have an array we concat it with our test config
      this.webpackOptions = [this.testWebpackOptions].concat(
        this.appWebpackOptions
      );
    } else {
      // we make an array of our test config and our app config
      this.webpackOptions = [this.testWebpackOptions, this.appWebpackOptions];
    }
  }
[...]
}

and see https://github.com/lk77/karma-webpack/blob/master/lib/karma-webpack/preprocessor.js

function KW_Preprocessor(config, emitter) {
  const controller = new KW_Controller();
  config.__karmaWebpackController = controller;
  ensureWebpackFrameworkSet(config);

  // one time setup
  if (controller.isActive === false) {
    // we set our test config with our entry
    controller.updateTestWebpackOptions({
      entry: configToWebpackEntries(config),
      watch: config.autoWatch,
    });

    // we allow end users to override it
    controller.updateTestWebpackOptions(config.testWebpack);
    // we set the app config of the user
    controller.updateAppWebpackOptions(config.webpack);
    controller.karmaEmitter = emitter;

    // We merge everything into an array of configs before processing it
    controller.computeWebpackOptions();
  }
[...]
}

lk77 avatar Dec 07 '22 16:12 lk77

As karma is now deprecated and coming up on EOL, we are no longer planning on any significant enhancements to this project and are instead going to focus on security updates, stability, and a migration path forward as karma's lifecycle comes to an end.

Thank you for supporting and using this project!

codymikol avatar Oct 22 '23 01:10 codymikol