codymikol / karma-webpack

Karma webpack Middleware
MIT License
830 stars 221 forks source link

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

Closed meyer closed 10 months ago

meyer commented 3 years ago

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.

codymikol commented 3 years ago

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.

meyer commented 3 years ago

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.

lk77 commented 1 year ago

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();
  }
[...]
}
codymikol commented 10 months ago

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!