Skip to content

Commit

Permalink
feat: migrate from reporters to workers (#691)
Browse files Browse the repository at this point in the history
Use simple functions and modules to simplify worker code
  • Loading branch information
piotr-oles committed Jan 11, 2022
1 parent a0ad06f commit f7dfdcf
Show file tree
Hide file tree
Showing 105 changed files with 2,187 additions and 3,123 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*.log

# Package artifacts
lib
/lib

# Package archive used by e2e tests
fork-ts-checker-webpack-plugin-0.0.0-semantic-release.tgz
Expand Down
33 changes: 19 additions & 14 deletions src/ForkTsCheckerWebpackPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as path from 'path';

import { cosmiconfigSync } from 'cosmiconfig';
import merge from 'deepmerge';
import type { JSONSchema7 } from 'json-schema';
Expand All @@ -15,10 +17,12 @@ import { dependenciesPool, issuesPool } from './hooks/pluginPools';
import { tapAfterCompileToAddDependencies } from './hooks/tapAfterCompileToAddDependencies';
import { tapAfterEnvironmentToPatchWatching } from './hooks/tapAfterEnvironmentToPatchWatching';
import { tapErrorToLogMessage } from './hooks/tapErrorToLogMessage';
import { tapStartToConnectAndRunReporter } from './hooks/tapStartToConnectAndRunReporter';
import { tapStopToDisconnectReporter } from './hooks/tapStopToDisconnectReporter';
import { createTypeScriptReporterRpcClient } from './typescript-reporter/reporter/TypeScriptReporterRpcClient';
import { assertTypeScriptSupport } from './typescript-reporter/TypeScriptSupport';
import { tapStartToRunWorkers } from './hooks/tapStartToRunWorkers';
import { tapStopToTerminateWorkers } from './hooks/tapStopToTerminateWorkers';
import { assertTypeScriptSupport } from './typescript/TypeScriptSupport';
import type { GetDependenciesWorker } from './typescript/worker/get-dependencies-worker';
import type { GetIssuesWorker } from './typescript/worker/get-issues-worker';
import { createRpcWorker } from './utils/rpc';

class ForkTsCheckerWebpackPlugin {
/**
Expand Down Expand Up @@ -61,19 +65,20 @@ class ForkTsCheckerWebpackPlugin {
const state = createForkTsCheckerWebpackPluginState();

assertTypeScriptSupport(configuration.typescript);
const issuesReporter = createTypeScriptReporterRpcClient(configuration.typescript);
const dependenciesReporter = createTypeScriptReporterRpcClient(configuration.typescript);
const getIssuesWorker = createRpcWorker<GetIssuesWorker>(
path.resolve(__dirname, './typescript/worker/get-issues-worker.js'),
configuration.typescript,
configuration.typescript.memoryLimit
);
const getDependenciesWorker = createRpcWorker<GetDependenciesWorker>(
path.resolve(__dirname, './typescript/worker/get-dependencies-worker.js'),
configuration.typescript
);

tapAfterEnvironmentToPatchWatching(compiler, state);
tapStartToConnectAndRunReporter(
compiler,
issuesReporter,
dependenciesReporter,
configuration,
state
);
tapStartToRunWorkers(compiler, getIssuesWorker, getDependenciesWorker, configuration, state);
tapAfterCompileToAddDependencies(compiler, configuration, state);
tapStopToDisconnectReporter(compiler, issuesReporter, dependenciesReporter, state);
tapStopToTerminateWorkers(compiler, getIssuesWorker, getDependenciesWorker, state);
tapErrorToLogMessage(compiler, configuration);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/ForkTsCheckerWebpackPluginConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { IssueConfiguration } from './issue/IssueConfiguration';
import { createIssueConfiguration } from './issue/IssueConfiguration';
import type { LoggerConfiguration } from './logger/LoggerConfiguration';
import { createLoggerConfiguration } from './logger/LoggerConfiguration';
import type { TypeScriptReporterConfiguration } from './typescript-reporter/TypeScriptReporterConfiguration';
import { createTypeScriptReporterConfiguration } from './typescript-reporter/TypeScriptReporterConfiguration';
import type { TypeScriptReporterConfiguration } from './typescript/TypeScriptReporterConfiguration';
import { createTypeScriptReporterConfiguration } from './typescript/TypeScriptReporterConfiguration';

interface ForkTsCheckerWebpackPluginConfiguration {
async: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/ForkTsCheckerWebpackPluginOptions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { FormatterOptions } from './formatter';
import type { IssueOptions } from './issue/IssueOptions';
import type LoggerOptions from './logger/LoggerOptions';
import type { TypeScriptReporterOptions } from './typescript-reporter/TypeScriptReporterOptions';
import type { TypeScriptReporterOptions } from './typescript/TypeScriptReporterOptions';

interface ForkTsCheckerWebpackPluginOptions {
async?: boolean;
Expand Down
8 changes: 3 additions & 5 deletions src/ForkTsCheckerWebpackPluginState.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import type { FullTap } from 'tapable';

import type { FilesMatch } from './files-match';
import type { Issue } from './issue';
import type { FilesMatch, Report } from './reporter';

interface ForkTsCheckerWebpackPluginState {
issuesReportPromise: Promise<Report | undefined>;
dependenciesReportPromise: Promise<Report | undefined>;
issuesPromise: Promise<Issue[] | undefined>;
dependenciesPromise: Promise<FilesMatch | undefined>;
lastDependencies: FilesMatch | undefined;
watching: boolean;
initialized: boolean;
iteration: number;
webpackDevServerDoneTap: FullTap | undefined;
}

function createForkTsCheckerWebpackPluginState(): ForkTsCheckerWebpackPluginState {
return {
issuesReportPromise: Promise.resolve(undefined),
dependenciesReportPromise: Promise.resolve(undefined),
issuesPromise: Promise.resolve(undefined),
dependenciesPromise: Promise.resolve(undefined),
lastDependencies: undefined,
watching: false,
initialized: false,
iteration: 0,
webpackDevServerDoneTap: undefined,
};
}
Expand Down
5 changes: 0 additions & 5 deletions src/error/OperationCanceledError.ts

This file was deleted.

14 changes: 7 additions & 7 deletions src/reporter/FilesChange.ts → src/files-change.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import type { Compiler } from 'webpack';
import type * as webpack from 'webpack';

import subtract from '../utils/array/substract';
import unique from '../utils/array/unique';
import subtract from './utils/array/substract';
import unique from './utils/array/unique';

interface FilesChange {
changedFiles?: string[];
deletedFiles?: string[];
}

const compilerFilesChangeMap = new WeakMap<Compiler, FilesChange>();
const compilerFilesChangeMap = new WeakMap<webpack.Compiler, FilesChange>();

function getFilesChange(compiler: Compiler): FilesChange {
function getFilesChange(compiler: webpack.Compiler): FilesChange {
return compilerFilesChangeMap.get(compiler) || { changedFiles: [], deletedFiles: [] };
}

function updateFilesChange(compiler: Compiler, change: FilesChange): void {
function updateFilesChange(compiler: webpack.Compiler, change: FilesChange): void {
compilerFilesChangeMap.set(compiler, aggregateFilesChanges([getFilesChange(compiler), change]));
}

function clearFilesChange(compiler: Compiler): void {
function clearFilesChange(compiler: webpack.Compiler): void {
compilerFilesChangeMap.delete(compiler);
}

Expand Down
File renamed without changes.
4 changes: 4 additions & 0 deletions src/hooks/interceptDoneToGetWebpackDevServerTap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';

function interceptDoneToGetWebpackDevServerTap(
compiler: webpack.Compiler,
configuration: ForkTsCheckerWebpackPluginConfiguration,
state: ForkTsCheckerWebpackPluginState
) {
const { debug } = getInfrastructureLogger(compiler);

// inspired by https://github.com/ypresto/fork-ts-checker-async-overlay-webpack-plugin
compiler.hooks.done.intercept({
register: (tap) => {
Expand All @@ -16,6 +19,7 @@ function interceptDoneToGetWebpackDevServerTap(
tap.type === 'sync' &&
configuration.logger.devServer
) {
debug('Intercepting webpack-dev-server tap.');
state.webpackDevServerDoneTap = tap;
}
return tap;
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/pluginHooks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { SyncHook, SyncWaterfallHook, AsyncSeriesWaterfallHook } from 'tapable';
import type * as webpack from 'webpack';

import type { FilesChange } from '../files-change';
import type { Issue } from '../issue';
import type { FilesChange } from '../reporter';

const compilerHookMap = new WeakMap<
webpack.Compiler | webpack.MultiCompiler,
Expand Down
4 changes: 4 additions & 0 deletions src/hooks/tapAfterCompileToAddDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';

function tapAfterCompileToAddDependencies(
compiler: webpack.Compiler,
configuration: ForkTsCheckerWebpackPluginConfiguration,
state: ForkTsCheckerWebpackPluginState
) {
const { debug } = getInfrastructureLogger(compiler);

compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', async (compilation) => {
if (compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
Expand All @@ -16,6 +19,7 @@ function tapAfterCompileToAddDependencies(

const dependencies = await state.dependenciesPromise;

debug(`Got dependencies from the getDependenciesWorker.`, dependencies);
if (dependencies) {
state.lastDependencies = dependencies;

Expand Down
4 changes: 4 additions & 0 deletions src/hooks/tapAfterCompileToGetIssues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';
import type { Issue } from '../issue';
import { IssueWebpackError } from '../issue/IssueWebpackError';

Expand All @@ -13,6 +14,7 @@ function tapAfterCompileToGetIssues(
state: ForkTsCheckerWebpackPluginState
) {
const hooks = getForkTsCheckerWebpackPluginHooks(compiler);
const { debug } = getInfrastructureLogger(compiler);

compiler.hooks.afterCompile.tapPromise('ForkTsCheckerWebpackPlugin', async (compilation) => {
if (compilation.compiler !== compiler) {
Expand All @@ -29,6 +31,8 @@ function tapAfterCompileToGetIssues(
return;
}

debug('Got issues from getIssuesWorker.', issues?.length);

if (!issues) {
// some error has been thrown or it was canceled
return;
Expand Down
6 changes: 6 additions & 0 deletions src/hooks/tapAfterEnvironmentToPatchWatching.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { getInfrastructureLogger } from '../infrastructure-logger';
import { InclusiveNodeWatchFileSystem } from '../watch/InclusiveNodeWatchFileSystem';
import type { WatchFileSystem } from '../watch/WatchFileSystem';

function tapAfterEnvironmentToPatchWatching(
compiler: webpack.Compiler,
state: ForkTsCheckerWebpackPluginState
) {
const { debug } = getInfrastructureLogger(compiler);

compiler.hooks.afterEnvironment.tap('ForkTsCheckerWebpackPlugin', () => {
const watchFileSystem = compiler.watchFileSystem;
if (watchFileSystem) {
debug("Overwriting webpack's watch file system.");
// wrap original watch file system
compiler.watchFileSystem = new InclusiveNodeWatchFileSystem(
// we use some internals here
watchFileSystem as WatchFileSystem,
compiler,
state
);
} else {
debug('No watch file system found - plugin may not work correctly.');
}
});
}
Expand Down
14 changes: 5 additions & 9 deletions src/hooks/tapDoneToAsyncGetIssues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type webpack from 'webpack';
import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import type { ForkTsCheckerWebpackPluginState } from '../ForkTsCheckerWebpackPluginState';
import { createWebpackFormatter } from '../formatter/WebpackFormatter';
import { getInfrastructureLogger } from '../infrastructure-logger';
import type { Issue } from '../issue';
import { IssueWebpackError } from '../issue/IssueWebpackError';
import isPending from '../utils/async/isPending';
Expand All @@ -17,14 +18,14 @@ function tapDoneToAsyncGetIssues(
state: ForkTsCheckerWebpackPluginState
) {
const hooks = getForkTsCheckerWebpackPluginHooks(compiler);
const { log, debug } = getInfrastructureLogger(compiler);

compiler.hooks.done.tap('ForkTsCheckerWebpackPlugin', async (stats) => {
if (stats.compilation.compiler !== compiler) {
// run only for the compiler that the plugin was registered for
return;
}

const reportPromise = state.issuesReportPromise;
const issuesPromise = state.issuesPromise;
let issues: Issue[] | undefined;

Expand All @@ -38,6 +39,7 @@ function tapDoneToAsyncGetIssues(
}

issues = await issuesPromise;
debug('Got issues from getIssuesWorker.', issues?.length);
} catch (error) {
hooks.error.call(error, stats.compilation);
return;
Expand All @@ -48,11 +50,6 @@ function tapDoneToAsyncGetIssues(
return;
}

if (reportPromise !== state.issuesReportPromise) {
// there is a newer report - ignore this one
return;
}

// filter list of issues by provided issue predicate
issues = issues.filter(configuration.issue.predicate);

Expand Down Expand Up @@ -81,13 +78,12 @@ function tapDoneToAsyncGetIssues(
}
});

debug('Sending issues to the webpack-dev-server.');
state.webpackDevServerDoneTap.fn(stats);
}

if (stats.startTime) {
configuration.logger.infrastructure.log(
`Time: ${Math.round(Date.now() - stats.startTime).toString()} ms`
);
log(`Time: ${Math.round(Date.now() - stats.startTime).toString()} ms`);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/tapErrorToLogMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import chalk from 'chalk';
import type webpack from 'webpack';

import type { ForkTsCheckerWebpackPluginConfiguration } from '../ForkTsCheckerWebpackPluginConfiguration';
import { RpcIpcMessagePortClosedError } from '../rpc/rpc-ipc/error/RpcIpcMessagePortClosedError';
import { RpcExitError } from '../utils/rpc';

import { getForkTsCheckerWebpackPluginHooks } from './pluginHooks';

Expand All @@ -15,7 +15,7 @@ function tapErrorToLogMessage(
hooks.error.tap('ForkTsCheckerWebpackPlugin', (error) => {
configuration.logger.issues.error(String(error));

if (error instanceof RpcIpcMessagePortClosedError) {
if (error instanceof RpcExitError) {
if (error.signal === 'SIGINT') {
configuration.logger.issues.error(
chalk.red(
Expand Down

0 comments on commit f7dfdcf

Please sign in to comment.