诊断和日志
Parcel 包含对丰富诊断的支持,用于以与格式无关的方式描述错误和警告。它还包括一个内置的日志系统,允许报告器插件处理所有日志和错误并将其呈现给用户。
诊断
#Diagnostic
是一个 JavaScript 对象,具有一组属性,这些属性对于创建有用的日志消息是必需的。这可以是从详细消息到警告或错误的任何内容。诊断可以包括消息、关于正在处理的文件的信息、代码框架、错误信息、关于如何潜在解决问题的提示,以及指向更多文档的链接。
@parcel/diagnostic
包中的 ThrowableDiagnostic
类扩展了 JavaScript 的 Error
对象,并支持诊断。在插件中抛出错误时,使用 ThrowableDiagnostic
对象附加带有错误上下文的诊断。Parcel 将自动将您的插件名称作为诊断的来源。
import ThrowableDiagnostic from "@parcel/diagnostic";
throw new ThrowableDiagnostic({
diagnostic: {
message: "发生了一个错误",
},
});
通过将数组传递给 ThrowableDiagnostic
的 diagnostic
选项,您还可以一次抛出多个诊断。
格式化消息
#要格式化诊断中的消息,支持非常简约的 Markdown 版本。这种格式专门构建为与终端和其他渲染目标(如浏览器和编辑器)兼容,同时在没有任何格式的情况下显示时也不会太加密。@parcel/reporter-cli
使用 @parcel/markdown-ansi
库将这些 Markdown 字符串转换为用于在终端中渲染的 ANSI 转义序列。
支持的 Markdown 功能有 **粗体**
、*斜体*
/_斜体_
、__下划线__
和 ~~删除线~~
。
@parcel/diagnostic
包包括一些处理 Markdown 消息的实用工具。md
标记的模板文字处理 Markdown 字符串中任何插值表达式的转义。这确保了表达式中的任何特殊 Markdown 字符不会影响格式。
import { md } from "@parcel/diagnostic";
throw new ThrowableDiagnostic({
diagnostic: {
message: md`**错误**:无法解析 ${filePath}`,
},
});
还有一些用于格式化插值表达式的实用工具,包括 md.bold
、md.italic
、md.underline
和 md.strikethrough
。
import { md } from "@parcel/diagnostic";
throw new ThrowableDiagnostic({
diagnostic: {
message: md`**错误**:无法解析 ${md.underline(filePath)}`,
},
});
代码框架
#Diagnostic
可以附加一个或多个代码框架。代码框架包括文件路径以及一个或多个代码高亮,这些高亮提供了关于错误发生位置的上下文。代码高亮由文件中的行和列位置定义,并且可能还有要在该位置显示的消息。
代码框架还应包括发生错误的文件的源代码。如果省略,Parcel 将从文件系统读取文件。但是,在许多情况下,输入源代码可能来自之前运行的另一个插件,因此代码已以某种方式被修改。在代码框架中包含代码可以避免此问题。
throw new ThrowableDiagnostic({
diagnostic: {
message: md`无法解析 ${asset.filePath}`,
codeFrames: [
{
filePath: asset.filePath,
code: await asset.getCode(),
codeHighlights: [
{
start: {
line: 1,
column: 5,
},
end: {
line: 2,
column: 3,
},
message: "预期是字符串,但得到了数字",
},
],
},
],
},
});
提示
#诊断还可以包括关于如何修复问题的提示,以及指向文档的链接,供用户了解更多信息。这些通过 hints
和 documentationURL
属性提供。
throw new ThrowableDiagnostic({
diagnostic: {
message: "找不到配置文件",
hints: ["在项目根目录创建 tool.config.json 文件。"],
documentationURL: "http://example.com/",
},
});
日志记录器
#Parcel 的日志记录器可用于在插件中记录消息。插件的每个函数都作为参数传递了一个 Logger
实例。该实例具有 Parcel 识别消息来源所需的所有信息。
日志记录器接受诊断,这些是具有标准化属性集的 JavaScript 对象,描述日志消息、其来源和上下文(如代码框架)。报告器插件使用这些信息记录您的消息,同时完全自由地决定如何格式化和显示这些数据。
Logger
有一个针对每个日志级别的函数,包括 verbose
、info
、log
、warn
和 error
。这些日志级别指定日志消息的严重性,这对于格式化和过滤很有用。例如,可以使用 --log-level
CLI 选项选择要查看的消息。每个日志记录函数都有一个单一参数,可以是单个 Diagnostic
对象,也可以是诊断数组,具体取决于要记录的消息数量。
note:Parcel 插件的结果是缓存的。这意味着插件发出的任何日志或警告只会在重新构建期间显示,而不会在缓存时显示。
日志级别
#级别 | 使用时机 | 函数 |
---|---|---|
verbose | 当您想记录可用于调试问题的任何内容,同时对普通使用不特别有趣时使用。 | logger.verbose(...) |
info | 用于记录与问题无关的任何信息。 | logger.info(...) 或 logger.log(...) |
warning | 用于记录与非关键问题相关的任何内容。 | logger.warning(...) |
error | 用于记录任何关键问题。您可能希望抛出 ThrowableDiagnostic 以导致构建失败。 |
logger.error(...) 或 throw ThrowableDiagnostic(...) |
如何记录消息
#熟悉 Diagnostic
格式后,您可以记录任何想要的内容,从详细消息到带有代码框架、提示和文档 URL 的错误。此示例展示了如何记录警告,包括代码框架、提示和文档 URL。
import { Transformer } from "@parcel/plugin";
export default new Transformer({
async transform({ asset, logger }) {
// ...
logger.warn({
message: "此功能已弃用。",
codeFrames: [
{
filePath: asset.filePath,
code: await asset.getCode(),
codeHighlights: [
{
start: {
line: 1,
column: 5,
},
end: {
line: 1,
column: 10,
},
},
],
},
],
hints: ["请改用此其他功能。"],
documentationURL: "http://example.com/",
});
},
});
自动收集的日志和错误
#Parcel 自动收集使用 console.log
和其他 console
方法创建的任何日志。每当调用 console.log
时,Parcel 都会捕获它,将其转换为 Diagnostic
对象,并像处理直接发送到 logger
的消息一样将其发送到报告器插件。但是,不建议这样做,因为 Parcel 没有像直接调用 logger
那样多的信息。
Parcel 还处理插件内部抛出的任何错误。这些被转换为 Diagnostic
,并添加了关于插件的信息。抛出的错误被发送到报告器插件,并且构建被中止。
API
#PluginLogger parcel/packages/core/logger/src/Logger.js:90
interface PluginLogger {
verbose(diagnostic: DiagnosticWithoutOrigin | Array<DiagnosticWithoutOrigin>): void,
info(diagnostic: DiagnosticWithoutOrigin | Array<DiagnosticWithoutOrigin>): void,
log(diagnostic: DiagnosticWithoutOrigin | Array<DiagnosticWithoutOrigin>): void,
warn(diagnostic: DiagnosticWithoutOrigin | Array<DiagnosticWithoutOrigin>): void,
error(input: Diagnostifiable | DiagnosticWithoutOrigin | Array<DiagnosticWithoutOrigin>): void,
}
Referenced by:
Bundler, Compressor, DedicatedThreadValidator, MultiThreadValidator, Namer, Optimizer, Packager, Reporter, Resolver, Runtime, TransformerDiagnosticHighlightLocation parcel/packages/core/diagnostic/src/diagnostic.js:8
These positions are 1-based (so 1
is the first line/column)
type DiagnosticHighlightLocation = {|
+line: number,
+column: number,
|}
Referenced by:
DiagnosticCodeHighlight, getJSONSourceLocationDiagnosticSeverity parcel/packages/core/diagnostic/src/diagnostic.js:13
Type
type DiagnosticSeverity = 'error' | 'warn' | 'info';
DiagnosticCodeHighlight parcel/packages/core/diagnostic/src/diagnostic.js:19
Note: A tab character is always counted as a single character This is to prevent any mismatch of highlighting across machines
type DiagnosticCodeHighlight = {|
start: DiagnosticHighlightLocation,
Location of the first character that should get highlighted for this highlight.
end: DiagnosticHighlightLocation,
Location of the last character that should get highlighted for this highlight.
message?: string,
A message that should be displayed at this location in the code (optional).
|}
Referenced by:
DiagnosticCodeFrame, generateJSONCodeHighlightsDiagnosticCodeFrame parcel/packages/core/diagnostic/src/diagnostic.js:33
Describes how to format a code frame. A code frame is a visualization of a piece of code with a certain amount of code highlights that point to certain chunk(s) inside the code.
type DiagnosticCodeFrame = {|
code?: string,
The contents of the source file.
If no code is passed, it will be read in from filePath, remember that
the asset's current code could be different from the input contents.
filePath?: string,
Path to the file this code frame is about (optional, absolute or relative to the project root)
language?: string,
Language of the file this code frame is about (optional)
codeHighlights: Array<DiagnosticCodeHighlight>,
|}
Referenced by:
DiagnosticDiagnostic parcel/packages/core/diagnostic/src/diagnostic.js:53
A style agnostic way of emitting errors, warnings and info. Reporters are responsible for rendering the message, codeframes, hints, ...
type Diagnostic = {|
message: string,
This is the message you want to log.
origin?: string,
Name of plugin or file that threw this error
stack?: string,
A stacktrace of the error (optional)
name?: string,
Name of the error (optional)
codeFrames?: ?Array<DiagnosticCodeFrame>,
A code frame points to a certain location(s) in the file this diagnostic is linked to (optional)
hints?: Array<string>,
An optional list of strings that suggest ways to resolve this issue
documentationURL?: string,
A URL to documentation to learn more about the diagnostic.
|}
Referenced by:
BuildFailureEvent, DiagnosticLogEvent, DiagnosticWithoutOrigin, Diagnostifiable, ResolveResult, ThrowableDiagnostic, ThrowableDiagnosticOpts, ValidateResult, anyToDiagnostic, errorToDiagnosticPrintableError parcel/packages/core/diagnostic/src/diagnostic.js:78
interface PrintableError extends Error {
fileName?: string,
filePath?: string,
codeFrame?: string,
highlightedCodeFrame?: string,
loc?: ?{
column: number,
line: number,
...
},
source?: string,
}
Referenced by:
Diagnostifiable, errorToDiagnosticDiagnosticWithoutOrigin parcel/packages/core/diagnostic/src/diagnostic.js:91
type DiagnosticWithoutOrigin = {|
...Diagnostic,
origin?: string,
|}
Referenced by:
PluginLoggerDiagnostifiable parcel/packages/core/diagnostic/src/diagnostic.js:97
Something that can be turned into a diagnostic.
Type
type Diagnostifiable = Diagnostic | Array<Diagnostic> | ThrowableDiagnostic | PrintableError | Error | string;
Referenced by:
PluginLogger, anyToDiagnosticanyToDiagnostic parcel/packages/core/diagnostic/src/diagnostic.js:106
Normalize the given value into a diagnostic.
Type
function anyToDiagnostic(input: Diagnostifiable): Array<Diagnostic> {}
errorToDiagnostic parcel/packages/core/diagnostic/src/diagnostic.js:123
Normalize the given error into a diagnostic.
Type
function errorToDiagnostic(error: ThrowableDiagnostic | PrintableError | string, defaultValues?: {|
origin?: ?string,
filePath?: ?string,
|}): Array<Diagnostic> {}
ThrowableDiagnosticOpts parcel/packages/core/diagnostic/src/diagnostic.js:189
type ThrowableDiagnosticOpts = {
diagnostic: Diagnostic | Array<Diagnostic>,
}
Referenced by:
ThrowableDiagnosticThrowableDiagnostic parcel/packages/core/diagnostic/src/diagnostic.js:198
An error wrapper around a diagnostic that can be throw
n (e.g. to signal a
build error).
interface ThrowableDiagnostic extends Error {
diagnostics: Array<Diagnostic>,
constructor(opts: ThrowableDiagnosticOpts): void,
}
Referenced by:
Diagnostifiable, errorToDiagnosticgenerateJSONCodeHighlights parcel/packages/core/diagnostic/src/diagnostic.js:225
Turns a list of positions in a JSON5 file with messages into a list of diagnostics.
Uses @mischnic/json-sourcemap.
Parameter Descriptions
code
: the JSON codeids
: A list of JSON keypaths (key: "/some/parent/child"
) with corresponding messages,type
signifies whether the key of the value in a JSON object should be highlighted.
Type
function generateJSONCodeHighlights(data: string | {|
data: mixed,
pointers: {|
[key: string]: Mapping
|},
|}, ids: Array<{|
key: string,
type?: ?'key' | 'value',
message?: string,
|}>): Array<DiagnosticCodeHighlight> {}
Referenced by:
encodeJSONKeyComponentgetJSONSourceLocation parcel/packages/core/diagnostic/src/diagnostic.js:251
Converts entries in @mischnic/json-sourcemap's
result.pointers
array.
Type
function getJSONSourceLocation(pos: Mapping, type?: ?'key' | 'value'): {|
start: DiagnosticHighlightLocation,
end: DiagnosticHighlightLocation,
|} {}
encodeJSONKeyComponent parcel/packages/core/diagnostic/src/diagnostic.js:281
Sanitizes object keys before using them as key
in generateJSONCodeHighlights
Type
function encodeJSONKeyComponent(component: string): string {}
escapeMarkdown parcel/packages/core/diagnostic/src/diagnostic.js:287
Type
function escapeMarkdown(s: string): string {}
TemplateInput parcel/packages/core/diagnostic/src/diagnostic.js:296
Type
type TemplateInput = $FlowFixMe;
Referenced by:
mdmd parcel/packages/core/diagnostic/src/diagnostic.js:299
Type
function md(strings: Array<string>, ...params: Array<TemplateInput>): string {}