Skip to content

Commit

Permalink
Fixed missing errors in watch mode in webpack5 (#1208)
Browse files Browse the repository at this point in the history
* Fixed missing errors in watch mode in webpack5

* Refactor to use regex only once
  • Loading branch information
appzuka committed Nov 7, 2020
1 parent 3f73e98 commit 4909d99
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 64 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog

## v8.0.10
* [Fixed missing errors in watch mode in webpack5](https://github.com/TypeStrong/ts-loader/issues/1204) - thanks @appzuka

## v8.0.9
* [Fixed build failing when using thread-loader](https://github.com/TypeStrong/ts-loader/pull/1207) - thanks @valerio

Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "ts-loader",
"version": "8.0.9",
"version": "8.0.10",
"description": "TypeScript loader for webpack",
"main": "index.js",
"types": "dist",
Expand Down
61 changes: 38 additions & 23 deletions src/after-compile.ts
Expand Up @@ -21,8 +21,16 @@ import {
tsLoaderSource,
} from './utils';

/**
* This returns a function that has options to add assets and also to provide errors to webpack
* In webpack 4 we can do both during the afterCompile hook
* In webpack 5 only errors should be provided during aftercompile. Assets should be
* emitted during the afterProcessAssets hook
*/
export function makeAfterCompile(
instance: TSInstance,
addAssets: boolean,
provideErrors: boolean,
configFilePath: string | undefined
) {
let getCompilerOptionDiagnostics = true;
Expand All @@ -39,18 +47,22 @@ export function makeAfterCompile(
}

if (instance.loaderOptions.transpileOnly) {
provideAssetsFromSolutionBuilderHost(instance, compilation);
if (addAssets) {
provideAssetsFromSolutionBuilderHost(instance, compilation);
}
callback();
return;
}
removeCompilationTSLoaderErrors(compilation, instance.loaderOptions);

provideCompilerOptionDiagnosticErrorsToWebpack(
getCompilerOptionDiagnostics,
compilation,
instance,
configFilePath
);
if (provideErrors) {
provideCompilerOptionDiagnosticErrorsToWebpack(
getCompilerOptionDiagnostics,
compilation,
instance,
configFilePath
);
}
getCompilerOptionDiagnostics = false;

const modules = determineModules(compilation, instance);
Expand All @@ -62,22 +74,25 @@ export function makeAfterCompile(
checkAllFilesForErrors = false;

const filesWithErrors: TSFiles = new Map();
provideErrorsToWebpack(
filesToCheckForErrors,
filesWithErrors,
compilation,
modules,
instance
);
provideDeclarationFilesToWebpack(
filesToCheckForErrors,
instance,
compilation
);
provideTsBuildInfoFilesToWebpack(instance, compilation);

provideSolutionErrorsToWebpack(compilation, modules, instance);
provideAssetsFromSolutionBuilderHost(instance, compilation);
if (provideErrors) {
provideErrorsToWebpack(
filesToCheckForErrors,
filesWithErrors,
compilation,
modules,
instance
);
provideSolutionErrorsToWebpack(compilation, modules, instance);
}
if (addAssets) {
provideDeclarationFilesToWebpack(
filesToCheckForErrors,
instance,
compilation
);
provideTsBuildInfoFilesToWebpack(instance, compilation);
provideAssetsFromSolutionBuilderHost(instance, compilation);
}

instance.filesWithErrors = filesWithErrors;
instance.modifiedFiles = undefined;
Expand Down
83 changes: 43 additions & 40 deletions src/instances.ts
Expand Up @@ -302,6 +302,46 @@ function getExistingSolutionBuilderHost(key: FilePathKey) {
return undefined;
}

// Adding assets in afterCompile is deprecated in webpack 5 so we
// need different behavior for webpack4 and 5
const addAssetHooks = !!webpack.version!.match(/^4.*/)
? (loader: webpack.loader.LoaderContext, instance: TSInstance) => {
// add makeAfterCompile with addAssets = true to emit assets and report errors
loader._compiler.hooks.afterCompile.tapAsync(
'ts-loader',
makeAfterCompile(instance, true, true, instance.configFilePath)
);
}
: (loader: webpack.loader.LoaderContext, instance: TSInstance) => {
// We must be running under webpack 5+

// Add makeAfterCompile with addAssets = false to suppress emitting assets
// during the afterCompile stage. Errors will be still be reported to webpack
loader._compiler.hooks.afterCompile.tapAsync(
'ts-loader',
makeAfterCompile(instance, false, true, instance.configFilePath)
);

// Emit the assets at the afterProcessAssets stage
loader._compilation.hooks.afterProcessAssets.tap(
'ts-loader',
(_: any) => {
makeAfterCompile(
instance,
true,
false,
instance.configFilePath
)(loader._compilation, () => {
return null;
});
}
);

// It may be better to add assets at the processAssets stage (https://webpack.js.org/api/compilation-hooks/#processassets)
// This requires Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL, which does not exist in webpack4
// Consider changing this when ts-loader is built using webpack5
};

export function initializeInstance(
loader: webpack.loader.LoaderContext,
instance: TSInstance
Expand Down Expand Up @@ -350,26 +390,7 @@ export function initializeInstance(
instance.transformers = getCustomTransformers(program);
// Setup watch run for solution building
if (instance.solutionBuilderHost) {
if (loader._compilation.hooks.afterProcessAssets) {
// afterProcessAssets does not exist in webpack4
loader._compilation.hooks.afterProcessAssets.tap(
'ts-loader',
(_: any) => {
makeAfterCompile(instance, instance.configFilePath)(
loader._compilation,
() => {
return null;
}
);
}
);
} else {
// adding assets in afterCompile is deprecated in webpack 5
loader._compiler.hooks.afterCompile.tapAsync(
'ts-loader',
makeAfterCompile(instance, instance.configFilePath)
);
}
addAssetHooks(loader, instance);
loader._compiler.hooks.watchRun.tapAsync(
'ts-loader',
makeWatchRun(instance, loader)
Expand Down Expand Up @@ -416,26 +437,8 @@ export function initializeInstance(
instance.languageService!.getProgram()
);
}
if (loader._compilation.hooks.afterProcessAssets) {
// afterProcessAssets does not exist in webpack4
loader._compilation.hooks.afterProcessAssets.tap(
'ts-loader',
(_: any) => {
makeAfterCompile(instance, instance.configFilePath)(
loader._compilation,
() => {
return null;
}
);
}
);
} else {
// adding assets in afterCompile is deprecated in webpack 5
loader._compiler.hooks.afterCompile.tapAsync(
'ts-loader',
makeAfterCompile(instance, instance.configFilePath)
);
}

addAssetHooks(loader, instance);

loader._compiler.hooks.watchRun.tapAsync(
'ts-loader',
Expand Down

0 comments on commit 4909d99

Please sign in to comment.