Skip to content

Commit

Permalink
refactor(karma-webpack): upgrade plugin system (tapable)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: requires `webpack >= v4.0.0`
  • Loading branch information
ryanclark authored and michael-ciniawsky committed Mar 19, 2018
1 parent 1ac16ea commit 395eab4
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 47 deletions.
130 changes: 104 additions & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -5,7 +5,7 @@
"description": "Use webpack with karma",
"license": "MIT",
"engines": {
"node": ">= 4"
"node": ">=6.11.5"
},
"main": "lib",
"files": [
Expand Down Expand Up @@ -33,7 +33,7 @@
"loader-utils": "^1.0.0",
"lodash": "^4.0.0",
"source-map": "^0.5.6",
"webpack-dev-middleware": "^2.0.6"
"webpack-dev-middleware": "^3.0.1"
},
"devDependencies": {
"babel-cli": "^6.0.0",
Expand All @@ -55,7 +55,7 @@
"karma-spec-reporter": "^0.0.32",
"mocha": "^4.0.0",
"standard-version": "^4.0.0",
"webpack": "^4.0.0"
"webpack": "^4.1.1"
},
"bugs": "https://github.com/webpack-contrib/karma-webpack/issues",
"repository": "https://github.com/webpack-contrib/karma-webpack.git",
Expand Down
87 changes: 69 additions & 18 deletions src/karma-webpack.js
Expand Up @@ -20,6 +20,14 @@ var escapeRegExp = function(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&')
}

function invalidate(middleware) {
if (middleware.context.watching) {
return middleware.context.watching.invalidate()
}

return middleware.invalidate()
}

function Plugin(
/* config.webpack */ webpackOptions,
/* config.webpackServer */ webpackServerOptions,
Expand Down Expand Up @@ -75,6 +83,7 @@ function Plugin(
this.files = []
this.basePath = basePath
this.waiting = []
this.plugin = {name: 'KarmaWebpack'}

var compiler

Expand All @@ -91,23 +100,56 @@ function Plugin(
var applyPlugins = compiler.compilers || [compiler]

applyPlugins.forEach(function(compiler) {
compiler.plugin('this-compilation', function(compilation, params) {
compilation.dependencyFactories.set(SingleEntryDependency, params.normalModuleFactory)
})
compiler.plugin('make', this.make.bind(this))
}, this);
if (compiler.hooks) {
compiler.hooks
.thisCompilation
.tap(this.plugin, (compilation, params) => {
compilation.dependencyFactories.set(SingleEntryDependency, params.normalModuleFactory)
})
compiler.hooks
.make
.tapAsync(this.plugin, this.make.bind(this))
} else {
compiler.plugin('this-compilation', function(compilation, params) {
compilation.dependencyFactories.set(SingleEntryDependency, params.normalModuleFactory)
})
compiler.plugin('make', this.make.bind(this))
}
}, this)

function handler(callback) {
isBlocked = true

if (typeof callback === 'function') {
callback(null)
}
}

['invalid', 'watch-run', 'run'].forEach(function(name) {
compiler.plugin(name, function(_, callback) {
isBlocked = true
var hooks = ['invalid', 'watch-run', 'run']

if (typeof callback === 'function') {
callback()
if (compiler.hooks) {
hooks = [
{method: 'sync', name: 'invalid'},
{method: 'async', name: 'watchRun'},
{method: 'async', name: 'run'}
]
}

hooks.forEach(function(hook) {
if (compiler.hooks) {
if (hook.method === 'sync') {
compiler.hooks[hook.name].tap(this.plugin, () => handler())
} else {
compiler.hooks[hook.name].tapAsync(this.plugin, (_, callback) => handler(callback))
}
})
})
} else {
compiler.plugin(hook, function(_, callback) {
handler(callback)
})
}
}, this)

compiler.plugin('done', function(stats) {
function done(stats) {
var applyStats = Array.isArray(stats.stats) ? stats.stats : [stats]
var assets = []
var noAssets = false
Expand Down Expand Up @@ -139,12 +181,21 @@ function Plugin(
blocked[i]()
}
blocked = []
}.bind(this))
compiler.plugin('invalid', function() {
}

function invalid() {
if (!this.waiting) {
this.waiting = []
}
}.bind(this))
}

if (compiler.hooks) {
compiler.hooks.done.tap(this.plugin, done.bind(this))
compiler.hooks.invalid.tap(this.plugin, invalid.bind(this))
} else {
compiler.plugin('done', done.bind(this))
compiler.plugin('invalid', invalid.bind(this))
}

webpackMiddlewareOptions.publicPath = path.join(os.tmpdir(), '_karma_webpack_', '/')
var middleware = this.middleware = new webpackDevMiddleware(compiler, webpackMiddlewareOptions)
Expand Down Expand Up @@ -197,7 +248,7 @@ Plugin.prototype.make = function(compilation, callback) {
this.files = this.files.filter(function(f) {
return file !== f
})
this.middleware.invalidate()
invalidate(this.middleware)
}
callback(err)
}.bind(this))
Expand Down Expand Up @@ -259,7 +310,7 @@ function createPreprocesor(/* config.basePath */ basePath, webpackPlugin) {
return function(content, file, done) {
if (webpackPlugin.addFile(file.originalPath)) {
// recompile as we have an asset that we have not seen before
webpackPlugin.middleware.invalidate()
invalidate(webpackPlugin.middleware)
}

// read blocks until bundle is done
Expand Down

0 comments on commit 395eab4

Please sign in to comment.