Proposal to enhance loader error reporting API: structured error reporting
See original GitHub issueProblem
Currently loader context provides an opaque API for error reporting: only
message
, stack
and (undocumented?) hideStack
error object
properties are used to report an error to a user.
Thus the appearance of error varies widely between different loaders. Babel, eslint, css, postcss, sass loaders for example all have different error reporting styles.
In addition to that there’s a lot of duplicated info, some loaders render filename of the module which is unnecessary as Webpack does so too and in a more concise manner (it uses request shortener).
I believe this overwhelms users of Webpack and takes a lot more cognitive efforts to recognize and process errors.
Solution
The solution I propose is to enhance error reporting API of loaders, namely:
this.emitError(err) // emit error
let cb = this.async(); cb(err, result) // emit error via cb
throw new Error(...) // emit error via throw
To accept an Error
object with the following properties:
name: string
— name of the error. Already present on errors but is not used explicitly.reason: string
— a human readable error message without filename of the module happened into. If not provided thenmessage
property is used as before.loc?: {line: number, column: number}
— optional default:undefined
, a location within the module error happened into. If provided it is used to render a code frame (similar to how babel-loader and css-loader do).hideStack?: boolean
— optional, defaultfalse
, a boolean flag which indicates that webpack shouldn’t render stack trace. Note thathideStack
already works but is undocumented.
With presence of such structured error messages Webpack could render errors in a consistent way:
ERROR in {moduleName}
${err.name}: ${err.reason}
${err.loc ? formatCodeFrame(source, err.loc.line, err.loc.column) : ''}
Note that moduleName
and source
are available to Webpack already.
Also webpack could provide plugin hooks for different error reporting UIs.
Example of loader API usage:
try {
return babelTransform(source)
catch (internalError) {
// only normalize known errors
if (internalError instanceof BabelSyntaxError) {
let error = new Error()
// readable name of the error type
error.name = 'Syntax error';
// strip filename from here if needed or use some other property
error.reason = internalError.message;
// location
error.loc = internalError.location;
// stack trace from parser isn't useful for end users
error.hideStack = true;
throw error;
// throw all other errors as-is
} else {
throw internalError;
}
}
Alternative solutions
Such work could be done by loaders themselves (normalizing message
property
and formatting code frames). But:
- This is more fragile as it is easy to drift away from consistence if error appearance would be controlled separately by loaders.
- Loader will have to do more to get better error reporting.
- Webpack provides UI but leaves error reporting UI to loaders. This leads to inconsistent developer experience.
I made the following PRs to loaders:
- https://github.com/babel/babel-loader/pull/287
- https://github.com/webpack/css-loader/pull/319
- https://github.com/postcss/postcss-loader/pull/87
But I believe if we enhance error reporting API it would be a much cleaner solution.
Also see what create-react-app is doing: we can get rid of this with this proposal & a couple of PRs to loadrs too.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:5
- Comments:8 (6 by maintainers)
Also:
@TheLarkInn as I understood current webpack UI isn’t written with plugins in mind (only compiler allows plugins). I think the first step would be to improve on default UI and only then modify it to allow plugins.