VSCode integration with webpack in watch mode
I'm using this loader with webpack in watch mode. In vscode you must defined start/end pattern for background task, so that vscode knows when to parse output for errors. The problem is that there is no distinguished message generated after errors are written to output stream. I also haven't found any solution to overcome this with webpack. Is it possible that this loader generates some distinguished start/end message. It is important that end message is generated after last error is streamed to output.
Hi @edvinv,
I'm afraid I don't know what you mean about "defined start/end pattern for background task". That said, I'm an avid VS Code user. Maybe if I tell you about my workflow / setup it might be useful to you:
- Fire up VS Code
- Open the terminal and enter
yarn start
This fires up webpack in watch mode, which allows me to see errors in the console and click upon them to get transported to the code itself. You can see examples (slightly out of date) here:
https://github.com/TypeStrong/ts-loader/tree/master/examples
Does this help at all?
Note to self - I must update the examples:
- drop the webpack 1 example
- remove gulp entirely
thx, @johnnyreilly
If you only look for errors in terminal this is ok, but if you want to make better integration and see errors in problem panel you must define problemMatcher in tasks.json. Problem matcher parses error output from compiler so that it is understood by vscode and can be correctly displayed. But for background tasks, such as webpack watch mode, vscode must know when compiling was started and when it was ended. This pattern is defined by beginsPattern and endsPattern properties in tasks.json. If you run tsc in watch mode, output is something like this:
10:09:54 AM - File change detected. Starting incremental compilation...
crosstyd/stores/dialer-campaigns-store.ts(164,47): error TS1005: ')' expected.
10:09:56 AM - Compilation complete. Watching for file changes.
So you have "Starting incremental compilation" and "Compilation complete. Watching for file changes." text that marks start/end compilation. But in the case of webpack watch mode there is no such text that can be used. Especially for marking compilation end. No text is streamed to output after last error! For example:
Hash: 4223297a8e86b7b2b6d3
Version: webpack 3.6.0
Time: 3942ms
Asset Size Chunks Chunk Names
.....
+ 830 hidden modules
ERROR in ./src/ui/call.ts
(20,12): error TS1005: ':' expected.
So it will be good that some start/end text will be generated, that can be used to inform vscode when background process is running. Ideally if the output will be the same as for tsc, you will be able to use "$tsc-watch" for problemMatcher and everything should work out of box.
Another benefit of knowing compilation start/end is with debugging. If you change some files and you start debugging (F5), vscode will save files what will then trigger compiler and vscode can wait for compiler to finish before debugger actually starts.
That's interesting @edvinv - thanks for the background. For my own use case I find that the TypeScript integration in VS Code already surfaces errors in the problem pane. Don't you get the same?
What you probably see is output from typescript service. As I understand those errors are auto generated for opened files and disappear when file is closed. On other side you can capture errors generated from compiler output with problem matcher as described here and here.
Ah that's pretty cool. So what do you propose? We already have a https://github.com/typestrong/ts-loader#errorformatter-message-errorinfo-colors-boolean--string-defaultundefined option. Does that give you what you need to hook into?
thx for info, I was not aware that you can configure output for ts-loader, but this is not so problematic, because for vscode you can add your own custom problem matcher or load appropriate extension like ts-loader matcher. Most problematic is the output when you run webpack in watch mode, then you don't get any message after last error and you can not inform vscode when compilation was ended. So it will be nice that ts-loader will generate start/end message when running in watch mode, like tsc does when running with --watch switch.
About output formating. IMO ts-loader should by default generate exactly the same output as tsc does, for both, normal and watch mode. This is also the most logical, if I run tsc standalone or in webpack I would expect same output result. In the case of vscode this means that you don't need any custom problem matcher or corresponding extension you just use $tsc or $tsc-watch. Of course integration of ts-loader will also be easier for other editors that already integrate tsc.
About output formatting. IMO ts-loader should by default generate exactly the same output as tsc does, for both, normal and watch mode.
I'd be open to having an in-build formatter that supports this.
So it will be nice that ts-loader will generate start/end message when running in watch mode,
This doesn't seem unreasonable.
Would you like to submit a PR to provide this support?
@johnnyreilly, sorry for late reply. Having ts-loader generate same output as tsc is good and most logical solution. This will simplify integration in vs-code and other tools.
About generating start/end message in watch mode, I have found an open issue webpack/webpack#5895. Implementing this on web-pack side is better and more general solution, so I will postpone this and wait for web-pack response.
Any progress on this matter? I would also like to see easy integration of webpack watchmode within vs code.
While I agree that webpack should fix the start/end watch mode issue, https://github.com/webpack/webpack/issues/5895 is closed. Hopefully it can be reconsidered. But it would be great if the error output matched tsc
If someone wants to submit a PR I'll take a look.
I was able to get it working using the following tasks.json for webpack-dev-server: https://github.com/go-faast/faast-portfolio/blob/81877b7ce302748f25d48a458cd6680cad36ace9/.vscode/tasks.json
I've gotten things working decently well with this problem matcher for both ts-loader and tslint-loader:
"problemMatcher": [
{
"fileLocation": "absolute",
"owner": "typescript",
"pattern": [
{
"regexp": "\\[tsl\\] ERROR in (.*)?\\((\\d+),(\\d+)\\)",
"file": 1,
"line": 2,
"column": 3
},
{
"regexp": "\\s*TS\\d+:\\s*(.*)",
"message": 1
}
],
"severity": "error",
"source": "ts",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "webpack is watching the files..."
},
"endsPattern": {
"regexp": "Built at\\:(.*)"
}
}
},
{
"fileLocation": "relative",
"owner": "typescript",
"pattern": [
{
"regexp": "WARNING in (.*)",
"file": 1
},
{
"regexp": "Module Warning (.*)"
},
{
"regexp": "\\[(\\d+), (\\d+)\\]: (.*)",
"line": 1,
"column": 2,
"message": 3
}
],
"severity": "warning",
"source": "tslint",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "webpack is watching the files..."
},
"endsPattern": {
"regexp": "Built at\\:(.*)"
}
}
}
]
The big issue is since there is no good start/stop message at the start/end of each recompile problems that have been resolved often stick around in vscode. I thought this was originally a vscode issue, but you can see the resolution here: https://github.com/Microsoft/vscode/issues/55964
If you aren't using multiple configs (i.e. returning an array from your webpack config) (See: https://github.com/webpack/webpack/issues/7906), it looks like you can use webpack --watch --info-verbosity verbose to get lifecycle start and end messages
Using that and changing the problem matcher to the following seems to work well:
"problemMatcher": [
{
"fileLocation": "absolute",
"owner": "typescript",
"pattern": [
{
"regexp": "\\[tsl\\] ERROR in (.*)?\\((\\d+),(\\d+)\\)",
"file": 1,
"line": 2,
"column": 3
},
{
"regexp": "\\s*TS\\d+:\\s*(.*)",
"message": 1
}
],
"severity": "error",
"source": "ts",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "Compilation starting…"
},
"endsPattern": {
"regexp": "Compilation finished"
}
}
},
{
"fileLocation": "relative",
"owner": "typescript",
"pattern": [
{
"regexp": "WARNING in (.*)",
"file": 1
},
{
"regexp": "Module Warning (.*)"
},
{
"regexp": "\\[(\\d+), (\\d+)\\]: (.*)",
"line": 1,
"column": 2,
"message": 3
}
],
"severity": "warning",
"source": "tslint",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "Compilation starting…"
},
"endsPattern": {
"regexp": "Compilation finished"
}
}
}
]
If someone wants to submit a docs PR to cover this I'll happily take a look.
Sorry no docs PR yet, but I published TypeScript + Webpack Problem Matchers for vscode that provides a set of problem matchers for ts-loader and tslint-loader
@eamodio i don't understand how this solution can correctly work. Actually, when i use webpack --watch --info-verbosity verbose i get the following output:
Compilation starting…
Compilation finished
Hash: 9f5804b616b6b7ae6618
Version: webpack 4.17.2
Time: 1583ms
How does the begin/endPattern can work correctly with this kind of output ? Effective error output is not in between those two patterns ...
@ClementVidal Yeah, I was wrong that it would be enough to be very accurate -- although it gets a lot closer than any other options right now. I still do get errors to show up in the problems pane in vscode and they often clear when resolved -- although not always because of the inaccuracy of the pattern matching.
@eamodio Do problem 'not always' clear when you fix them, or do they never clear until you trigger a new compilation (by changing a file), in which case old problem disappear and new one replace them ? ( This is what is actually have )
AFAIK, problems will never clear until there is a new compile when using the problem matchers, since there is no trigger to update them.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Please don't close this -- this is a very important feature for using webpack in watch mode
Marked as pinned - would be better to get this into the docs
Its not just about docs -- and it might be more of a webpack than ts-loader issue, but there is still no way to really setup a problem matcher for vscode -- it kind of works with my published matcher, but still fails too often and if you have more than 1 webpack build it almost always fails to work. It really comes down to not having good messages to key the problem matcher regex to -- the message would need to have a structure of start, errors (if any), and then a completion.
FWIW, this is my solution to incremental builds and problem matchers until Webpack adds a better solution. Just add this as a plugin to your Webpack config:
import webpack from "webpack";
export class ProblemMatcherMarkerPlugin implements webpack.Plugin {
private pluginName = "ProblemMatcherMarkerPlugin";
apply( compiler: webpack.Compiler ): void {
compiler.hooks.done.tap( this.pluginName, stats => {
// We're going to hook the toString function of the "stats" object
// to put a marker at the end of the stats to signal the end of
// error reporting
let _toString = stats.toString;
stats.toString = function ( options?: webpack.compiler.StatsToStringOptions ) {
let statsString = _toString.call( this, options );
return `${statsString}\r\n\r\n# Finished compiling!`;
};
} );
}
}
It "hijacks" the toString function on Webpack's stats object to add a signal to the end. You can then use a regex to match the # Finished compiling! message as the endsPattern for your problem matchers. This works for me until Webpack adds a less-hacky solution.
I've created this extension to make it more reliable. I've not check it with ts-loader for now, but in case something didn't work as expected it should be quite easy to add.
@KnisterPeter FYI, there is a problem matcher extension for ts-loader/fork-ts-checker. And I've just added support for fork-ts-checker v5
@eamodio I know, and there are a lot of shortcommings and required configuration to use it. The extension is an alternative for it.