Skip to content

Karma Preprocessors

Most real projects can't serve raw source files directly — TypeScript needs compiling, modules need bundling, and coverage instrumentation needs injecting. This lesson explains how Karma's preprocessors option handles all of that.

What Preprocessors Do

A preprocessor is a plugin that transforms a file's contents after Karma matches it via files, but before it's served to the browser. The preprocessors option maps glob patterns to one or more preprocessor names, and Karma applies them in order for every matching file.

Common examples include karma-webpack (bundles modules), karma-typescript (compiles TypeScript), karma-babel-preprocessor (transpiles modern syntax), and karma-coverage (instruments code for coverage collection).

npm install --save-dev karma-webpack

// karma.conf.js
config.set({
  files: ['src/**/*.spec.js'],
  preprocessors: {
    'src/**/*.spec.js': ['webpack']
  },
  webpack: require('./webpack.test.config.js')
});

The webpack key here isn't a Karma option itself — karma-webpack reads it to know which webpack config to use for bundling.

Mapping Patterns to Preprocessors

preprocessors: {
  'src/**/*.ts': ['karma-typescript'],
  'src/**/*.spec.js': ['webpack', 'sourcemap'],
  'src/app/**/!(*.spec).js': ['coverage']
}
  • Each key is a glob pattern; each value is an array of preprocessor names, applied in listed order.
  • Coverage preprocessing is typically scoped to source files, excluding spec files, so specs aren't instrumented themselves.
  • Multiple preprocessors can chain on the same pattern (e.g. bundle, then extract source maps).
  • A preprocessor plugin must be installed and (for some) referenced under frameworks or a dedicated config key.

Common Preprocessors Cheat Sheet

The preprocessor plugin to install for common transformation needs.

Need Preprocessor Package
Bundle with webpack karma-webpack
Compile TypeScript karma-typescript
Transpile with Babel karma-babel-preprocessor
Code coverage instrumentation karma-coverage
Load and map source maps karma-sourcemap-loader
Compile CoffeeScript (legacy) karma-coffee-preprocessor

Why Preprocessor Order Matters

When chaining preprocessors on the same pattern, each one receives the output of the previous one. Bundling before extracting source maps (rather than after) is a common example of order mattering for correct debugging output.

preprocessors: {
  'src/**/*.spec.js': ['webpack', 'sourcemap']
}
// webpack bundles the file first,
// then sourcemap makes Karma aware of the resulting source map

Scoping Coverage Preprocessing Correctly

Coverage instrumentation should apply to your application source files, not your spec files — instrumenting spec files themselves produces meaningless coverage numbers and can slow down the suite for no benefit.

preprocessors: {
  'src/app/**/*.js': ['coverage']
  // note: no entry for src/app/**/*.spec.js
}

This exact scoping mistake is one of the most common Karma coverage misconfigurations.

Common Mistakes

  • Instrumenting spec files for coverage along with source files, inflating and distorting coverage reports.
  • Chaining preprocessors in the wrong order, producing broken source maps or bundling errors.
  • Forgetting to install the preprocessor plugin itself, even after correctly configuring the preprocessors map.
  • Applying a heavy preprocessor (like full webpack bundling) to files that don't actually need it, slowing down every run.

Key Takeaways

  • Preprocessors transform matched files before Karma serves them to the browser.
  • The preprocessors option maps glob patterns to an ordered array of preprocessor names.
  • Coverage preprocessing should be scoped to source files only, excluding spec files.
  • Preprocessor order matters when chaining more than one on the same file pattern.

Pro Tip

If a bundling preprocessor makes your suite noticeably slower, measure with time karma start --single-run before and after removing it experimentally. Preprocessing overhead is one of the most overlooked sources of slow Karma runs.