@esmx/rspack 3.0.0-rc.11 → 3.0.0-rc.111
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/LICENSE +1 -1
- package/README.md +48 -20
- package/README.zh-CN.md +57 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.mjs +4 -4
- package/dist/module-link/config.d.ts +5 -0
- package/dist/module-link/config.mjs +100 -0
- package/dist/module-link/config1.d.ts +3 -0
- package/dist/module-link/config1.mjs +16 -0
- package/dist/module-link/config2.d.ts +3 -0
- package/dist/module-link/config2.mjs +17 -0
- package/dist/module-link/index.d.ts +4 -0
- package/dist/module-link/index.mjs +8 -0
- package/dist/module-link/manifest-plugin.d.ts +14 -0
- package/dist/module-link/manifest-plugin.mjs +141 -0
- package/dist/module-link/parse.d.ts +2 -0
- package/dist/module-link/parse.mjs +24 -0
- package/dist/module-link/types.d.ts +25 -0
- package/dist/rspack/app.d.ts +183 -0
- package/dist/{app.mjs → rspack/app.mjs} +18 -46
- package/dist/rspack/build-target.d.ts +7 -0
- package/dist/rspack/build-target.mjs +0 -0
- package/dist/{config.d.ts → rspack/chain-config.d.ts} +3 -4
- package/dist/rspack/chain-config.mjs +113 -0
- package/dist/rspack/index.d.ts +3 -0
- package/dist/rspack/index.mjs +4 -0
- package/dist/rspack/loader.d.ts +9 -0
- package/dist/{loader.mjs → rspack/loader.mjs} +2 -22
- package/dist/rspack/pack.d.ts +9 -0
- package/dist/{pack.mjs → rspack/pack.mjs} +33 -25
- package/dist/rspack/pack.test.d.ts +1 -0
- package/dist/rspack/pack.test.mjs +180 -0
- package/dist/rspack/utils/rsbuild.d.ts +6 -0
- package/dist/{utils → rspack/utils}/rsbuild.mjs +7 -37
- package/dist/rspack-html/index.d.ts +168 -0
- package/dist/rspack-html/index.mjs +160 -0
- package/dist/rspack-html/target-setting.d.ts +17 -0
- package/dist/rspack-html/target-setting.mjs +31 -0
- package/dist/rspack-html/target-setting.test.d.ts +1 -0
- package/dist/rspack-html/target-setting.test.mjs +105 -0
- package/package.json +23 -21
- package/src/index.ts +7 -6
- package/src/module-link/config.ts +157 -0
- package/src/module-link/config1.ts +24 -0
- package/src/module-link/config2.ts +28 -0
- package/src/module-link/index.ts +19 -0
- package/src/module-link/manifest-plugin.ts +179 -0
- package/src/module-link/parse.ts +31 -0
- package/src/module-link/types.ts +31 -0
- package/src/{app.ts → rspack/app.ts} +104 -107
- package/src/rspack/build-target.ts +7 -0
- package/src/rspack/chain-config.ts +165 -0
- package/src/rspack/index.ts +8 -0
- package/src/{loader.ts → rspack/loader.ts} +3 -22
- package/src/rspack/pack.test.ts +215 -0
- package/src/rspack/pack.ts +101 -0
- package/src/{utils → rspack/utils}/rsbuild.ts +11 -40
- package/src/rspack-html/index.ts +495 -0
- package/src/rspack-html/target-setting.test.ts +123 -0
- package/src/rspack-html/target-setting.ts +52 -0
- package/dist/app.d.ts +0 -160
- package/dist/build-target.d.ts +0 -8
- package/dist/config.mjs +0 -142
- package/dist/html-app.d.ts +0 -299
- package/dist/html-app.mjs +0 -214
- package/dist/loader.d.ts +0 -30
- package/dist/pack.d.ts +0 -2
- package/dist/utils/rsbuild.d.ts +0 -12
- package/src/build-target.ts +0 -8
- package/src/config.ts +0 -171
- package/src/html-app.ts +0 -560
- package/src/pack.ts +0 -79
- /package/dist/{build-target.mjs → module-link/types.mjs} +0 -0
- /package/dist/{utils → rspack/utils}/index.d.ts +0 -0
- /package/dist/{utils → rspack/utils}/index.mjs +0 -0
- /package/src/{utils → rspack/utils}/index.ts +0 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import type { Esmx } from '@esmx/core';
|
|
2
|
+
import {
|
|
3
|
+
type LightningcssLoaderOptions,
|
|
4
|
+
rspack,
|
|
5
|
+
type SwcLoaderOptions
|
|
6
|
+
} from '@rspack/core';
|
|
7
|
+
import NodePolyfillPlugin from 'node-polyfill-webpack-plugin';
|
|
8
|
+
import type RspackChain from 'rspack-chain';
|
|
9
|
+
import {
|
|
10
|
+
type BuildTarget,
|
|
11
|
+
createRspackApp,
|
|
12
|
+
RSPACK_LOADER,
|
|
13
|
+
type RspackAppOptions
|
|
14
|
+
} from '../rspack';
|
|
15
|
+
import type { TargetSetting } from './target-setting';
|
|
16
|
+
import { getTargetSetting } from './target-setting';
|
|
17
|
+
|
|
18
|
+
export type { TargetSetting };
|
|
19
|
+
export interface RspackHtmlAppOptions extends RspackAppOptions {
|
|
20
|
+
/**
|
|
21
|
+
* CSS output mode configuration
|
|
22
|
+
*
|
|
23
|
+
* @default Automatically selected based on environment:
|
|
24
|
+
* - Production: 'css', outputs CSS to separate files for better caching and parallel loading
|
|
25
|
+
* - Development: 'js', bundles CSS into JS to support hot module replacement (HMR) for instant style updates
|
|
26
|
+
*
|
|
27
|
+
* - 'css': Output CSS to separate CSS files
|
|
28
|
+
* - 'js': Bundle CSS into JS files and dynamically inject styles at runtime
|
|
29
|
+
* - false: Disable default CSS processing configuration, requires manual loader rule configuration
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* // Use environment default configuration
|
|
34
|
+
* css: undefined
|
|
35
|
+
*
|
|
36
|
+
* // Force output to separate CSS files
|
|
37
|
+
* css: 'css'
|
|
38
|
+
*
|
|
39
|
+
* // Force bundle into JS
|
|
40
|
+
* css: 'js'
|
|
41
|
+
*
|
|
42
|
+
* // Custom CSS processing
|
|
43
|
+
* css: false
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
css?: 'css' | 'js' | false;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Custom loader configuration
|
|
50
|
+
*
|
|
51
|
+
* Allows replacing default loader implementations, useful for switching to framework-specific loaders
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // Use Vue's style-loader
|
|
56
|
+
* loaders: {
|
|
57
|
+
* styleLoader: 'vue-style-loader'
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
loaders?: Partial<Record<keyof typeof RSPACK_LOADER, string>>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Configure style injection method. For complete options, see:
|
|
65
|
+
* https://github.com/webpack-contrib/style-loader
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* styleLoader: {
|
|
70
|
+
* injectType: 'singletonStyleTag',
|
|
71
|
+
* attributes: { id: 'app-styles' }
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
styleLoader?: Record<string, any>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Configure CSS modules, URL resolution, etc. For complete options, see:
|
|
79
|
+
* https://github.com/webpack-contrib/css-loader
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* cssLoader: {
|
|
84
|
+
* modules: true,
|
|
85
|
+
* url: false
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
cssLoader?: Record<string, any>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Configure Less compilation options. For complete options, see:
|
|
93
|
+
* https://github.com/webpack-contrib/less-loader
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* lessLoader: {
|
|
98
|
+
* lessOptions: {
|
|
99
|
+
* javascriptEnabled: true,
|
|
100
|
+
* modifyVars: { '@primary-color': '#1DA57A' }
|
|
101
|
+
* }
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
lessLoader?: Record<string, any>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Automatically inject global style resources. For complete options, see:
|
|
109
|
+
* https://github.com/yenshih/style-resources-loader
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* styleResourcesLoader: {
|
|
114
|
+
* patterns: [
|
|
115
|
+
* './src/styles/variables.less',
|
|
116
|
+
* './src/styles/mixins.less'
|
|
117
|
+
* ]
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
styleResourcesLoader?: Record<string, any>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Configure TypeScript/JavaScript compilation options. For complete options, see:
|
|
125
|
+
* https://rspack.dev/guide/features/builtin-swc-loader
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* swcLoader: {
|
|
130
|
+
* jsc: {
|
|
131
|
+
* parser: {
|
|
132
|
+
* syntax: 'typescript',
|
|
133
|
+
* decorators: true
|
|
134
|
+
* },
|
|
135
|
+
* transform: {
|
|
136
|
+
* legacyDecorator: true
|
|
137
|
+
* }
|
|
138
|
+
* }
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
swcLoader?: SwcLoaderOptions;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Define compile-time global constants, supports setting different values for different build targets
|
|
146
|
+
* For complete documentation, see: https://rspack.dev/plugins/webpack/define-plugin
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* // Unified value
|
|
151
|
+
* definePlugin: {
|
|
152
|
+
* 'process.env.APP_ENV': JSON.stringify('production')
|
|
153
|
+
* }
|
|
154
|
+
*
|
|
155
|
+
* // Values for different build targets
|
|
156
|
+
* definePlugin: {
|
|
157
|
+
* 'process.env.IS_SERVER': {
|
|
158
|
+
* server: 'true',
|
|
159
|
+
* client: 'false'
|
|
160
|
+
* }
|
|
161
|
+
* }
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
definePlugin?: Record<
|
|
165
|
+
string,
|
|
166
|
+
string | Partial<Record<BuildTarget, string>>
|
|
167
|
+
>;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Set the target runtime environment for the code, affecting code compilation downgrading and polyfill injection
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* // Global compatible mode
|
|
175
|
+
* target: 'compatible'
|
|
176
|
+
*
|
|
177
|
+
* // Global modern mode
|
|
178
|
+
* target: 'modern'
|
|
179
|
+
*
|
|
180
|
+
* // Global custom targets
|
|
181
|
+
* target: ['chrome>=89', 'edge>=89', 'firefox>=108', 'safari>=16.4', 'node>=24']
|
|
182
|
+
*
|
|
183
|
+
* // Per-build-target configuration
|
|
184
|
+
* target: {
|
|
185
|
+
* client: 'modern',
|
|
186
|
+
* server: ['node>=24']
|
|
187
|
+
* }
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
target?: TargetSetting;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export async function createRspackHtmlApp(
|
|
194
|
+
esmx: Esmx,
|
|
195
|
+
options?: RspackHtmlAppOptions
|
|
196
|
+
) {
|
|
197
|
+
options = {
|
|
198
|
+
...options,
|
|
199
|
+
css: options?.css ? options.css : esmx.isProd ? 'css' : 'js'
|
|
200
|
+
};
|
|
201
|
+
return createRspackApp(esmx, {
|
|
202
|
+
...options,
|
|
203
|
+
chain(context) {
|
|
204
|
+
const { chain, buildTarget, esmx } = context;
|
|
205
|
+
|
|
206
|
+
chain.stats('errors-warnings');
|
|
207
|
+
chain.devtool(false);
|
|
208
|
+
chain.cache(false);
|
|
209
|
+
|
|
210
|
+
configureAssetRules(chain, esmx);
|
|
211
|
+
|
|
212
|
+
chain.module
|
|
213
|
+
.rule('json')
|
|
214
|
+
.test(/\.json$/i)
|
|
215
|
+
.type('json');
|
|
216
|
+
|
|
217
|
+
configureWorkerRule(chain, esmx, options);
|
|
218
|
+
|
|
219
|
+
configureTypeScriptRule(chain, buildTarget, options);
|
|
220
|
+
|
|
221
|
+
configureOptimization(chain, options);
|
|
222
|
+
|
|
223
|
+
chain.plugin('node-polyfill').use(NodePolyfillPlugin);
|
|
224
|
+
|
|
225
|
+
configureDefinePlugin(chain, buildTarget, options);
|
|
226
|
+
|
|
227
|
+
chain.resolve.extensions.clear().add('...').add('.ts');
|
|
228
|
+
|
|
229
|
+
configureCssRules(chain, esmx, options);
|
|
230
|
+
|
|
231
|
+
options?.chain?.(context);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function configureAssetRules(chain: RspackChain, esmx: Esmx): void {
|
|
237
|
+
chain.module
|
|
238
|
+
.rule('images')
|
|
239
|
+
.test(
|
|
240
|
+
/\.(png|jpg|jpeg|gif|svg|bmp|webp|ico|apng|avif|tif|tiff|jfif|pjpeg|pjp|cur)$/i
|
|
241
|
+
)
|
|
242
|
+
.type('asset/resource')
|
|
243
|
+
.set('generator', {
|
|
244
|
+
filename: filename(esmx, 'images')
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
chain.module
|
|
248
|
+
.rule('media')
|
|
249
|
+
.test(/\.(mp4|webm|ogg|mov)$/i)
|
|
250
|
+
.type('asset/resource')
|
|
251
|
+
.set('generator', {
|
|
252
|
+
filename: filename(esmx, 'media')
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
chain.module
|
|
256
|
+
.rule('audio')
|
|
257
|
+
.test(/\.(mp3|wav|flac|aac|m4a|opus)$/i)
|
|
258
|
+
.type('asset/resource')
|
|
259
|
+
.set('generator', {
|
|
260
|
+
filename: filename(esmx, 'audio')
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
chain.module
|
|
264
|
+
.rule('fonts')
|
|
265
|
+
.test(/\.(woff|woff2|eot|ttf|otf|ttc)(\?.*)?$/i)
|
|
266
|
+
.type('asset/resource')
|
|
267
|
+
.set('generator', {
|
|
268
|
+
filename: filename(esmx, 'fonts')
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function configureWorkerRule(
|
|
273
|
+
chain: RspackChain,
|
|
274
|
+
esmx: Esmx,
|
|
275
|
+
options: RspackHtmlAppOptions
|
|
276
|
+
): void {
|
|
277
|
+
chain.module
|
|
278
|
+
.rule('worker')
|
|
279
|
+
.test(/\.worker\.(c|m)?(t|j)s$/i)
|
|
280
|
+
.use('worker-loader')
|
|
281
|
+
.loader(
|
|
282
|
+
options.loaders?.workerRspackLoader ??
|
|
283
|
+
RSPACK_LOADER.workerRspackLoader
|
|
284
|
+
)
|
|
285
|
+
.options({
|
|
286
|
+
esModule: false,
|
|
287
|
+
filename: `${esmx.name}/workers/[name].[contenthash]${esmx.isProd ? '.final' : ''}.js`
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function configureTypeScriptRule(
|
|
292
|
+
chain: RspackChain,
|
|
293
|
+
buildTarget: BuildTarget,
|
|
294
|
+
options: RspackHtmlAppOptions
|
|
295
|
+
): void {
|
|
296
|
+
const targets = getTargetSetting(options?.target, buildTarget);
|
|
297
|
+
chain.module
|
|
298
|
+
.rule('typescript')
|
|
299
|
+
.test(/\.(ts|mts)$/i)
|
|
300
|
+
.use('swc-loader')
|
|
301
|
+
.loader(
|
|
302
|
+
options.loaders?.builtinSwcLoader ?? RSPACK_LOADER.builtinSwcLoader
|
|
303
|
+
)
|
|
304
|
+
.options({
|
|
305
|
+
env: {
|
|
306
|
+
targets,
|
|
307
|
+
...options?.swcLoader?.env
|
|
308
|
+
},
|
|
309
|
+
jsc: {
|
|
310
|
+
parser: {
|
|
311
|
+
syntax: 'typescript',
|
|
312
|
+
...options?.swcLoader?.jsc?.parser
|
|
313
|
+
},
|
|
314
|
+
...options?.swcLoader?.jsc
|
|
315
|
+
},
|
|
316
|
+
...options?.swcLoader
|
|
317
|
+
} as SwcLoaderOptions)
|
|
318
|
+
.end()
|
|
319
|
+
.type('javascript/auto');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function configureOptimization(
|
|
323
|
+
chain: RspackChain,
|
|
324
|
+
options: RspackHtmlAppOptions
|
|
325
|
+
): void {
|
|
326
|
+
chain.optimization
|
|
327
|
+
.minimizer('swc-js-minimizer')
|
|
328
|
+
.use(rspack.SwcJsMinimizerRspackPlugin, [
|
|
329
|
+
{
|
|
330
|
+
minimizerOptions: {
|
|
331
|
+
format: {
|
|
332
|
+
comments: false
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
]);
|
|
337
|
+
|
|
338
|
+
chain.optimization
|
|
339
|
+
.minimizer('lightningcss-minimizer')
|
|
340
|
+
.use(rspack.LightningCssMinimizerRspackPlugin, [
|
|
341
|
+
{
|
|
342
|
+
minimizerOptions: {
|
|
343
|
+
targets: getTargetSetting(options?.target, 'client'),
|
|
344
|
+
errorRecovery: false
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
]);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function configureDefinePlugin(
|
|
351
|
+
chain: RspackChain,
|
|
352
|
+
buildTarget: BuildTarget,
|
|
353
|
+
options: RspackHtmlAppOptions
|
|
354
|
+
): void {
|
|
355
|
+
if (options.definePlugin) {
|
|
356
|
+
const defineOptions: Record<string, string> = {};
|
|
357
|
+
Object.entries(options.definePlugin).forEach(([name, value]) => {
|
|
358
|
+
const targetValue =
|
|
359
|
+
typeof value === 'string'
|
|
360
|
+
? value
|
|
361
|
+
: value[buildTarget as keyof typeof value];
|
|
362
|
+
if (typeof targetValue === 'string' && name !== targetValue) {
|
|
363
|
+
defineOptions[name] = targetValue;
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
if (Object.keys(defineOptions).length) {
|
|
368
|
+
chain.plugin('define').use(rspack.DefinePlugin, [defineOptions]);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function configureCssRules(
|
|
374
|
+
chain: RspackChain,
|
|
375
|
+
esmx: Esmx,
|
|
376
|
+
options: RspackHtmlAppOptions
|
|
377
|
+
): void {
|
|
378
|
+
if (options.css === false) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (options.css === 'js') {
|
|
383
|
+
configureCssInJS(chain, esmx, options);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
configureCssExtract(chain, options);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function configureCssInJS(
|
|
390
|
+
chain: RspackChain,
|
|
391
|
+
esmx: Esmx,
|
|
392
|
+
options: RspackHtmlAppOptions
|
|
393
|
+
): void {
|
|
394
|
+
chain.module
|
|
395
|
+
.rule('css')
|
|
396
|
+
.test(/\.css$/)
|
|
397
|
+
.use('style-loader')
|
|
398
|
+
.loader(options.loaders?.styleLoader ?? RSPACK_LOADER.styleLoader)
|
|
399
|
+
.options(options.styleLoader ?? {})
|
|
400
|
+
.end()
|
|
401
|
+
.use('css-loader')
|
|
402
|
+
.loader(options.loaders?.cssLoader ?? RSPACK_LOADER.cssLoader)
|
|
403
|
+
.options(options.cssLoader ?? {})
|
|
404
|
+
.end()
|
|
405
|
+
.use('lightning-css-loader')
|
|
406
|
+
.loader(
|
|
407
|
+
options.loaders?.lightningcssLoader ??
|
|
408
|
+
RSPACK_LOADER.lightningcssLoader
|
|
409
|
+
)
|
|
410
|
+
.options({
|
|
411
|
+
targets: getTargetSetting(options?.target, 'client'),
|
|
412
|
+
minify: esmx.isProd
|
|
413
|
+
} as LightningcssLoaderOptions)
|
|
414
|
+
.end()
|
|
415
|
+
.type('javascript/auto');
|
|
416
|
+
|
|
417
|
+
const lessRule = chain.module
|
|
418
|
+
.rule('less')
|
|
419
|
+
.test(/\.less$/)
|
|
420
|
+
.use('style-loader')
|
|
421
|
+
.loader(options.loaders?.styleLoader ?? RSPACK_LOADER.styleLoader)
|
|
422
|
+
.options(options.styleLoader ?? {})
|
|
423
|
+
.end()
|
|
424
|
+
.use('css-loader')
|
|
425
|
+
.loader(options.loaders?.cssLoader ?? RSPACK_LOADER.cssLoader)
|
|
426
|
+
.options(options.cssLoader ?? {})
|
|
427
|
+
.end()
|
|
428
|
+
.use('lightning-css-loader')
|
|
429
|
+
.loader(
|
|
430
|
+
options.loaders?.lightningcssLoader ??
|
|
431
|
+
RSPACK_LOADER.lightningcssLoader
|
|
432
|
+
)
|
|
433
|
+
.options({
|
|
434
|
+
targets: getTargetSetting(options?.target, 'client'),
|
|
435
|
+
minify: esmx.isProd
|
|
436
|
+
} as LightningcssLoaderOptions)
|
|
437
|
+
.end()
|
|
438
|
+
.use('less-loader')
|
|
439
|
+
.loader(options.loaders?.lessLoader ?? RSPACK_LOADER.lessLoader)
|
|
440
|
+
.options(options.lessLoader ?? {})
|
|
441
|
+
.end();
|
|
442
|
+
|
|
443
|
+
if (options.styleResourcesLoader) {
|
|
444
|
+
lessRule
|
|
445
|
+
.use('style-resources-loader')
|
|
446
|
+
.loader(
|
|
447
|
+
options.loaders?.styleResourcesLoader ??
|
|
448
|
+
RSPACK_LOADER.styleResourcesLoader
|
|
449
|
+
)
|
|
450
|
+
.options(options.styleResourcesLoader);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
lessRule.type('javascript/auto');
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function configureCssExtract(
|
|
457
|
+
chain: RspackChain,
|
|
458
|
+
options: RspackHtmlAppOptions
|
|
459
|
+
): void {
|
|
460
|
+
chain.set('experiments', {
|
|
461
|
+
...(chain.get('experiments') ?? {}),
|
|
462
|
+
css: true
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
const experiments = chain.get('experiments');
|
|
466
|
+
if (!experiments || !experiments.css) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const lessRule = chain.module
|
|
471
|
+
.rule('less')
|
|
472
|
+
.test(/\.less$/)
|
|
473
|
+
.use('less-loader')
|
|
474
|
+
.loader(options.loaders?.lessLoader ?? RSPACK_LOADER.lessLoader)
|
|
475
|
+
.options(options.lessLoader ?? {})
|
|
476
|
+
.end();
|
|
477
|
+
|
|
478
|
+
if (options.styleResourcesLoader) {
|
|
479
|
+
lessRule
|
|
480
|
+
.use('style-resources-loader')
|
|
481
|
+
.loader(
|
|
482
|
+
options.loaders?.styleResourcesLoader ??
|
|
483
|
+
RSPACK_LOADER.styleResourcesLoader
|
|
484
|
+
)
|
|
485
|
+
.options(options.styleResourcesLoader);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
lessRule.type('css');
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function filename(esmx: Esmx, name: string, ext = '[ext]') {
|
|
492
|
+
return esmx.isProd
|
|
493
|
+
? `${name}/[name].[contenthash:8].final${ext}`
|
|
494
|
+
: `${name}/[path][name]${ext}`;
|
|
495
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { BuildTarget } from '../rspack';
|
|
3
|
+
import type { TargetSetting } from './target-setting';
|
|
4
|
+
import { getTargetSetting, PRESET_TARGETS } from './target-setting';
|
|
5
|
+
|
|
6
|
+
describe('getTargetSetting', () => {
|
|
7
|
+
const buildTargets: BuildTarget[] = ['client', 'server', 'node'];
|
|
8
|
+
|
|
9
|
+
describe('when setting is undefined', () => {
|
|
10
|
+
it('should return compatible preset for all build targets', () => {
|
|
11
|
+
buildTargets.forEach((buildTarget) => {
|
|
12
|
+
const result = getTargetSetting(undefined, buildTarget);
|
|
13
|
+
expect(result).toEqual(PRESET_TARGETS.compatible[buildTarget]);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('when setting is a string preset', () => {
|
|
19
|
+
it('should return compatible preset for all build targets', () => {
|
|
20
|
+
buildTargets.forEach((buildTarget) => {
|
|
21
|
+
const result = getTargetSetting('compatible', buildTarget);
|
|
22
|
+
expect(result).toEqual(PRESET_TARGETS.compatible[buildTarget]);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should return modern preset for all build targets', () => {
|
|
27
|
+
buildTargets.forEach((buildTarget) => {
|
|
28
|
+
const result = getTargetSetting('modern', buildTarget);
|
|
29
|
+
expect(result).toEqual(PRESET_TARGETS.modern[buildTarget]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('when setting is a custom array', () => {
|
|
35
|
+
const customTargets = ['chrome>=90', 'firefox>=80', 'safari>=14'];
|
|
36
|
+
|
|
37
|
+
it('should return the custom array for all build targets', () => {
|
|
38
|
+
buildTargets.forEach((buildTarget) => {
|
|
39
|
+
const result = getTargetSetting(customTargets, buildTarget);
|
|
40
|
+
expect(result).toEqual(customTargets);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('when setting is an object with specific build targets', () => {
|
|
46
|
+
it('should return specified preset for configured build targets', () => {
|
|
47
|
+
const setting: TargetSetting = {
|
|
48
|
+
client: 'modern',
|
|
49
|
+
server: 'compatible'
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
expect(getTargetSetting(setting, 'client')).toEqual(
|
|
53
|
+
PRESET_TARGETS.modern.client
|
|
54
|
+
);
|
|
55
|
+
expect(getTargetSetting(setting, 'server')).toEqual(
|
|
56
|
+
PRESET_TARGETS.compatible.server
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should return compatible preset for unconfigured build targets', () => {
|
|
61
|
+
const setting: TargetSetting = {
|
|
62
|
+
client: 'modern'
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
expect(getTargetSetting(setting, 'client')).toEqual(
|
|
66
|
+
PRESET_TARGETS.modern.client
|
|
67
|
+
);
|
|
68
|
+
expect(getTargetSetting(setting, 'server')).toEqual(
|
|
69
|
+
PRESET_TARGETS.compatible.server
|
|
70
|
+
);
|
|
71
|
+
expect(getTargetSetting(setting, 'node')).toEqual(
|
|
72
|
+
PRESET_TARGETS.compatible.node
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should return custom array for configured build targets', () => {
|
|
77
|
+
const customClientTargets = ['chrome>=90', 'firefox>=80'];
|
|
78
|
+
const customServerTargets = ['node>=18'];
|
|
79
|
+
const setting: TargetSetting = {
|
|
80
|
+
client: customClientTargets,
|
|
81
|
+
server: customServerTargets
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
expect(getTargetSetting(setting, 'client')).toEqual(
|
|
85
|
+
customClientTargets
|
|
86
|
+
);
|
|
87
|
+
expect(getTargetSetting(setting, 'server')).toEqual(
|
|
88
|
+
customServerTargets
|
|
89
|
+
);
|
|
90
|
+
expect(getTargetSetting(setting, 'node')).toEqual(
|
|
91
|
+
PRESET_TARGETS.compatible.node
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should handle mixed preset and custom configurations', () => {
|
|
96
|
+
const setting: TargetSetting = {
|
|
97
|
+
client: 'modern',
|
|
98
|
+
server: ['node>=18'],
|
|
99
|
+
node: 'compatible'
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
expect(getTargetSetting(setting, 'client')).toEqual(
|
|
103
|
+
PRESET_TARGETS.modern.client
|
|
104
|
+
);
|
|
105
|
+
expect(getTargetSetting(setting, 'server')).toEqual(['node>=18']);
|
|
106
|
+
expect(getTargetSetting(setting, 'node')).toEqual(
|
|
107
|
+
PRESET_TARGETS.compatible.node
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('edge cases', () => {
|
|
113
|
+
it('should handle empty custom array', () => {
|
|
114
|
+
const result = getTargetSetting([], 'client');
|
|
115
|
+
expect(result).toEqual([]);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should handle single item custom array', () => {
|
|
119
|
+
const result = getTargetSetting(['chrome>=90'], 'client');
|
|
120
|
+
expect(result).toEqual(['chrome>=90']);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { BuildTarget } from '../rspack/build-target';
|
|
2
|
+
|
|
3
|
+
export type TargetPreset = 'compatible' | 'modern';
|
|
4
|
+
|
|
5
|
+
export type TargetSpec = TargetPreset | string[];
|
|
6
|
+
|
|
7
|
+
export type TargetSetting =
|
|
8
|
+
| TargetSpec
|
|
9
|
+
| Partial<Record<BuildTarget, TargetSpec>>;
|
|
10
|
+
|
|
11
|
+
export const PRESET_TARGETS = {
|
|
12
|
+
compatible: {
|
|
13
|
+
client: ['chrome>=64', 'edge>=79', 'firefox>=67', 'safari>=11.1'],
|
|
14
|
+
server: ['node>=24'],
|
|
15
|
+
node: ['node>=24']
|
|
16
|
+
},
|
|
17
|
+
modern: {
|
|
18
|
+
client: ['chrome>=89', 'edge>=89', 'firefox>=108', 'safari>=16.4'],
|
|
19
|
+
server: ['node>=24'],
|
|
20
|
+
node: ['node>=24']
|
|
21
|
+
}
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
function resolveTargetSpec(
|
|
25
|
+
spec: TargetSpec,
|
|
26
|
+
buildTarget: BuildTarget
|
|
27
|
+
): string[] {
|
|
28
|
+
if (typeof spec === 'string') {
|
|
29
|
+
return [...PRESET_TARGETS[spec][buildTarget]];
|
|
30
|
+
}
|
|
31
|
+
return spec;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getTargetSetting(
|
|
35
|
+
setting: TargetSetting | undefined,
|
|
36
|
+
buildTarget: BuildTarget
|
|
37
|
+
): string[] {
|
|
38
|
+
if (!setting) {
|
|
39
|
+
return [...PRESET_TARGETS.compatible[buildTarget]];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (typeof setting === 'string' || Array.isArray(setting)) {
|
|
43
|
+
return resolveTargetSpec(setting, buildTarget);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const targetSpec = setting[buildTarget];
|
|
47
|
+
if (!targetSpec) {
|
|
48
|
+
return [...PRESET_TARGETS.compatible[buildTarget]];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return resolveTargetSpec(targetSpec, buildTarget);
|
|
52
|
+
}
|