Skip to content

Commit 05737c1

Browse files
authored
fix(rspack):optimize the builtin:swc-loader matching calculation (#170)
1 parent 8cd62f8 commit 05737c1

File tree

5 files changed

+413
-19
lines changed

5 files changed

+413
-19
lines changed

.changeset/polite-lamps-itch.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@rsdoctor/rspack-plugin': patch
3+
'@rsdoctor/types': patch
4+
'@rsdoctor/core': patch
5+
---
6+
7+
fix(rspack):optimize the builtin:swc-loader matching calculation

packages/core/src/build-utils/build/utils/loader.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getOptions } from 'loader-utils';
22
import path from 'path';
3-
import { omit } from 'lodash';
3+
import { omit, findIndex } from 'lodash';
44
import { Loader } from '@rsdoctor/utils/common';
55
import type { Common, Plugin } from '@rsdoctor/types';
66
import { Rule, SourceMapInput as WebpackSourceMapInput } from '../../../types';
@@ -167,6 +167,86 @@ export function mapEachRules<T extends Plugin.BuildRuleSetRule>(
167167
});
168168
}
169169

170+
function getLoaderNameMatch(_r: Plugin.BuildRuleSetRule, loaderName: string) {
171+
return (
172+
(typeof _r === 'object' &&
173+
typeof _r?.loader === 'string' &&
174+
_r.loader === loaderName) ||
175+
(typeof _r === 'string' && _r === loaderName)
176+
);
177+
}
178+
179+
// FIXME: Type BuildRuleSetRule maybe need optimize.
180+
export function changeBuiltinLoader<T extends Plugin.BuildRuleSetRule>(
181+
rules: T[],
182+
loaderName: string,
183+
appendRules: (rule: T, index: number) => T,
184+
): T[] {
185+
return rules.map((rule) => {
186+
if (!rule || typeof rule === 'string') return rule;
187+
188+
if (getLoaderNameMatch(rule, loaderName)) {
189+
const _rule = {
190+
...rule,
191+
use: [
192+
{
193+
loader: rule.loader,
194+
options: rule.options,
195+
},
196+
],
197+
loader: undefined,
198+
options: undefined,
199+
};
200+
return appendRules(_rule, 0);
201+
}
202+
203+
if (rule.use) {
204+
if (Array.isArray(rule.use)) {
205+
const _index = findIndex(rule.use, (_r) =>
206+
getLoaderNameMatch(_r as T, loaderName),
207+
);
208+
if (_index > -1) {
209+
return appendRules(rule, _index);
210+
}
211+
} else if (
212+
typeof rule.use === 'object' &&
213+
!Array.isArray(rule.use) &&
214+
typeof rule.use !== 'function'
215+
) {
216+
rule.use = [
217+
{
218+
...rule.use,
219+
},
220+
];
221+
return appendRules(rule, 0);
222+
}
223+
}
224+
225+
if ('oneOf' in rule && rule.oneOf) {
226+
return {
227+
...rule,
228+
oneOf: changeBuiltinLoader<T>(
229+
rule.oneOf as T[],
230+
loaderName,
231+
appendRules,
232+
),
233+
};
234+
}
235+
236+
if ('rules' in rule && rule.rules) {
237+
return {
238+
...rule,
239+
rules: changeBuiltinLoader<T>(
240+
rule.rules as T[],
241+
loaderName,
242+
appendRules,
243+
),
244+
};
245+
}
246+
return rule;
247+
});
248+
}
249+
170250
export function createLoaderContextTrap(
171251
this: Plugin.LoaderContext<Common.PlainObject>,
172252
final: (
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`test src/build/utils/loader.ts changeBuiltinLoader > changeBuiltinLoader() 1`] = `
4+
[
5+
{
6+
"test": /\\\\\\.less\\$/,
7+
"type": "css",
8+
"use": "less-loader",
9+
},
10+
{
11+
"test": /\\\\\\.module\\\\\\.less\\$/,
12+
"type": "css/module",
13+
"use": "less-loader",
14+
},
15+
{
16+
"test": /\\\\\\.svg\\$/,
17+
"use": "@svgr/webpack",
18+
},
19+
{
20+
"oneOf": [
21+
{
22+
"loader": undefined,
23+
"options": undefined,
24+
"type": "javascript/auto",
25+
"use": [
26+
{
27+
"loader": "probe",
28+
"options": {
29+
"loader": "builtin:swc-loader",
30+
"options": {
31+
"jsc": {
32+
"parser": {
33+
"jsx": true,
34+
"syntax": "typescript",
35+
},
36+
},
37+
"sourceMap": true,
38+
},
39+
"type": "end",
40+
},
41+
},
42+
{
43+
"loader": "builtin:swc-loader",
44+
"options": {
45+
"jsc": {
46+
"parser": {
47+
"jsx": true,
48+
"syntax": "typescript",
49+
},
50+
},
51+
"sourceMap": true,
52+
},
53+
},
54+
{
55+
"loader": "probe",
56+
"options": {
57+
"loader": "builtin:swc-loader",
58+
"options": {
59+
"jsc": {
60+
"parser": {
61+
"jsx": true,
62+
"syntax": "typescript",
63+
},
64+
},
65+
"sourceMap": true,
66+
},
67+
"type": "start",
68+
},
69+
},
70+
],
71+
},
72+
],
73+
"test": /\\\\\\.tsx\\$/,
74+
},
75+
{
76+
"rules": [
77+
{
78+
"loader": undefined,
79+
"options": undefined,
80+
"type": "javascript/auto",
81+
"use": [
82+
{
83+
"loader": "probe",
84+
"options": {
85+
"loader": "builtin:swc-loader",
86+
"options": {
87+
"jsc": {
88+
"parser": {
89+
"jsx": true,
90+
"syntax": "typescript",
91+
},
92+
},
93+
"sourceMap": true,
94+
},
95+
"type": "end",
96+
},
97+
},
98+
{
99+
"loader": "builtin:swc-loader",
100+
"options": {
101+
"jsc": {
102+
"parser": {
103+
"jsx": true,
104+
"syntax": "typescript",
105+
},
106+
},
107+
"sourceMap": true,
108+
},
109+
},
110+
{
111+
"loader": "probe",
112+
"options": {
113+
"loader": "builtin:swc-loader",
114+
"options": {
115+
"jsc": {
116+
"parser": {
117+
"jsx": true,
118+
"syntax": "typescript",
119+
},
120+
},
121+
"sourceMap": true,
122+
},
123+
"type": "start",
124+
},
125+
},
126+
],
127+
},
128+
],
129+
"test": /\\\\\\.tsx\\$/,
130+
},
131+
{
132+
"test": /\\\\\\.ts\\$/,
133+
"type": "javascript/auto",
134+
"use": [
135+
{
136+
"loader": "probe",
137+
"options": {
138+
"loader": "builtin:swc-loader",
139+
"options": {
140+
"jsc": {
141+
"externalHelpers": true,
142+
"parser": {
143+
"syntax": "typescript",
144+
},
145+
"preserveAllComments": false,
146+
},
147+
"sourceMap": true,
148+
},
149+
"type": "end",
150+
},
151+
},
152+
{
153+
"loader": "builtin:swc-loader",
154+
"options": {
155+
"jsc": {
156+
"externalHelpers": true,
157+
"parser": {
158+
"syntax": "typescript",
159+
},
160+
"preserveAllComments": false,
161+
},
162+
"sourceMap": true,
163+
},
164+
},
165+
{
166+
"loader": "probe",
167+
"options": {
168+
"loader": "builtin:swc-loader",
169+
"options": {
170+
"jsc": {
171+
"externalHelpers": true,
172+
"parser": {
173+
"syntax": "typescript",
174+
},
175+
"preserveAllComments": false,
176+
},
177+
"sourceMap": true,
178+
},
179+
"type": "start",
180+
},
181+
},
182+
],
183+
},
184+
{
185+
"test": /\\\\\\.svg\\$/,
186+
"type": "asset/resource",
187+
},
188+
]
189+
`;
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { changeBuiltinLoader } from '@/build-utils/build/utils/loader';
2+
import { describe, it, expect } from 'vitest';
3+
import { Plugin } from '@rsdoctor/types';
4+
5+
const rules = [
6+
{
7+
test: /\.less$/,
8+
use: 'less-loader',
9+
type: 'css',
10+
},
11+
{
12+
test: /\.module\.less$/,
13+
use: 'less-loader',
14+
type: 'css/module',
15+
},
16+
{
17+
test: /\.svg$/,
18+
use: '@svgr/webpack',
19+
},
20+
{
21+
test: /\.tsx$/,
22+
oneOf: [
23+
{
24+
loader: 'builtin:swc-loader',
25+
options: {
26+
sourceMap: true,
27+
jsc: {
28+
parser: {
29+
syntax: 'typescript',
30+
jsx: true,
31+
},
32+
},
33+
},
34+
type: 'javascript/auto',
35+
},
36+
],
37+
},
38+
{
39+
test: /\.tsx$/,
40+
rules: [
41+
{
42+
loader: 'builtin:swc-loader',
43+
options: {
44+
sourceMap: true,
45+
jsc: {
46+
parser: {
47+
syntax: 'typescript',
48+
jsx: true,
49+
},
50+
},
51+
},
52+
type: 'javascript/auto',
53+
},
54+
],
55+
},
56+
{
57+
test: /\.ts$/,
58+
use: {
59+
loader: 'builtin:swc-loader',
60+
options: {
61+
sourceMap: true,
62+
jsc: {
63+
parser: {
64+
syntax: 'typescript',
65+
},
66+
externalHelpers: true,
67+
preserveAllComments: false,
68+
},
69+
},
70+
},
71+
type: 'javascript/auto',
72+
},
73+
{
74+
test: /\.svg$/,
75+
type: 'asset/resource',
76+
},
77+
];
78+
79+
const appendRule = (rule: Plugin.RuleSetRule, index: number) => {
80+
if ('use' in rule && Array.isArray(rule.use)) {
81+
const _builtinRule = rule.use[index] as Plugin.RuleSetRule;
82+
const _options =
83+
typeof _builtinRule.options === 'string' ? {} : { ..._builtinRule };
84+
rule.use.splice(index, 0, {
85+
loader: 'probe',
86+
options: { ..._options, type: 'end' },
87+
});
88+
rule.use.splice(index + 2, 0, {
89+
loader: 'probe',
90+
options: { ..._options, type: 'start' },
91+
});
92+
}
93+
return rule;
94+
};
95+
describe('test src/build/utils/loader.ts changeBuiltinLoader', () => {
96+
it('changeBuiltinLoader()', () => {
97+
expect(
98+
changeBuiltinLoader(rules, 'builtin:swc-loader', appendRule),
99+
).toMatchSnapshot();
100+
});
101+
});

0 commit comments

Comments
 (0)