@esmx/rspack 3.0.0-rc.44 → 3.0.0-rc.45

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.
Files changed (44) hide show
  1. package/dist/index.d.ts +2 -4
  2. package/dist/index.mjs +4 -4
  3. package/dist/{app.d.ts → rspack/app.d.ts} +41 -0
  4. package/dist/{app.mjs → rspack/app.mjs} +2 -4
  5. package/dist/rspack/build-target.d.ts +8 -0
  6. package/dist/rspack/chain-config.d.ts +7 -0
  7. package/dist/rspack/chain-config.mjs +133 -0
  8. package/dist/rspack/index.d.ts +3 -0
  9. package/dist/rspack/index.mjs +4 -0
  10. package/dist/{html-app.d.ts → rspack-html/index.d.ts} +1 -114
  11. package/dist/rspack-html/index.mjs +158 -0
  12. package/package.json +7 -6
  13. package/src/index.ts +6 -5
  14. package/src/{app.ts → rspack/app.ts} +49 -6
  15. package/src/rspack/build-target.ts +8 -0
  16. package/src/rspack/chain-config.ts +193 -0
  17. package/src/rspack/index.ts +8 -0
  18. package/src/rspack-html/index.ts +510 -0
  19. package/dist/build-target.d.ts +0 -8
  20. package/dist/html-app.mjs +0 -214
  21. package/src/build-target.ts +0 -8
  22. package/src/html-app.ts +0 -559
  23. /package/dist/{build-target.mjs → rspack/build-target.mjs} +0 -0
  24. /package/dist/{config.d.ts → rspack/config.d.ts} +0 -0
  25. /package/dist/{config.mjs → rspack/config.mjs} +0 -0
  26. /package/dist/{hmr-config.d.ts → rspack/hmr-config.d.ts} +0 -0
  27. /package/dist/{hmr-config.mjs → rspack/hmr-config.mjs} +0 -0
  28. /package/dist/{hot-fix.d.ts → rspack/hot-fix.d.ts} +0 -0
  29. /package/dist/{hot-fix.mjs → rspack/hot-fix.mjs} +0 -0
  30. /package/dist/{loader.d.ts → rspack/loader.d.ts} +0 -0
  31. /package/dist/{loader.mjs → rspack/loader.mjs} +0 -0
  32. /package/dist/{pack.d.ts → rspack/pack.d.ts} +0 -0
  33. /package/dist/{pack.mjs → rspack/pack.mjs} +0 -0
  34. /package/dist/{utils → rspack/utils}/index.d.ts +0 -0
  35. /package/dist/{utils → rspack/utils}/index.mjs +0 -0
  36. /package/dist/{utils → rspack/utils}/rsbuild.d.ts +0 -0
  37. /package/dist/{utils → rspack/utils}/rsbuild.mjs +0 -0
  38. /package/src/{config.ts → rspack/config.ts} +0 -0
  39. /package/src/{hmr-config.ts → rspack/hmr-config.ts} +0 -0
  40. /package/src/{hot-fix.ts → rspack/hot-fix.ts} +0 -0
  41. /package/src/{loader.ts → rspack/loader.ts} +0 -0
  42. /package/src/{pack.ts → rspack/pack.ts} +0 -0
  43. /package/src/{utils → rspack/utils}/index.ts +0 -0
  44. /package/src/{utils → rspack/utils}/rsbuild.ts +0 -0
@@ -0,0 +1,510 @@
1
+ import type { Esmx } from '@esmx/core';
2
+ import {
3
+ type LightningcssLoaderOptions,
4
+ type SwcLoaderOptions,
5
+ rspack
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
+ RSPACK_LOADER,
12
+ type RspackAppOptions,
13
+ createRspackApp
14
+ } from '../rspack';
15
+
16
+ export interface RspackHtmlAppOptions extends RspackAppOptions {
17
+ /**
18
+ * CSS 输出模式配置
19
+ *
20
+ * @default 根据环境自动选择:
21
+ * - 生产环境: 'css',将CSS输出到独立文件中,有利于缓存和并行加载
22
+ * - 开发环境: 'js',将CSS打包到JS中以支持热更新(HMR),实现样式的即时更新
23
+ *
24
+ * - 'css': 将 CSS 输出到独立的 CSS 文件中
25
+ * - 'js': 将 CSS 打包到 JS 文件中,运行时动态插入样式
26
+ * - false: 关闭默认的 CSS 处理配置,需要手动配置 loader 规则
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // 使用环境默认配置
31
+ * css: undefined
32
+ *
33
+ * // 强制输出到独立的 CSS 文件
34
+ * css: 'css'
35
+ *
36
+ * // 强制打包到 JS 中
37
+ * css: 'js'
38
+ *
39
+ * // 自定义 CSS 处理
40
+ * css: false
41
+ * ```
42
+ */
43
+ css?: 'css' | 'js' | false;
44
+
45
+ /**
46
+ * 自定义 loader 配置
47
+ *
48
+ * 允许替换默认的 loader 实现,可用于切换到特定框架的 loader
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * // 使用 Vue 的 style-loader
53
+ * loaders: {
54
+ * styleLoader: 'vue-style-loader'
55
+ * }
56
+ * ```
57
+ */
58
+ loaders?: Partial<Record<keyof typeof RSPACK_LOADER, string>>;
59
+
60
+ /**
61
+ * style-loader 配置项
62
+ *
63
+ * 用于配置样式注入方式,完整选项参考:
64
+ * https://github.com/webpack-contrib/style-loader
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * styleLoader: {
69
+ * injectType: 'singletonStyleTag',
70
+ * attributes: { id: 'app-styles' }
71
+ * }
72
+ * ```
73
+ */
74
+ styleLoader?: Record<string, any>;
75
+
76
+ /**
77
+ * css-loader 配置项
78
+ *
79
+ * 用于配置 CSS 模块化、URL 解析等,完整选项参考:
80
+ * https://github.com/webpack-contrib/css-loader
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * cssLoader: {
85
+ * modules: true,
86
+ * url: false
87
+ * }
88
+ * ```
89
+ */
90
+ cssLoader?: Record<string, any>;
91
+
92
+ /**
93
+ * less-loader 配置项
94
+ *
95
+ * 用于配置 Less 编译选项,完整选项参考:
96
+ * https://github.com/webpack-contrib/less-loader
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * lessLoader: {
101
+ * lessOptions: {
102
+ * javascriptEnabled: true,
103
+ * modifyVars: { '@primary-color': '#1DA57A' }
104
+ * }
105
+ * }
106
+ * ```
107
+ */
108
+ lessLoader?: Record<string, any>;
109
+
110
+ /**
111
+ * style-resources-loader 配置项
112
+ *
113
+ * 用于自动注入全局的样式资源,完整选项参考:
114
+ * https://github.com/yenshih/style-resources-loader
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * styleResourcesLoader: {
119
+ * patterns: [
120
+ * './src/styles/variables.less',
121
+ * './src/styles/mixins.less'
122
+ * ]
123
+ * }
124
+ * ```
125
+ */
126
+ styleResourcesLoader?: Record<string, any>;
127
+
128
+ /**
129
+ * SWC loader 配置项
130
+ *
131
+ * 用于配置 TypeScript/JavaScript 编译选项,完整选项参考:
132
+ * https://rspack.dev/guide/features/builtin-swc-loader
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * swcLoader: {
137
+ * jsc: {
138
+ * parser: {
139
+ * syntax: 'typescript',
140
+ * decorators: true
141
+ * },
142
+ * transform: {
143
+ * legacyDecorator: true
144
+ * }
145
+ * }
146
+ * }
147
+ * ```
148
+ */
149
+ swcLoader?: SwcLoaderOptions;
150
+
151
+ /**
152
+ * DefinePlugin 配置项
153
+ *
154
+ * 用于定义编译时的全局常量,支持针对不同构建目标设置不同的值
155
+ * 完整说明参考: https://rspack.dev/plugins/webpack/define-plugin
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * // 统一的值
160
+ * definePlugin: {
161
+ * 'process.env.APP_ENV': JSON.stringify('production')
162
+ * }
163
+ *
164
+ * // 针对不同构建目标的值
165
+ * definePlugin: {
166
+ * 'process.env.IS_SERVER': {
167
+ * server: 'true',
168
+ * client: 'false'
169
+ * }
170
+ * }
171
+ * ```
172
+ */
173
+ definePlugin?: Record<
174
+ string,
175
+ string | Partial<Record<BuildTarget, string>>
176
+ >;
177
+
178
+ /**
179
+ * 构建目标配置
180
+ *
181
+ * 用于设置代码的目标运行环境,影响代码的编译降级和 polyfill 注入
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * target: {
186
+ * // 浏览器构建目标
187
+ * web: ['chrome>=87', 'firefox>=78', 'safari>=14'],
188
+ * // Node.js 构建目标
189
+ * node: ['node>=16']
190
+ * }
191
+ * ```
192
+ */
193
+ target?: {
194
+ /**
195
+ * 浏览器构建目标
196
+ *
197
+ * @default ['chrome>=64', 'edge>=79', 'firefox>=67', 'safari>=11.1']
198
+ */
199
+ web?: string[];
200
+
201
+ /**
202
+ * Node.js 构建目标
203
+ *
204
+ * @default ['node>=24']
205
+ */
206
+ node?: string[];
207
+ };
208
+ }
209
+
210
+ export async function createRspackHtmlApp(
211
+ esmx: Esmx,
212
+ options?: RspackHtmlAppOptions
213
+ ) {
214
+ options = {
215
+ ...options,
216
+ target: {
217
+ web: ['chrome>=64', 'edge>=79', 'firefox>=67', 'safari>=11.1'],
218
+ node: ['node>=24'],
219
+ ...options?.target
220
+ },
221
+ css: options?.css ? options.css : esmx.isProd ? 'css' : 'js'
222
+ };
223
+ return createRspackApp(esmx, {
224
+ ...options,
225
+ chain(context) {
226
+ const { chain, buildTarget, esmx } = context;
227
+
228
+ chain.stats('errors-warnings');
229
+ chain.devtool(false);
230
+ chain.cache(false);
231
+
232
+ configureAssetRules(chain, esmx);
233
+
234
+ chain.module
235
+ .rule('json')
236
+ .test(/\.json$/i)
237
+ .type('json');
238
+
239
+ configureWorkerRule(chain, esmx, options);
240
+
241
+ configureTypeScriptRule(chain, buildTarget, options);
242
+
243
+ configureOptimization(chain, options);
244
+
245
+ chain.plugin('node-polyfill').use(NodePolyfillPlugin);
246
+
247
+ configureDefinePlugin(chain, buildTarget, options);
248
+
249
+ chain.resolve.extensions.clear().add('...').add('.ts');
250
+
251
+ configureCssRules(chain, esmx, options);
252
+
253
+ options?.chain?.(context);
254
+ }
255
+ });
256
+ }
257
+
258
+ function configureAssetRules(chain: RspackChain, esmx: Esmx): void {
259
+ chain.module
260
+ .rule('images')
261
+ .test(/\.(jpe?g|png|gif|bmp|webp|svg)$/i)
262
+ .type('asset/resource')
263
+ .set('generator', {
264
+ filename: filename(esmx, 'images')
265
+ });
266
+
267
+ chain.module
268
+ .rule('media')
269
+ .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)$/i)
270
+ .type('asset/resource')
271
+ .set('generator', {
272
+ filename: filename(esmx, 'media')
273
+ });
274
+
275
+ chain.module
276
+ .rule('fonts')
277
+ .test(/\.(woff|woff2|eot|ttf|otf)(\?.*)?$/i)
278
+ .type('asset/resource')
279
+ .set('generator', {
280
+ filename: filename(esmx, 'fonts')
281
+ });
282
+ }
283
+
284
+ function configureWorkerRule(
285
+ chain: RspackChain,
286
+ esmx: Esmx,
287
+ options: RspackHtmlAppOptions
288
+ ): void {
289
+ chain.module
290
+ .rule('worker')
291
+ .test(/\.worker\.(c|m)?(t|j)s$/i)
292
+ .use('worker-loader')
293
+ .loader(
294
+ options.loaders?.workerRspackLoader ??
295
+ RSPACK_LOADER.workerRspackLoader
296
+ )
297
+ .options({
298
+ esModule: false,
299
+ filename: `${esmx.name}/workers/[name].[contenthash]${esmx.isProd ? '.final' : ''}.js`
300
+ });
301
+ }
302
+
303
+ function configureTypeScriptRule(
304
+ chain: RspackChain,
305
+ buildTarget: BuildTarget,
306
+ options: RspackHtmlAppOptions
307
+ ): void {
308
+ chain.module
309
+ .rule('typescript')
310
+ .test(/\.(ts|mts)$/i)
311
+ .use('swc-loader')
312
+ .loader(
313
+ options.loaders?.builtinSwcLoader ?? RSPACK_LOADER.builtinSwcLoader
314
+ )
315
+ .options({
316
+ env: {
317
+ targets:
318
+ buildTarget === 'client'
319
+ ? options?.target?.web
320
+ : options?.target?.node,
321
+ ...options?.swcLoader?.env
322
+ },
323
+ jsc: {
324
+ parser: {
325
+ syntax: 'typescript',
326
+ ...options?.swcLoader?.jsc?.parser
327
+ },
328
+ ...options?.swcLoader?.jsc
329
+ },
330
+ ...options?.swcLoader
331
+ } as SwcLoaderOptions)
332
+ .end()
333
+ .type('javascript/auto');
334
+ }
335
+
336
+ function configureOptimization(
337
+ chain: RspackChain,
338
+ options: RspackHtmlAppOptions
339
+ ): void {
340
+ chain.optimization
341
+ .minimizer('swc-js-minimizer')
342
+ .use(rspack.SwcJsMinimizerRspackPlugin, [
343
+ {
344
+ minimizerOptions: {
345
+ format: {
346
+ comments: false
347
+ }
348
+ }
349
+ }
350
+ ]);
351
+
352
+ chain.optimization
353
+ .minimizer('lightningcss-minimizer')
354
+ .use(rspack.LightningCssMinimizerRspackPlugin, [
355
+ {
356
+ minimizerOptions: {
357
+ targets: options.target?.web,
358
+ errorRecovery: false
359
+ }
360
+ }
361
+ ]);
362
+ }
363
+
364
+ function configureDefinePlugin(
365
+ chain: RspackChain,
366
+ buildTarget: BuildTarget,
367
+ options: RspackHtmlAppOptions
368
+ ): void {
369
+ if (options.definePlugin) {
370
+ const defineOptions: Record<string, string> = {};
371
+ Object.entries(options.definePlugin).forEach(([name, value]) => {
372
+ const targetValue =
373
+ typeof value === 'string'
374
+ ? value
375
+ : value[buildTarget as keyof typeof value];
376
+ if (typeof targetValue === 'string' && name !== targetValue) {
377
+ defineOptions[name] = targetValue;
378
+ }
379
+ });
380
+
381
+ if (Object.keys(defineOptions).length) {
382
+ chain.plugin('define').use(rspack.DefinePlugin, [defineOptions]);
383
+ }
384
+ }
385
+ }
386
+
387
+ function configureCssRules(
388
+ chain: RspackChain,
389
+ esmx: Esmx,
390
+ options: RspackHtmlAppOptions
391
+ ): void {
392
+ if (options.css === false) {
393
+ return;
394
+ }
395
+
396
+ if (options.css === 'js') {
397
+ configureCssInJS(chain, esmx, options);
398
+ return;
399
+ }
400
+ configureCssExtract(chain, esmx, options);
401
+ }
402
+
403
+ function configureCssInJS(
404
+ chain: RspackChain,
405
+ esmx: Esmx,
406
+ options: RspackHtmlAppOptions
407
+ ): void {
408
+ chain.module
409
+ .rule('css')
410
+ .test(/\.css$/)
411
+ .use('style-loader')
412
+ .loader(options.loaders?.styleLoader ?? RSPACK_LOADER.styleLoader)
413
+ .options(options.styleLoader || {})
414
+ .end()
415
+ .use('css-loader')
416
+ .loader(options.loaders?.cssLoader ?? RSPACK_LOADER.cssLoader)
417
+ .options(options.cssLoader || {})
418
+ .end()
419
+ .use('lightning-css-loader')
420
+ .loader(
421
+ options.loaders?.lightningcssLoader ??
422
+ RSPACK_LOADER.lightningcssLoader
423
+ )
424
+ .options({
425
+ targets: options.target?.web ?? [],
426
+ minify: esmx.isProd
427
+ } as LightningcssLoaderOptions)
428
+ .end()
429
+ .type('javascript/auto');
430
+
431
+ const lessRule = chain.module
432
+ .rule('less')
433
+ .test(/\.less$/)
434
+ .use('style-loader')
435
+ .loader(options.loaders?.styleLoader ?? RSPACK_LOADER.styleLoader)
436
+ .options(options.styleLoader || {})
437
+ .end()
438
+ .use('css-loader')
439
+ .loader(options.loaders?.cssLoader ?? RSPACK_LOADER.cssLoader)
440
+ .options(options.cssLoader || {})
441
+ .end()
442
+ .use('lightning-css-loader')
443
+ .loader(
444
+ options.loaders?.lightningcssLoader ??
445
+ RSPACK_LOADER.lightningcssLoader
446
+ )
447
+ .options({
448
+ targets: options.target?.web ?? [],
449
+ minify: esmx.isProd
450
+ } as LightningcssLoaderOptions)
451
+ .end()
452
+ .use('less-loader')
453
+ .loader(options.loaders?.lessLoader ?? RSPACK_LOADER.lessLoader)
454
+ .options(options.lessLoader || {})
455
+ .end();
456
+
457
+ if (options.styleResourcesLoader) {
458
+ lessRule
459
+ .use('style-resources-loader')
460
+ .loader(
461
+ options.loaders?.styleResourcesLoader ??
462
+ RSPACK_LOADER.styleResourcesLoader
463
+ )
464
+ .options(options.styleResourcesLoader);
465
+ }
466
+
467
+ lessRule.type('javascript/auto');
468
+ }
469
+
470
+ function configureCssExtract(
471
+ chain: RspackChain,
472
+ esmx: Esmx,
473
+ options: RspackHtmlAppOptions
474
+ ): void {
475
+ chain.set('experiments', {
476
+ ...(chain.get('experiments') || {}),
477
+ css: true
478
+ });
479
+
480
+ const experiments = chain.get('experiments');
481
+ if (!experiments || !experiments.css) {
482
+ return;
483
+ }
484
+
485
+ const lessRule = chain.module
486
+ .rule('less')
487
+ .test(/\.less$/)
488
+ .use('less-loader')
489
+ .loader(options.loaders?.lessLoader ?? RSPACK_LOADER.lessLoader)
490
+ .options(options.lessLoader || {})
491
+ .end();
492
+
493
+ if (options.styleResourcesLoader) {
494
+ lessRule
495
+ .use('style-resources-loader')
496
+ .loader(
497
+ options.loaders?.styleResourcesLoader ??
498
+ RSPACK_LOADER.styleResourcesLoader
499
+ )
500
+ .options(options.styleResourcesLoader);
501
+ }
502
+
503
+ lessRule.type('css');
504
+ }
505
+
506
+ function filename(esmx: Esmx, name: string, ext = '[ext]') {
507
+ return esmx.isProd
508
+ ? `${name}/[name].[contenthash:8].final${ext}`
509
+ : `${name}/[path][name]${ext}`;
510
+ }
@@ -1,8 +0,0 @@
1
- /**
2
- * 构建目标环境类型
3
- * @description 定义了应用程序的构建目标环境,用于配置构建过程中的特定优化和功能
4
- * - node: 构建为 Node.js 环境运行的代码
5
- * - client: 构建为浏览器环境运行的代码
6
- * - server: 构建为服务端环境运行的代码
7
- */
8
- export type BuildTarget = 'node' | 'client' | 'server';