@rsdoctor/docs 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/en/_meta.json +1 -1
- package/docs/en/blog/release/_meta.json +1 -1
- package/docs/en/blog/release/release-note-0_3.mdx +138 -0
- package/docs/en/config/options/options.mdx +54 -1
- package/docs/en/guide/_meta.json +5 -0
- package/docs/en/guide/custom/_meta.json +1 -0
- package/docs/en/guide/custom/rule-custom.mdx +558 -0
- package/docs/en/guide/custom/upload-data.mdx +45 -0
- package/docs/zh/_meta.json +1 -1
- package/docs/zh/blog/release/_meta.json +1 -1
- package/docs/zh/blog/release/release-note-0_3.mdx +133 -0
- package/docs/zh/config/options/options.mdx +54 -1
- package/docs/zh/guide/_meta.json +5 -0
- package/docs/zh/guide/custom/_meta.json +1 -0
- package/docs/zh/guide/custom/rule-custom.mdx +559 -0
- package/docs/zh/guide/custom/upload-data.mdx +45 -0
- package/package.json +2 -2
- /package/docs/en/blog/release/{release-note-1.mdx → release-note-0_1.mdx} +0 -0
- /package/docs/zh/blog/release/{release-note-1.mdx → release-note-0_1.mdx} +0 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
# 自定义扩展规则
|
|
2
|
+
|
|
3
|
+
## 功能介绍
|
|
4
|
+
|
|
5
|
+
考虑到用户会有特有的规则定义需求,Rsdoctor 除了内部已有的规则外,还提供了外部接口供用户定制自己的规则检查。外部扩展接口通过 `extends` 字段配置到 Rsdoctor 插件上,配置也放在 `rules` 字段内。
|
|
6
|
+
|
|
7
|
+
- 示例如下:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// src/rules/assets-count-limit.ts
|
|
11
|
+
import { defineRule } from '@rsdoctor/core/rules';
|
|
12
|
+
|
|
13
|
+
export const AssetsCountLimit = defineRule(() => ({
|
|
14
|
+
meta: {
|
|
15
|
+
category: 'bundle',
|
|
16
|
+
severity: 'Warn',
|
|
17
|
+
title: 'assets-count-limit',
|
|
18
|
+
defaultConfig: {
|
|
19
|
+
limit: 10,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
check({ chunkGraph, report, ruleConfig }) {
|
|
23
|
+
const assets = chunkGraph.getAssets();
|
|
24
|
+
|
|
25
|
+
if (assets.length > ruleConfig.limit) {
|
|
26
|
+
report({
|
|
27
|
+
message: 'The count of assets is bigger than limit',
|
|
28
|
+
detail: {
|
|
29
|
+
type: 'link',
|
|
30
|
+
link: 'https://rsdoctor.dev/zh/guide/start/quick-start', // This link just for show case.
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
}));
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// rsbuild.config.ts
|
|
40
|
+
import { AssetsCountLimit } from './rules/assets-count-limit';
|
|
41
|
+
|
|
42
|
+
export default {
|
|
43
|
+
tools: {
|
|
44
|
+
bundlerChain: (chain) => {
|
|
45
|
+
chain.plugin('Rsdoctor').use(RsdoctorRspackPlugin, [
|
|
46
|
+
{
|
|
47
|
+
linter: {
|
|
48
|
+
level: 'Error',
|
|
49
|
+
extends: [AssetsCountLimit],
|
|
50
|
+
rules: {
|
|
51
|
+
'assets-count-limit': [
|
|
52
|
+
'on',
|
|
53
|
+
{
|
|
54
|
+
limit: 1, // rule custom configs
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
可按照下面自定义规则详细步骤进行规则定义及编写。
|
|
67
|
+
|
|
68
|
+
## 自定义规则步骤
|
|
69
|
+
|
|
70
|
+
### 1. 安装
|
|
71
|
+
|
|
72
|
+
编写自定义规则时,除了安装基本的 @rsdoctor/rspack-plugin(@rsdoctor/webpack-plugin) 依赖,还需要安装 @rsdoctor/core 并使用 @rsdoctor/core/rules 中的 defineRule 函数来定义统一的 Rsdoctor 规则。
|
|
73
|
+
|
|
74
|
+
import { PackageManagerTabs } from '@theme';
|
|
75
|
+
|
|
76
|
+
import { Tab, Tabs } from 'rspress/theme';
|
|
77
|
+
|
|
78
|
+
<PackageManagerTabs command="add @rsdoctor/core -D" />
|
|
79
|
+
|
|
80
|
+
### 2. 编写规则
|
|
81
|
+
|
|
82
|
+
编写规则需要先使用`defineRule`函数,它内部输入一个函数,此函数返回一个固定格式的对象。参考按照如下实例:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// src/rules/some-rule.ts
|
|
86
|
+
import { defineRule } from '@rsdoctor/core/rules';
|
|
87
|
+
|
|
88
|
+
const ruleTitle = 'check-rule';
|
|
89
|
+
const ruleConfig = {
|
|
90
|
+
// some rule configs
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const CheckRule = defineRule<typeof ruleTitle, config>(() => ({
|
|
94
|
+
meta: {
|
|
95
|
+
category: 'bundle', // rule category
|
|
96
|
+
severity: 'Warn', // rule severity
|
|
97
|
+
title: ruleTitle, // rule title
|
|
98
|
+
defaultConfig: {
|
|
99
|
+
// rule default config
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
check(ruleContext) {
|
|
103
|
+
// rule check...
|
|
104
|
+
},
|
|
105
|
+
}));
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
其中,`meta` 字段为此规则的固定配置和内容,`check` 字段为包含规则检查具体逻辑的回调,它们的类型如下。
|
|
109
|
+
|
|
110
|
+
#### meta 对象
|
|
111
|
+
|
|
112
|
+
meta 类型定义查看:[RuleMeta](#rulemeta)。
|
|
113
|
+
|
|
114
|
+
##### 属性含义
|
|
115
|
+
|
|
116
|
+
- meta
|
|
117
|
+
- category
|
|
118
|
+
- info: 定义规则分类:编译规则或构建打包规则。
|
|
119
|
+
- type: 'compile' | 'bundle'。
|
|
120
|
+
- title
|
|
121
|
+
- info:规则标题,用于在 Rsdoctor 报告页面中展示。
|
|
122
|
+
- type:string | 泛型,用户可通过泛型下传。
|
|
123
|
+
- severity
|
|
124
|
+
- info: 规则等级。
|
|
125
|
+
- type: 参考下方 ErrorLevel 类型。
|
|
126
|
+
- default: 'Warn'
|
|
127
|
+
- defaultConfig
|
|
128
|
+
- info:规则默认配置。自定义规则中可能需要特有的配置,defaultConfig 可用于配置默认的规则配置。
|
|
129
|
+
- type:泛型,用户可通过泛型定义。如上面示例。
|
|
130
|
+
- referenceUrl
|
|
131
|
+
- info: 规则文档链接。
|
|
132
|
+
- type: string。
|
|
133
|
+
|
|
134
|
+
#### check 函数
|
|
135
|
+
|
|
136
|
+
check 函数主要是用来做规则判断的,参数 `ruleContext` 是 Rsdoctor 在构建分析过程中所整合到的所有构建信息,类型定义如下。
|
|
137
|
+
可以在 `check` 函数的函数体内利用构建信息进行自定义的规则判断。判断后,如果规则检查出问题,可通过参数中的 `report` 方法进行上报,具体参见下一步。
|
|
138
|
+
|
|
139
|
+
##### CheckCallback 类型
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
type CheckCallback<Config = DefaultRuleConfig> = (
|
|
143
|
+
context: RuleCheckerContext<Config>,
|
|
144
|
+
) => void | Promise<void>;
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
[`RuleCheckerContext` 类型定义请查看详情](#rulecheckercontext)
|
|
148
|
+
|
|
149
|
+
##### 示例
|
|
150
|
+
|
|
151
|
+
如下实例是对 assets 资源的个数进行一个限制的自定义规则:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
// src/rules/some-rule.ts
|
|
155
|
+
const CheckRule = defineRule<typeof ruleTitle, config>(() => ({
|
|
156
|
+
// .....
|
|
157
|
+
|
|
158
|
+
check({ chunkGraph, report, ruleConfig }) {
|
|
159
|
+
const assets = chunkGraph.getAssets();
|
|
160
|
+
|
|
161
|
+
if (assets.length > ruleConfig.limit) {
|
|
162
|
+
report({
|
|
163
|
+
message: 'The count of assets is bigger than limit',
|
|
164
|
+
detail: {
|
|
165
|
+
type: 'link',
|
|
166
|
+
link: 'https://rsdoctor.dev/zh/guide/start/quick-start', // This link just for show case.
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
}));
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 3. 上报规则结果
|
|
175
|
+
|
|
176
|
+
上报错误需要使用`check` 回调函数的参数中的 `report` 方法,`report` 方法的参数主要是包含以下的几个部分:
|
|
177
|
+
|
|
178
|
+
- message:错误消息
|
|
179
|
+
- document:文件数据, 用于描述报错代码文件位置及代码位置。
|
|
180
|
+
- suggestions:规则建议。
|
|
181
|
+
- detail:详细信息,主要是提供给前端的额外数据。
|
|
182
|
+
|
|
183
|
+
详细类型定义查看:[ReportData](#reportdata)
|
|
184
|
+
|
|
185
|
+
### 4. 规则结果展示
|
|
186
|
+
|
|
187
|
+
`report` 函数会把自定义规则的错误信息传递给 compilation 的 errors 或 warnings,会在构建的时候在终端中输出构建规则结果提示,甚至中断构建。
|
|
188
|
+
同时,Rsdoctor 还有两种组件可以作为规则展示,详细的查看下方[展示组件](#%E5%B1%95%E7%A4%BA%E7%BB%84%E4%BB%B6)
|
|
189
|
+
|
|
190
|
+
- 基本规则警示组件
|
|
191
|
+
|
|
192
|
+
<img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/lognuvj/rsdoctor/docs/rule-1.jpeg" />
|
|
193
|
+
|
|
194
|
+
- 代码展示组件
|
|
195
|
+
|
|
196
|
+
<img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/lognuvj/rsdoctor/docs/rule-2.jpeg" />
|
|
197
|
+
|
|
198
|
+
## 展示组件
|
|
199
|
+
|
|
200
|
+
### 基本规则警示组件
|
|
201
|
+
|
|
202
|
+
- 组件类型
|
|
203
|
+
|
|
204
|
+
[LinkRule Type](#linkrulestoredata)
|
|
205
|
+
|
|
206
|
+
- 组件输入
|
|
207
|
+
|
|
208
|
+
- type
|
|
209
|
+
|
|
210
|
+
- 使用组件类型。
|
|
211
|
+
- value: 'link'。
|
|
212
|
+
|
|
213
|
+
- title
|
|
214
|
+
|
|
215
|
+
- 规则标题。
|
|
216
|
+
- type: string。
|
|
217
|
+
|
|
218
|
+
- description
|
|
219
|
+
|
|
220
|
+
- 规则描述。数据来源为 report 中的 message 或 detail.description:
|
|
221
|
+
```js
|
|
222
|
+
report({
|
|
223
|
+
message: 'The count of assets is bigger than limit',
|
|
224
|
+
detail: {
|
|
225
|
+
// ......
|
|
226
|
+
description: 'The count of assets is bigger than limit',
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
- type: string。
|
|
231
|
+
|
|
232
|
+
- level
|
|
233
|
+
|
|
234
|
+
- 规则级别。
|
|
235
|
+
- type:warn | error。
|
|
236
|
+
|
|
237
|
+
- link:
|
|
238
|
+
- 规则详情。数据来源为 detail.link:
|
|
239
|
+
```js
|
|
240
|
+
report({
|
|
241
|
+
detail: {
|
|
242
|
+
// ......
|
|
243
|
+
link: 'http://....',
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
- type:string。
|
|
248
|
+
|
|
249
|
+
- 示例
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
report({
|
|
253
|
+
message: 'The count of assets is bigger than limit',
|
|
254
|
+
detail: {
|
|
255
|
+
type: 'link',
|
|
256
|
+
link: 'https://rsdoctor.dev/zh/guide/start/quick-start', // This link just for show case.
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
- 组件展示
|
|
262
|
+
|
|
263
|
+
<img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/lognuvj/rsdoctor/docs/rule-1.jpeg" />
|
|
264
|
+
|
|
265
|
+
- 组件代码 [Code](https://github.com/web-infra-dev/rsdoctor/blob/main/packages/components/src/components/Alert/link.tsx)
|
|
266
|
+
|
|
267
|
+
### 代码展示组件
|
|
268
|
+
|
|
269
|
+
- 组件类型
|
|
270
|
+
|
|
271
|
+
[CodeViewRule Type](#codeviewrule)
|
|
272
|
+
|
|
273
|
+
- 组件输入
|
|
274
|
+
|
|
275
|
+
- type
|
|
276
|
+
|
|
277
|
+
- 使用组件类型。
|
|
278
|
+
- value: 'code-view'。
|
|
279
|
+
|
|
280
|
+
- title
|
|
281
|
+
|
|
282
|
+
- 规则标题。
|
|
283
|
+
- type: string。
|
|
284
|
+
|
|
285
|
+
- description
|
|
286
|
+
|
|
287
|
+
- 规则描述。数据来源为 report 中的 message 或 detail.description:
|
|
288
|
+
```js
|
|
289
|
+
report({
|
|
290
|
+
message: 'The count of assets is bigger than limit',
|
|
291
|
+
detail: {
|
|
292
|
+
// ......
|
|
293
|
+
description: 'The count of assets is bigger than limit',
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
- type: string。
|
|
298
|
+
|
|
299
|
+
- level
|
|
300
|
+
|
|
301
|
+
- 规则级别。
|
|
302
|
+
- type:warn | error。
|
|
303
|
+
|
|
304
|
+
- file
|
|
305
|
+
- 代码详情展示。
|
|
306
|
+
- [type](#codeviewrule):
|
|
307
|
+
- file: string, 代码文件地址。
|
|
308
|
+
- content: string, 代码内容。
|
|
309
|
+
- ranges: SourceRange, 代码行列范围。
|
|
310
|
+
|
|
311
|
+
- 示例
|
|
312
|
+
|
|
313
|
+
```js
|
|
314
|
+
const detail {
|
|
315
|
+
type: 'code-view',
|
|
316
|
+
file: {
|
|
317
|
+
path: document.path,
|
|
318
|
+
content: document.content,
|
|
319
|
+
ranges: [node.loc!],
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
report({
|
|
324
|
+
message,
|
|
325
|
+
document,
|
|
326
|
+
detail,
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
- [更多示例代码](https://github.com/web-infra-dev/rsdoctor/blob/main/packages/core/src/rules/rules/default-import-check/index.ts#L103)
|
|
332
|
+
|
|
333
|
+
- 组件展示
|
|
334
|
+
|
|
335
|
+
<img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/lognuvj/rsdoctor/docs/rule-2.jpeg" />
|
|
336
|
+
|
|
337
|
+
<img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/lognuvj/rsdoctor/docs/rule-3.jpeg" />
|
|
338
|
+
|
|
339
|
+
- 组件代码 [Code](https://github.com/web-infra-dev/rsdoctor/blob/main/packages/components/src/components/Alert/view.tsx)
|
|
340
|
+
|
|
341
|
+
## 类型定义
|
|
342
|
+
|
|
343
|
+
### RuleMeta
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
interface RuleMeta<
|
|
347
|
+
Config = DefaultRuleConfig,
|
|
348
|
+
Title extends DefaultRuleTitle = DefaultRuleTitle,
|
|
349
|
+
> {
|
|
350
|
+
title: Title;
|
|
351
|
+
category:
|
|
352
|
+
severity: ErrorLevel;
|
|
353
|
+
referenceUrl?: string;
|
|
354
|
+
defaultConfig?: Config;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** Error Level */
|
|
358
|
+
export enum ErrorLevel {
|
|
359
|
+
Ignore = 0,
|
|
360
|
+
Warn = 1,
|
|
361
|
+
Error = 2,
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### RuleCheckerContext
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
interface RuleCheckerContext<Config> {
|
|
369
|
+
/** 工程根目录 */
|
|
370
|
+
root: string;
|
|
371
|
+
/** 当前规则配置 */
|
|
372
|
+
ruleConfig: Config;
|
|
373
|
+
/** 工程配置 */
|
|
374
|
+
configs: ConfigData;
|
|
375
|
+
/** 构建错误 */
|
|
376
|
+
errors: Error[];
|
|
377
|
+
/** Chunk 图 */
|
|
378
|
+
chunkGraph: ChunkGraph;
|
|
379
|
+
/** 模块图 */
|
|
380
|
+
moduleGraph: ModuleGraph;
|
|
381
|
+
/** 依赖图 */
|
|
382
|
+
packageGraph: PackageGraph;
|
|
383
|
+
/** loader 数据 */
|
|
384
|
+
loader: LoaderData;
|
|
385
|
+
/**
|
|
386
|
+
* 上报错误
|
|
387
|
+
* @param {any} error - 错误数据
|
|
388
|
+
* @param {any} replacer - 替换原错误
|
|
389
|
+
*/
|
|
390
|
+
report(error: ReportData, replacer?: any): void;
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### ReportData
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
interface ReportData {
|
|
398
|
+
/** 错误消息 */
|
|
399
|
+
message: string;
|
|
400
|
+
/** 文件数据 */
|
|
401
|
+
document?: ReportDocument;
|
|
402
|
+
/** 诊断建议 */
|
|
403
|
+
suggestions?: Suggestion;
|
|
404
|
+
/**
|
|
405
|
+
* 详细信息
|
|
406
|
+
* - 主要是提供给前端的额外数据
|
|
407
|
+
*/
|
|
408
|
+
detail?: any;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** Error file information */
|
|
412
|
+
interface ReportDocument {
|
|
413
|
+
/** file path */
|
|
414
|
+
path: string;
|
|
415
|
+
/** Is it a transformed code */
|
|
416
|
+
isTransformed?: boolean;
|
|
417
|
+
/** code content */
|
|
418
|
+
content: string;
|
|
419
|
+
range: Range;
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### LinkRuleStoreData
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
interface BaseRuleStoreData extends Pick<RuleMessage, 'code' | 'category'> {
|
|
427
|
+
/**
|
|
428
|
+
* unique of error
|
|
429
|
+
*/
|
|
430
|
+
id: number | string;
|
|
431
|
+
/**
|
|
432
|
+
* title of alerts
|
|
433
|
+
*/
|
|
434
|
+
title: string;
|
|
435
|
+
/**
|
|
436
|
+
* description of alerts
|
|
437
|
+
*/
|
|
438
|
+
description?: string;
|
|
439
|
+
/**
|
|
440
|
+
* level of error
|
|
441
|
+
*/
|
|
442
|
+
level: 'warn' | 'error';
|
|
443
|
+
/**
|
|
444
|
+
* rule doc link
|
|
445
|
+
*/
|
|
446
|
+
link?: string;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
interface LinkRuleStoreData extends BaseRuleStoreData {
|
|
450
|
+
type: 'link';
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### CodeViewRule
|
|
455
|
+
|
|
456
|
+
```ts
|
|
457
|
+
interface CodeViewRuleStoreData extends BaseRuleStoreData {
|
|
458
|
+
type: 'code-view';
|
|
459
|
+
file: {
|
|
460
|
+
/**
|
|
461
|
+
* file path
|
|
462
|
+
*/
|
|
463
|
+
path: string;
|
|
464
|
+
/**
|
|
465
|
+
* the code content
|
|
466
|
+
*/
|
|
467
|
+
content: string;
|
|
468
|
+
/**
|
|
469
|
+
* fix highlight range in source
|
|
470
|
+
*/
|
|
471
|
+
ranges?: SourceRange[];
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/** Source code location */
|
|
476
|
+
interface SourcePosition {
|
|
477
|
+
line?: number;
|
|
478
|
+
column?: number;
|
|
479
|
+
index?: number;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/** Source code range */
|
|
483
|
+
interface SourceRange {
|
|
484
|
+
start: SourcePosition;
|
|
485
|
+
end?: SourcePosition;
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## 工具
|
|
490
|
+
|
|
491
|
+
### AST 处理
|
|
492
|
+
|
|
493
|
+
在进行规则检测分析时,对模块进行AST分析等操作是常见的。为了提供更多辅助功能,我们还提供了 `@rsdoctor/utils` 包中的 `@rsdoctor/utils/rule-utils`,其中包含了许多实用的工具函数和方法。
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
/** 这里包含了 AST 所有节点的类型定义 */
|
|
497
|
+
export type Node = /* SyntaxNode */;
|
|
498
|
+
|
|
499
|
+
export interface parser {
|
|
500
|
+
/** AST 迭代器 */
|
|
501
|
+
walk,
|
|
502
|
+
/**
|
|
503
|
+
* 编译代码
|
|
504
|
+
* - 输出根节点为`Node.Program`
|
|
505
|
+
*/
|
|
506
|
+
parse,
|
|
507
|
+
/**
|
|
508
|
+
* 编译接下来的首个表达式
|
|
509
|
+
* - 输出根节点为`Node.ExpressionStatement`
|
|
510
|
+
*/
|
|
511
|
+
parseExpressionAt,
|
|
512
|
+
/** 断言方法集 */
|
|
513
|
+
asserts,
|
|
514
|
+
/** 辅助方法集 */
|
|
515
|
+
utils,
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/** 文档类 */
|
|
519
|
+
export interface Document {
|
|
520
|
+
/** 获取文件位置在文本中的位移 */
|
|
521
|
+
positionAt!: (offset: number) => Position | undefined;
|
|
522
|
+
/** 获取位移点在文件的位置 */
|
|
523
|
+
offsetAt!: (position: Position) => number | undefined;
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
其中的 `asserts` 断言方法集,提供了所有 AST 节点的类型断言方法,`utils` 辅助方法集里提供了诸如判断某些语句的语义是否相同,获取 Import 节点等等常用的方法。
|
|
528
|
+
|
|
529
|
+
### 上报代码位置
|
|
530
|
+
|
|
531
|
+
有些错误需要提供代码的位置,所以需要提供`document`字段的内容。但是在这里有个很重要的区别,那就是每个模块实际上有两套代码,transformed 和 source,意为经过 loader 之后的代码和用户的原始代码,AST 实际上也是转换之后的代码格式。
|
|
532
|
+
为了给用户展示的方便,我们需要尽量使用原始代码,所以就需要用户在选中对应的 AST 节点之后,使用模块带有的 SourceMap 模块将位置信息转换到原始代码,如果模块因为某些特殊原因没有原始代码或者是 SourceMap,此时再使用转换后的代码/位置是比较合适的。一个比较典型的流程是这样的:
|
|
533
|
+
|
|
534
|
+
```ts
|
|
535
|
+
const module: SDK.ModuleInstance;
|
|
536
|
+
const node: Node.ImportDeclaration;
|
|
537
|
+
/** 默认类型为可选,实际上都是有值的 */
|
|
538
|
+
const transformedRange = node.loc!;
|
|
539
|
+
/** 若是模块的 SourceMap 不可用,则这个值为空 */
|
|
540
|
+
const sourceRange = module.getSourceRange(transformedRange);
|
|
541
|
+
/** 获取代码 */
|
|
542
|
+
const source = mod.getSource();
|
|
543
|
+
|
|
544
|
+
// 根据是否生成原始位置来判断使用哪个值
|
|
545
|
+
const range = (sourceRange ?? transformed) as Linter.Range;
|
|
546
|
+
const content = sourceRange ? source.source : source.transformed;
|
|
547
|
+
|
|
548
|
+
report({
|
|
549
|
+
document: {
|
|
550
|
+
path: module.path,
|
|
551
|
+
content,
|
|
552
|
+
range,
|
|
553
|
+
},
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## 数据上报
|
|
558
|
+
|
|
559
|
+
请跳转到[数据上报](./upload-data)进行查看
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# 数据上报
|
|
2
|
+
|
|
3
|
+
进行数据上报需要借助自定义拓展规则的接口,请先查看[自定义拓展规则](./rule-custom)。
|
|
4
|
+
|
|
5
|
+
自定义规则的方式还可以用于用户数据收集和上报,像自定义拓展规则一样的方式,只是在 check 函数中不进行 report 上报错误即可。例如:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// src/rules/upload-data.ts
|
|
9
|
+
import { defineRule } from '@rsdoctor/core/rules';
|
|
10
|
+
|
|
11
|
+
export const UploadData = defineRule(() => ({
|
|
12
|
+
meta: {
|
|
13
|
+
category: 'bundle',
|
|
14
|
+
severity: 'Warn',
|
|
15
|
+
title: 'upload-data',
|
|
16
|
+
defaultConfig: {
|
|
17
|
+
limit: 10,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
check({ chunkGraph, moduleGraph, ruleConfig }) {
|
|
21
|
+
// upload some data
|
|
22
|
+
Upload({ chunkGraph, moduleGraph });
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// rsbuild.config.ts
|
|
29
|
+
import { UploadData } from './rules/upload-data';
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
tools: {
|
|
33
|
+
bundlerChain: (chain) => {
|
|
34
|
+
chain.plugin('Rsdoctor').use(RsdoctorRspackPlugin, [
|
|
35
|
+
{
|
|
36
|
+
linter: {
|
|
37
|
+
level: 'Warn',
|
|
38
|
+
extends: [UploadData],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
]);
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsdoctor/docs",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/web-infra-dev/rsdoctor",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"rsbuild-plugin-open-graph": "1.0.0",
|
|
29
29
|
"rspress-plugin-font-open-sans": "^1.0.0",
|
|
30
30
|
"typescript": "^5.2.2",
|
|
31
|
-
"@rsdoctor/types": "0.3.
|
|
31
|
+
"@rsdoctor/types": "0.3.6"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"framer-motion": "^10.18.0",
|
|
File without changes
|
|
File without changes
|