@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.
Files changed (76) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +48 -20
  3. package/README.zh-CN.md +57 -0
  4. package/dist/index.d.ts +2 -4
  5. package/dist/index.mjs +4 -4
  6. package/dist/module-link/config.d.ts +5 -0
  7. package/dist/module-link/config.mjs +100 -0
  8. package/dist/module-link/config1.d.ts +3 -0
  9. package/dist/module-link/config1.mjs +16 -0
  10. package/dist/module-link/config2.d.ts +3 -0
  11. package/dist/module-link/config2.mjs +17 -0
  12. package/dist/module-link/index.d.ts +4 -0
  13. package/dist/module-link/index.mjs +8 -0
  14. package/dist/module-link/manifest-plugin.d.ts +14 -0
  15. package/dist/module-link/manifest-plugin.mjs +141 -0
  16. package/dist/module-link/parse.d.ts +2 -0
  17. package/dist/module-link/parse.mjs +24 -0
  18. package/dist/module-link/types.d.ts +25 -0
  19. package/dist/rspack/app.d.ts +183 -0
  20. package/dist/{app.mjs → rspack/app.mjs} +18 -46
  21. package/dist/rspack/build-target.d.ts +7 -0
  22. package/dist/rspack/build-target.mjs +0 -0
  23. package/dist/{config.d.ts → rspack/chain-config.d.ts} +3 -4
  24. package/dist/rspack/chain-config.mjs +113 -0
  25. package/dist/rspack/index.d.ts +3 -0
  26. package/dist/rspack/index.mjs +4 -0
  27. package/dist/rspack/loader.d.ts +9 -0
  28. package/dist/{loader.mjs → rspack/loader.mjs} +2 -22
  29. package/dist/rspack/pack.d.ts +9 -0
  30. package/dist/{pack.mjs → rspack/pack.mjs} +33 -25
  31. package/dist/rspack/pack.test.d.ts +1 -0
  32. package/dist/rspack/pack.test.mjs +180 -0
  33. package/dist/rspack/utils/rsbuild.d.ts +6 -0
  34. package/dist/{utils → rspack/utils}/rsbuild.mjs +7 -37
  35. package/dist/rspack-html/index.d.ts +168 -0
  36. package/dist/rspack-html/index.mjs +160 -0
  37. package/dist/rspack-html/target-setting.d.ts +17 -0
  38. package/dist/rspack-html/target-setting.mjs +31 -0
  39. package/dist/rspack-html/target-setting.test.d.ts +1 -0
  40. package/dist/rspack-html/target-setting.test.mjs +105 -0
  41. package/package.json +23 -21
  42. package/src/index.ts +7 -6
  43. package/src/module-link/config.ts +157 -0
  44. package/src/module-link/config1.ts +24 -0
  45. package/src/module-link/config2.ts +28 -0
  46. package/src/module-link/index.ts +19 -0
  47. package/src/module-link/manifest-plugin.ts +179 -0
  48. package/src/module-link/parse.ts +31 -0
  49. package/src/module-link/types.ts +31 -0
  50. package/src/{app.ts → rspack/app.ts} +104 -107
  51. package/src/rspack/build-target.ts +7 -0
  52. package/src/rspack/chain-config.ts +165 -0
  53. package/src/rspack/index.ts +8 -0
  54. package/src/{loader.ts → rspack/loader.ts} +3 -22
  55. package/src/rspack/pack.test.ts +215 -0
  56. package/src/rspack/pack.ts +101 -0
  57. package/src/{utils → rspack/utils}/rsbuild.ts +11 -40
  58. package/src/rspack-html/index.ts +495 -0
  59. package/src/rspack-html/target-setting.test.ts +123 -0
  60. package/src/rspack-html/target-setting.ts +52 -0
  61. package/dist/app.d.ts +0 -160
  62. package/dist/build-target.d.ts +0 -8
  63. package/dist/config.mjs +0 -142
  64. package/dist/html-app.d.ts +0 -299
  65. package/dist/html-app.mjs +0 -214
  66. package/dist/loader.d.ts +0 -30
  67. package/dist/pack.d.ts +0 -2
  68. package/dist/utils/rsbuild.d.ts +0 -12
  69. package/src/build-target.ts +0 -8
  70. package/src/config.ts +0 -171
  71. package/src/html-app.ts +0 -560
  72. package/src/pack.ts +0 -79
  73. /package/dist/{build-target.mjs → module-link/types.mjs} +0 -0
  74. /package/dist/{utils → rspack/utils}/index.d.ts +0 -0
  75. /package/dist/{utils → rspack/utils}/index.mjs +0 -0
  76. /package/src/{utils → rspack/utils}/index.ts +0 -0
@@ -0,0 +1,215 @@
1
+ import type { ManifestJsonExports } from '@esmx/core';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { contentHash, generateExports } from './pack';
4
+
5
+ describe('generateExports', () => {
6
+ it('should generate exports with both client and server files', () => {
7
+ const clientExports: ManifestJsonExports = {
8
+ 'src/entry.client': {
9
+ file: 'src/entry.client.95f6085b.final.mjs',
10
+ name: 'src/entry.client',
11
+ pkg: true,
12
+ identifier: 'ssr-vue2-remote/src/entry.client'
13
+ },
14
+ 'src/components/index': {
15
+ file: 'src/components/index.a73d6772.final.mjs',
16
+ name: 'src/components/index',
17
+ pkg: true,
18
+ identifier: 'ssr-vue2-remote/src/components/index'
19
+ }
20
+ };
21
+
22
+ const serverExports: ManifestJsonExports = {
23
+ 'src/entry.server': {
24
+ file: 'src/entry.server.b85ed2ff.final.mjs',
25
+ name: 'src/entry.server',
26
+ pkg: true,
27
+ identifier: 'ssr-vue2-remote/src/entry.server'
28
+ },
29
+ 'src/components/index': {
30
+ file: 'src/components/index.12b57db5.final.mjs',
31
+ name: 'src/components/index',
32
+ pkg: true,
33
+ identifier: 'ssr-vue2-remote/src/components/index'
34
+ }
35
+ };
36
+
37
+ const result = generateExports({
38
+ client: clientExports,
39
+ server: serverExports
40
+ });
41
+
42
+ expect(result).toEqual({
43
+ './src/entry.client':
44
+ './client/src/entry.client.95f6085b.final.mjs',
45
+ './src/entry.server':
46
+ './server/src/entry.server.b85ed2ff.final.mjs',
47
+ './src/components/index': {
48
+ default: './server/src/components/index.12b57db5.final.mjs',
49
+ browser: './client/src/components/index.a73d6772.final.mjs'
50
+ }
51
+ });
52
+ });
53
+
54
+ it('should merge with existing exports', () => {
55
+ const clientExports: ManifestJsonExports = {
56
+ index: {
57
+ file: 'index.js',
58
+ name: 'index',
59
+ pkg: true,
60
+ identifier: 'index'
61
+ }
62
+ };
63
+
64
+ const serverExports: ManifestJsonExports = {
65
+ index: {
66
+ file: 'index.js',
67
+ name: 'index',
68
+ pkg: true,
69
+ identifier: 'index'
70
+ }
71
+ };
72
+
73
+ const existingExports = {
74
+ './custom': './custom.js'
75
+ };
76
+
77
+ const result = generateExports({
78
+ client: clientExports,
79
+ server: serverExports,
80
+ base: existingExports
81
+ });
82
+
83
+ expect(result).toEqual({
84
+ './custom': './custom.js',
85
+ '.': {
86
+ default: './server/index.js',
87
+ browser: './client/index.js'
88
+ }
89
+ });
90
+ });
91
+
92
+ it('should handle empty exports', () => {
93
+ const clientExports: ManifestJsonExports = {};
94
+ const serverExports: ManifestJsonExports = {};
95
+
96
+ const result = generateExports({
97
+ client: clientExports,
98
+ server: serverExports
99
+ });
100
+
101
+ expect(result).toEqual({});
102
+ });
103
+
104
+ it('should handle only client exports', () => {
105
+ const clientExports: ManifestJsonExports = {
106
+ utils: {
107
+ file: 'utils.js',
108
+ name: 'utils',
109
+ pkg: true,
110
+ identifier: 'utils'
111
+ }
112
+ };
113
+
114
+ const serverExports: ManifestJsonExports = {};
115
+
116
+ const result = generateExports({
117
+ client: clientExports,
118
+ server: serverExports
119
+ });
120
+
121
+ expect(result).toEqual({
122
+ './utils': './client/utils.js'
123
+ });
124
+ });
125
+
126
+ it('should handle only server exports', () => {
127
+ const clientExports: ManifestJsonExports = {};
128
+
129
+ const serverExports: ManifestJsonExports = {
130
+ api: {
131
+ file: 'api.js',
132
+ name: 'api',
133
+ pkg: true,
134
+ identifier: 'api'
135
+ }
136
+ };
137
+
138
+ const result = generateExports({
139
+ client: clientExports,
140
+ server: serverExports
141
+ });
142
+
143
+ expect(result).toEqual({
144
+ './api': './server/api.js'
145
+ });
146
+ });
147
+
148
+ it('should handle index export correctly', () => {
149
+ const clientExports: ManifestJsonExports = {
150
+ index: {
151
+ file: 'index.js',
152
+ name: 'index',
153
+ pkg: true,
154
+ identifier: 'index'
155
+ }
156
+ };
157
+
158
+ const serverExports: ManifestJsonExports = {
159
+ index: {
160
+ file: 'index.js',
161
+ name: 'index',
162
+ pkg: true,
163
+ identifier: 'index'
164
+ }
165
+ };
166
+
167
+ const result = generateExports({
168
+ client: clientExports,
169
+ server: serverExports
170
+ });
171
+
172
+ expect(result).toEqual({
173
+ '.': {
174
+ default: './server/index.js',
175
+ browser: './client/index.js'
176
+ }
177
+ });
178
+ });
179
+ });
180
+
181
+ describe('contentHash', () => {
182
+ it('should generate SHA256 hash for buffer', () => {
183
+ const buffer = Buffer.from('test content');
184
+ const result = contentHash(buffer);
185
+
186
+ expect(result).toMatch(/^sha256-[a-f0-9]{64}$/);
187
+ expect(result).toBe(
188
+ 'sha256-6ae8a75555209fd6c44157c0aed8016e763ff435a19cf186f76863140143ff72'
189
+ );
190
+ });
191
+
192
+ it('should use custom algorithm when provided', () => {
193
+ const buffer = Buffer.from('test content');
194
+ const result = contentHash(buffer, 'md5');
195
+
196
+ expect(result).toMatch(/^md5-[a-f0-9]{32}$/);
197
+ expect(result).toBe('md5-9473fdd0d880a43c21b7778d34872157');
198
+ });
199
+
200
+ it('should handle empty buffer', () => {
201
+ const buffer = Buffer.from('');
202
+ const result = contentHash(buffer);
203
+
204
+ expect(result).toBe(
205
+ 'sha256-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
206
+ );
207
+ });
208
+
209
+ it('should handle binary data', () => {
210
+ const buffer = Buffer.from([0x00, 0x01, 0x02, 0x03, 0xff]);
211
+ const result = contentHash(buffer);
212
+
213
+ expect(result).toMatch(/^sha256-[a-f0-9]{64}$/);
214
+ });
215
+ });
@@ -0,0 +1,101 @@
1
+ import crypto from 'node:crypto';
2
+ import type { Esmx, ManifestJson } from '@esmx/core';
3
+ import Arborist from '@npmcli/arborist';
4
+ import pacote from 'pacote';
5
+
6
+ export async function pack(esmx: Esmx): Promise<boolean> {
7
+ const { packConfig } = esmx;
8
+
9
+ const pkgJson = await packConfig.packageJson(
10
+ esmx,
11
+ await buildPackageJson(esmx)
12
+ );
13
+ esmx.writeSync(
14
+ esmx.resolvePath('dist/package.json'),
15
+ JSON.stringify(pkgJson, null, 4)
16
+ );
17
+
18
+ if (!packConfig.enable) {
19
+ return true;
20
+ }
21
+
22
+ await packConfig.onBefore(esmx, pkgJson);
23
+
24
+ const data = await pacote.tarball(esmx.resolvePath('dist'), {
25
+ Arborist
26
+ });
27
+ const hash = contentHash(data);
28
+ packConfig.outputs.forEach((file) => {
29
+ const tgz = esmx.resolvePath('./', file);
30
+ const txt = tgz.replace(/\.tgz$/, '.txt');
31
+ esmx.writeSync(tgz, data);
32
+ esmx.writeSync(txt, hash);
33
+ });
34
+
35
+ await packConfig.onAfter(esmx, pkgJson, data);
36
+ return true;
37
+ }
38
+
39
+ export interface GenerateExportsOptions {
40
+ client: ManifestJson['exports'];
41
+ server: ManifestJson['exports'];
42
+ base?: Record<string, unknown>;
43
+ }
44
+
45
+ export function generateExports(
46
+ options: GenerateExportsOptions
47
+ ): Record<string, unknown> {
48
+ const { client, server, base = {} } = options;
49
+ const exports: Record<string, unknown> = { ...base };
50
+
51
+ const set = new Set([...Object.keys(client), ...Object.keys(server)]);
52
+
53
+ set.forEach((name) => {
54
+ const clientExport = client[name];
55
+ const serverExport = server[name];
56
+ const exportName = name === 'index' ? '.' : `./${name}`;
57
+
58
+ if (clientExport && serverExport) {
59
+ exports[exportName] = {
60
+ default: `./server/${serverExport.file}`,
61
+ browser: `./client/${clientExport.file}`
62
+ };
63
+ } else if (clientExport) {
64
+ exports[exportName] = `./client/${clientExport.file}`;
65
+ } else if (serverExport) {
66
+ exports[exportName] = `./server/${serverExport.file}`;
67
+ }
68
+ });
69
+
70
+ return exports;
71
+ }
72
+
73
+ async function buildPackageJson(esmx: Esmx): Promise<Record<string, any>> {
74
+ const [clientJson, serverJson, curJson] = await Promise.all([
75
+ esmx.readJson<ManifestJson>(
76
+ esmx.resolvePath('dist/client/manifest.json')
77
+ ),
78
+ esmx.readJson<ManifestJson>(
79
+ esmx.resolvePath('dist/server/manifest.json')
80
+ ),
81
+ esmx.readJson(esmx.resolvePath('package.json'))
82
+ ]);
83
+
84
+ const exports = generateExports({
85
+ client: clientJson.exports,
86
+ server: serverJson.exports,
87
+ base: curJson?.exports
88
+ });
89
+
90
+ const buildJson: Record<string, any> = {
91
+ ...curJson,
92
+ exports
93
+ };
94
+ return buildJson;
95
+ }
96
+
97
+ export function contentHash(buffer: Buffer, algorithm = 'sha256') {
98
+ const hash = crypto.createHash(algorithm);
99
+ hash.update(buffer);
100
+ return `${algorithm}-${hash.digest('hex')}`;
101
+ }
@@ -1,5 +1,9 @@
1
1
  import { styleText } from 'node:util';
2
- import { type Compiler, type RspackOptions, rspack } from '@rspack/core';
2
+ import { type RspackOptions, rspack } from '@rspack/core';
3
+
4
+ function showError(message: string) {
5
+ console.error(styleText('red', message));
6
+ }
3
7
 
4
8
  export function createRsBuild(options: RspackOptions[]) {
5
9
  const multiCompiler = rspack(options);
@@ -11,19 +15,20 @@ export function createRsBuild(options: RspackOptions[]) {
11
15
  return new Promise<boolean>((resolve) => {
12
16
  multiCompiler.run((err, stats) => {
13
17
  if (err) {
18
+ showError(err.message);
14
19
  return resolve(false);
15
20
  }
16
21
  if (stats?.hasErrors()) {
17
22
  stats
18
23
  .toJson({ errors: true })
19
24
  ?.errors?.forEach((err) => {
20
- console.log(styleText('red', err.message));
25
+ showError(err.message);
21
26
  });
22
27
  return resolve(false);
23
28
  }
24
29
  multiCompiler.close((err) => {
25
30
  if (err) {
26
- console.log(styleText('red', err.message));
31
+ showError(err.message);
27
32
  return resolve(false);
28
33
  }
29
34
  process.nextTick(() => {
@@ -36,7 +41,7 @@ export function createRsBuild(options: RspackOptions[]) {
36
41
  watch() {
37
42
  const watching = multiCompiler.watch({}, (err, stats) => {
38
43
  if (err) {
39
- console.error(err);
44
+ console.log(styleText('red', err.message));
40
45
  return;
41
46
  }
42
47
  if (stats?.hasErrors()) {
@@ -46,7 +51,7 @@ export function createRsBuild(options: RspackOptions[]) {
46
51
  }
47
52
  });
48
53
 
49
- // 监听进程信号,确保优雅退出
54
+ // Listen to process signals to ensure graceful shutdown
50
55
  const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'] satisfies string[];
51
56
  signals.forEach((signal) => {
52
57
  process.on(signal, () => {
@@ -56,7 +61,7 @@ export function createRsBuild(options: RspackOptions[]) {
56
61
  });
57
62
  });
58
63
 
59
- // 监听未捕获的异常和 Promise 拒绝
64
+ // Listen to uncaught exceptions and Promise rejections
60
65
  process.on('uncaughtException', handleExit);
61
66
  process.on('unhandledRejection', handleExit);
62
67
 
@@ -69,37 +74,3 @@ export function createRsBuild(options: RspackOptions[]) {
69
74
  }
70
75
  };
71
76
  }
72
-
73
- export class RsBuild {
74
- private compiler: Compiler;
75
- public constructor(options: RspackOptions) {
76
- this.compiler = rspack(options);
77
- }
78
- public async build() {
79
- return new Promise<boolean>((resolve) => {
80
- this.compiler.run((err, stats) => {
81
- if (err) {
82
- return resolve(false);
83
- }
84
- if (stats?.hasErrors()) {
85
- stats.toJson({ errors: true })?.errors?.forEach((err) => {
86
- console.error(err);
87
- });
88
- return resolve(false);
89
- }
90
- this.compiler.close((err) => {
91
- if (err) {
92
- console.error(err);
93
- return resolve(false);
94
- }
95
- process.nextTick(() => {
96
- resolve(true);
97
- });
98
- });
99
- });
100
- });
101
- }
102
- public watch() {
103
- const watching = this.compiler.watch({}, () => {});
104
- }
105
- }