Skip to content

Commit 9265624

Browse files
committed
Use feature detection to support webpack 2 and 3
1 parent 8b99f13 commit 9265624

File tree

3 files changed

+303
-115
lines changed

3 files changed

+303
-115
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ node_js:
44
install:
55
- yarn install
66
- yarn build
7-
- yarn add $WEBPACK
7+
- npm install $WEBPACK
88
# Test against multiple webpack versions
99
env:
1010

src/index.ts

Lines changed: 220 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ class ForkTsCheckerWebpackPlugin {
180180
}
181181

182182
if (tsconfigOk && tslintOk) {
183-
this.registerCustomHooks();
183+
if ('hooks' in compiler) {
184+
this.registerCustomHooks();
185+
}
184186
this.pluginStart();
185187
this.pluginStop();
186188
this.pluginCompile();
@@ -217,31 +219,47 @@ class ForkTsCheckerWebpackPlugin {
217219
}
218220

219221
pluginStart() {
220-
this.compiler.hooks.run.tapAsync(checkerPluginName,
221-
(_compiler: webpack.Compiler, callback: () => void) => {
222-
this.isWatching = false;
223-
callback();
224-
});
222+
const run = (_compiler: webpack.Compiler, callback: () => void) => {
223+
this.isWatching = false;
224+
callback();
225+
};
225226

226-
this.compiler.hooks.watchRun.tapAsync(checkerPluginName,
227-
(_compiler: webpack.Compiler, callback: () => void) => {
228-
this.isWatching = true;
229-
callback();
230-
});
227+
const watchRun = (_compiler: webpack.Compiler, callback: () => void) => {
228+
this.isWatching = true;
229+
callback();
230+
};
231+
232+
if ('hooks' in this.compiler) {
233+
// webpack 4
234+
this.compiler.hooks.run.tapAsync(checkerPluginName, run);
235+
this.compiler.hooks.watchRun.tapAsync(checkerPluginName, watchRun);
236+
} else {
237+
// webpack 2 / 3
238+
this.compiler.plugin('run', run);
239+
this.compiler.plugin('watch-run', watchRun);
240+
}
231241
}
232242

233243
pluginStop() {
234-
this.compiler.hooks.watchClose.tap(checkerPluginName,
235-
() => {
244+
const watchClose = () => {
245+
this.killService();
246+
};
247+
248+
const done = (_stats: webpack.Stats) => {
249+
if (!this.isWatching) {
236250
this.killService();
237-
});
251+
}
252+
};
238253

239-
this.compiler.hooks.done.tap(checkerPluginName,
240-
(_stats: webpack.Stats) => {
241-
if (!this.isWatching) {
242-
this.killService();
243-
}
244-
});
254+
if ('hooks' in this.compiler) {
255+
// webpack 4
256+
this.compiler.hooks.watchClose.tap(checkerPluginName, watchClose);
257+
this.compiler.hooks.done.tap(checkerPluginName, done);
258+
} else {
259+
// webpack 2 / 3
260+
this.compiler.plugin('watch-close', watchClose);
261+
this.compiler.plugin('done', done);
262+
}
245263

246264
process.on('exit', () => {
247265
this.killService();
@@ -292,39 +310,73 @@ class ForkTsCheckerWebpackPlugin {
292310
}
293311

294312
pluginCompile() {
295-
this.compiler.hooks.compile.tap(checkerPluginName, () => {
296-
this.compiler.hooks.forkTsCheckerServiceBeforeStart.callAsync(() => {
297-
if (this.cancellationToken) {
298-
// request cancellation if there is not finished job
299-
this.cancellationToken.requestCancellation();
300-
this.compiler.hooks.forkTsCheckerCancel.call(this.cancellationToken);
301-
}
302-
this.checkDone = false;
303-
this.compilationDone = false;
313+
if ('hooks' in this.compiler) {
314+
// webpack 4
315+
this.compiler.hooks.compile.tap(checkerPluginName, () => {
316+
this.compiler.hooks.forkTsCheckerServiceBeforeStart.callAsync(() => {
317+
if (this.cancellationToken) {
318+
// request cancellation if there is not finished job
319+
this.cancellationToken.requestCancellation();
320+
this.compiler.hooks.forkTsCheckerCancel.call(this.cancellationToken);
321+
}
322+
this.checkDone = false;
323+
this.compilationDone = false;
304324

305-
this.started = process.hrtime();
325+
this.started = process.hrtime();
306326

307-
// create new token for current job
308-
this.cancellationToken = new CancellationToken(undefined, undefined);
309-
if (!this.service || !this.service.connected) {
310-
this.spawnService();
311-
}
327+
// create new token for current job
328+
this.cancellationToken = new CancellationToken(undefined, undefined);
329+
if (!this.service || !this.service.connected) {
330+
this.spawnService();
331+
}
312332

313-
try {
314-
this.service.send(this.cancellationToken);
315-
} catch (error) {
316-
if (!this.silent && this.logger) {
317-
this.logger.error(this.colors.red('Cannot start checker service: ' + (error ? error.toString() : 'Unknown error')));
333+
try {
334+
this.service.send(this.cancellationToken);
335+
} catch (error) {
336+
if (!this.silent && this.logger) {
337+
this.logger.error(this.colors.red('Cannot start checker service: ' + (error ? error.toString() : 'Unknown error')));
338+
}
339+
340+
this.compiler.hooks.forkTsCheckerServiceStartError.call(error);
341+
}
342+
});
343+
});
344+
} else {
345+
// webpack 2 / 3
346+
this.compiler.plugin('compile', () => {
347+
this.compiler.applyPluginsAsync('fork-ts-checker-service-before-start', () => {
348+
if (this.cancellationToken) {
349+
// request cancellation if there is not finished job
350+
this.cancellationToken.requestCancellation();
351+
this.compiler.applyPlugins('fork-ts-checker-cancel', this.cancellationToken);
318352
}
353+
this.checkDone = false;
354+
this.compilationDone = false;
319355

320-
this.compiler.hooks.forkTsCheckerServiceStartError.call(error);
321-
}
356+
this.started = process.hrtime();
357+
358+
// create new token for current job
359+
this.cancellationToken = new CancellationToken(undefined, undefined);
360+
if (!this.service || !this.service.connected) {
361+
this.spawnService();
362+
}
363+
364+
try {
365+
this.service.send(this.cancellationToken);
366+
} catch (error) {
367+
if (!this.silent && this.logger) {
368+
this.logger.error(this.colors.red('Cannot start checker service: ' + (error ? error.toString() : 'Unknown error')));
369+
}
370+
371+
this.compiler.applyPlugins('fork-ts-checker-service-start-error', error);
372+
}
373+
});
322374
});
323-
});
375+
}
324376
}
325377

326378
pluginEmit() {
327-
this.compiler.hooks.emit.tapAsync(checkerPluginName, (compilation: any, callback: () => void) => {
379+
const emit = (compilation: any, callback: () => void) => {
328380
if (this.isWatching && this.async) {
329381
callback();
330382
return;
@@ -337,32 +389,70 @@ class ForkTsCheckerWebpackPlugin {
337389
}
338390

339391
this.compilationDone = true;
340-
});
392+
};
393+
394+
if ('hooks' in this.compiler) {
395+
// webpack 4
396+
this.compiler.hooks.emit.tapAsync(checkerPluginName, emit);
397+
} else {
398+
// webpack 2 / 3
399+
this.compiler.plugin('emit', emit);
400+
}
341401
}
342402

343403
pluginDone() {
344-
this.compiler.hooks.done.tap(checkerPluginName, (_stats: webpack.Stats) => {
345-
if (!this.isWatching || !this.async) {
346-
return;
347-
}
404+
if ('hooks' in this.compiler) {
405+
// webpack 4
406+
this.compiler.hooks.done.tap(checkerPluginName, (_stats: webpack.Stats) => {
407+
if (!this.isWatching || !this.async) {
408+
return;
409+
}
348410

349-
if (this.checkDone) {
350-
this.doneCallback();
351-
} else {
352-
if (this.compiler) {
353-
this.compiler.hooks.forkTsCheckerWaiting.call(this.tslint !== false);
411+
if (this.checkDone) {
412+
this.doneCallback();
413+
} else {
414+
if (this.compiler) {
415+
this.compiler.hooks.forkTsCheckerWaiting.call(this.tslint !== false);
416+
}
417+
if (!this.silent && this.logger) {
418+
this.logger.info(
419+
this.tslint
420+
? 'Type checking and linting in progress...'
421+
: 'Type checking in progress...'
422+
);
423+
}
354424
}
355-
if (!this.silent && this.logger) {
356-
this.logger.info(
357-
this.tslint
358-
? 'Type checking and linting in progress...'
359-
: 'Type checking in progress...'
360-
);
425+
426+
this.compilationDone = true;
427+
});
428+
} else {
429+
// webpack 2 / 3
430+
this.compiler.plugin('done', () => {
431+
if (!this.isWatching || !this.async) {
432+
return;
361433
}
362-
}
363434

364-
this.compilationDone = true;
365-
});
435+
if (this.checkDone) {
436+
this.doneCallback();
437+
} else {
438+
if (this.compiler) {
439+
this.compiler.applyPlugins(
440+
'fork-ts-checker-waiting',
441+
this.tslint !== false
442+
);
443+
}
444+
if (!this.silent && this.logger) {
445+
this.logger.info(
446+
this.tslint
447+
? 'Type checking and linting in progress...'
448+
: 'Type checking in progress...'
449+
);
450+
}
451+
}
452+
453+
this.compilationDone = true;
454+
});
455+
}
366456
}
367457

368458
spawnService() {
@@ -388,13 +478,26 @@ class ForkTsCheckerWebpackPlugin {
388478
}
389479
);
390480

391-
this.compiler.hooks.forkTsCheckerServiceStart.call(
392-
this.tsconfigPath,
393-
this.tslintPath,
394-
this.watchPaths,
395-
this.workersNumber,
396-
this.memoryLimit
397-
);
481+
if ('hooks' in this.compiler) {
482+
// webpack 4
483+
this.compiler.hooks.forkTsCheckerServiceStart.call(
484+
this.tsconfigPath,
485+
this.tslintPath,
486+
this.watchPaths,
487+
this.workersNumber,
488+
this.memoryLimit
489+
);
490+
} else {
491+
// webpack 2 / 3
492+
this.compiler.applyPlugins(
493+
'fork-ts-checker-service-start',
494+
this.tsconfigPath,
495+
this.tslintPath,
496+
this.watchPaths,
497+
this.workersNumber,
498+
this.memoryLimit
499+
);
500+
}
398501

399502
if (!this.silent && this.logger) {
400503
this.logger.info('Starting type checking' + (this.tslint ? ' and linting' : '') + ' service...');
@@ -459,7 +562,13 @@ class ForkTsCheckerWebpackPlugin {
459562
);
460563
}
461564

462-
this.compiler.hooks.forkTsCheckerReceive.call(this.diagnostics, this.lints);
565+
if ('hooks' in this.compiler) {
566+
// webpack 4
567+
this.compiler.hooks.forkTsCheckerReceive.call(this.diagnostics, this.lints);
568+
} else {
569+
// webpack 2 / 3
570+
this.compiler.applyPlugins('fork-ts-checker-receive', this.diagnostics, this.lints);
571+
}
463572

464573
if (this.compilationDone) {
465574
(this.isWatching && this.async) ? this.doneCallback() : this.emitCallback();
@@ -470,7 +579,13 @@ class ForkTsCheckerWebpackPlugin {
470579
if (signal === 'SIGABRT') {
471580
// probably out of memory :/
472581
if (this.compiler) {
473-
this.compiler.hooks.forkTsCheckerServiceOutOfMemory.call();
582+
if ('hooks' in this.compiler) {
583+
// webpack 4
584+
this.compiler.hooks.forkTsCheckerServiceOutOfMemory.call();
585+
} else {
586+
// webpack 2 / 3
587+
this.compiler.applyPlugins('fork-ts-checker-service-out-of-memory');
588+
}
474589
}
475590
if (!this.silent && this.logger) {
476591
this.logger.error(
@@ -487,11 +602,22 @@ class ForkTsCheckerWebpackPlugin {
487602
return function emitCallback (this: ForkTsCheckerWebpackPlugin) {
488603
const elapsed = Math.round(this.elapsed[0] * 1E9 + this.elapsed[1]);
489604

490-
this.compiler.hooks.forkTsCheckerEmit.call(
491-
this.diagnostics,
492-
this.lints,
493-
elapsed
494-
);
605+
if ('hooks' in this.compiler) {
606+
// webpack 4
607+
this.compiler.hooks.forkTsCheckerEmit.call(
608+
this.diagnostics,
609+
this.lints,
610+
elapsed
611+
);
612+
} else {
613+
// webpack 2 / 3
614+
this.compiler.applyPlugins(
615+
'fork-ts-checker-emit',
616+
this.diagnostics,
617+
this.lints,
618+
elapsed
619+
);
620+
}
495621

496622
this.diagnostics.concat(this.lints).forEach(message => {
497623
// webpack message format
@@ -529,12 +655,24 @@ class ForkTsCheckerWebpackPlugin {
529655
const elapsed = Math.round(this.elapsed[0] * 1E9 + this.elapsed[1]);
530656

531657
if (this.compiler) {
532-
this.compiler.hooks.forkTsCheckerDone.call(
533-
this.diagnostics,
534-
this.lints,
535-
elapsed
536-
);
658+
if ('hooks' in this.compiler) {
659+
// webpack 4
660+
this.compiler.hooks.forkTsCheckerDone.call(
661+
this.diagnostics,
662+
this.lints,
663+
elapsed
664+
);
665+
} else {
666+
// webpack 2 / 3
667+
this.compiler.applyPlugins(
668+
'fork-ts-checker-done',
669+
this.diagnostics,
670+
this.lints,
671+
elapsed
672+
);
673+
}
537674
}
675+
538676
if (!this.silent && this.logger) {
539677
if (this.diagnostics.length || this.lints.length) {
540678
(this.lints || []).concat(this.diagnostics).forEach(message => {

0 commit comments

Comments
 (0)