webgpu-computed 0.0.16 → 0.0.17

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 (2) hide show
  1. package/README.md +456 -54
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,23 +1,22 @@
1
1
  # webgpu-computed
2
2
 
3
- 🌐 Other languages:
3
+ 🌐 Other language versions:
4
+ - [中文](https://github.com/xiaguochuqiu/webgpu-computed/blob/main/README.zh.md)
4
5
 
5
- * [中文](https://github.com/xiaguochuqiu/webgpu-computed/blob/main/README.zh.md)
6
-
7
- A simplified WebGPU compute library that wraps verbose initialization and buffer management, allowing developers to focus on WGSL shader logic.
6
+ A simplified WebGPU compute library that encapsulates tedious initialization and buffer management, allowing developers to focus on WGSL shader logic.
8
7
 
9
8
  ## Features
10
9
 
11
- * 🚀 Simplified WebGPU initialization
12
- * 📦 Automatic buffer management and layout calculation
13
- * 🔧 Supports complex data structures (vectors, matrices)
14
- * ⚡ High-performance GPU computation
15
- * 📚 Built-in common WGSL functions
16
- * ✅ Node.js environment support
17
- * 🛠️ TypeScript support
18
- * 📖 Detailed documentation and examples
19
- * 🔄 Buffer reuse support
20
- * ⚛️ Atomic operations support (u32)
10
+ - 🚀 Simplified WebGPU initialization
11
+ - 📦 Automatic buffer management and layout calculation
12
+ - 🔧 Support for complex data structures (vectors, matrices)
13
+ - ⚡ High-performance GPU computing
14
+ - 📚 Built-in common WGSL functions
15
+ -Support for Node.js environment
16
+ - 🛠️ TypeScript support
17
+ - 📖 Detailed Chinese documentation and examples
18
+ - 🔄 Support for buffer reuse
19
+ - ⚛️ Support for atomic operations (u32)
21
20
 
22
21
  ## Installation
23
22
 
@@ -37,13 +36,13 @@ import { GpuComputed } from 'webgpu-computed';
37
36
  // Initialize WebGPU
38
37
  await GpuComputed.init();
39
38
 
40
- // In Node.js, call this after usage:
39
+ // In Node.js environment, call after use:
41
40
  // GpuComputed.destroy()
42
41
  ```
43
42
 
44
- ### 2. Execute a Simple Computation
43
+ ### 2. Perform Simple Computation
45
44
 
46
- Below is a simple vector addition example:
45
+ Here's a simple vector addition example:
47
46
 
48
47
  ```javascript
49
48
  import { GpuComputed } from 'webgpu-computed';
@@ -55,7 +54,7 @@ const data = {
55
54
  output: new Array(4).fill(0) // Output buffer
56
55
  };
57
56
 
58
- // WGSL computation code
57
+ // WGSL compute code
59
58
  const code = `
60
59
  output[index] = inputA[index] + inputB[index];
61
60
  `;
@@ -65,7 +64,7 @@ GpuComputed.computed({
65
64
  code,
66
65
  data,
67
66
  synchronize: ["output"], // Fields to return
68
- workgroupCount: [1] // Number of workgroups
67
+ workgroupCount: [1] // Workgroup count
69
68
  }).then(results => {
70
69
  console.log(results); // [[1.5, 3.5, 5.5, 7.5]]
71
70
  })
@@ -89,25 +88,26 @@ const code = `
89
88
  output[index].vel = positions[index].vel * 2.0;
90
89
  `;
91
90
 
91
+ // Execute computation
92
92
  GpuComputed.computed({
93
93
  code,
94
94
  data,
95
- synchronize: ["output"],
96
- workgroupCount: [1]
95
+ synchronize: ["output"], // Fields to return
96
+ workgroupCount: [1] // Workgroup count
97
97
  }).then(results => {
98
- console.log(results);
98
+ console.log(results); // [[1.100000023841858,2.200000047683716,3.299999952316284,0,0.20000000298023224,0.4000000059604645,0.6000000238418579,0,4.400000095367432,5.5,6.599999904632568,0,0.800000011920929,1,1.2000000476837158,0]]
99
99
  })
100
100
  ```
101
101
 
102
102
  ### 4. Using Different Data Types
103
103
 
104
- #### Unsigned Integer (u32)
104
+ #### Using Unsigned Integers (u32)
105
105
 
106
106
  ```javascript
107
107
  import { GpuComputed } from 'webgpu-computed';
108
108
 
109
109
  const data = {
110
- counters: new Uint32Array([0, 1, 2, 3]),
110
+ counters: new Uint32Array([0, 1, 2, 3]), // u32 array
111
111
  output: new Uint32Array(4)
112
112
  };
113
113
 
@@ -125,13 +125,13 @@ const results = await GpuComputed.computed({
125
125
  console.log(results[0]); // [0, 2, 4, 6]
126
126
  ```
127
127
 
128
- #### Atomic Operations
128
+ #### Using Atomic Operations
129
129
 
130
130
  ```javascript
131
131
  import { GpuComputed, AtomicUint32Array } from 'webgpu-computed';
132
132
 
133
133
  const data = {
134
- atomicCounter: new AtomicUint32Array([0]),
134
+ atomicCounter: new AtomicUint32Array([0]), // Atomic counter
135
135
  output: new Uint32Array(4)
136
136
  };
137
137
 
@@ -152,36 +152,121 @@ console.log(results[0]); // [1, 2, 3, 4]
152
152
 
153
153
  ### 5. Manually Creating a GpuComputed Instance
154
154
 
155
- If you need more fine-grained control, you can create a GpuComputed instance directly:
155
+ If you need finer control, you can create a GpuComputed instance directly:
156
156
 
157
157
  ```javascript
158
158
  import { GpuComputed } from 'webgpu-computed';
159
159
 
160
+ // 1. Define data template
160
161
  const template = {
161
162
  inputA: [] as number[],
162
163
  inputB: [] as number[],
163
164
  output: [] as number[]
164
165
  };
165
166
 
167
+ // 2. Create instance
166
168
  const gpuComputed = new GpuComputed(template, {
167
169
  code: `
168
170
  output[index] = inputA[index] + inputB[index];
169
171
  `,
170
- workgroupSize: [32, 1, 1]
172
+ workgroupSize: [32, 1, 1] // Optional: Custom workgroup size
171
173
  });
172
174
 
175
+ // 3. Initialize pipeline
173
176
  await gpuComputed.initPipeline();
174
177
 
178
+ // 4. Prepare data
175
179
  const data = {
176
180
  inputA: [1.0, 2.0, 3.0, 4.0],
177
181
  inputB: [0.5, 1.5, 2.5, 3.5],
178
182
  output: new Array(4).fill(0)
179
183
  };
180
184
 
185
+ // 5. Create bind group
181
186
  const bindGroup = gpuComputed.createBindGroup(data);
187
+
188
+ // 6. Execute computation
182
189
  const results = await gpuComputed.computed(bindGroup, [1], ['output']);
183
190
 
184
- console.log(results[0]);
191
+ console.log(results[0]); // [1.5, 3.5, 5.5, 7.5]
192
+ ```
193
+
194
+ #### Buffer Reuse
195
+
196
+ ```javascript
197
+ // First computation
198
+ const data1 = { input: [1, 2, 3], output: [0, 0, 0] };
199
+ const bindGroup1 = gpuComputed.createBindGroup(data1);
200
+ const results1 = await gpuComputed.computed(bindGroup1, [1], ['output']);
201
+
202
+ // Reuse the output buffer from the first computation for the second
203
+ // Note: The template must still include output to build the compute code
204
+ // const template = {
205
+ // input: [] as number[],
206
+ // output: [] as number[]
207
+ // };
208
+ const data2 = { input: [4, 5, 6]};
209
+ const bindGroup2 = gpuComputed.createBindGroup(data2, bindGroup1); // Reuse output buffer
210
+ const results2 = await gpuComputed.computed(bindGroup2, [1], ['output']);
211
+
212
+ console.log(results2[0]); // [4, 5, 6] output buffer reused
213
+ ```
214
+
215
+ #### Using Struct Data
216
+
217
+ ```javascript
218
+ // Define struct template
219
+ const structTemplate = {
220
+ particles: {
221
+ layout: [
222
+ { name: 'position', type: 'vec3' },
223
+ { name: 'velocity', type: 'vec3' },
224
+ { name: 'mass', type: 'f32' }
225
+ ]
226
+ },
227
+ output: {
228
+ layout: [
229
+ { name: 'position', type: 'vec3' },
230
+ { name: 'velocity', type: 'vec3' },
231
+ { name: 'mass', type: 'f32' }
232
+ ]
233
+ }
234
+ };
235
+
236
+ const gpuComputed = new GpuComputed(structTemplate, {
237
+ code: `
238
+ output[index].position = particles[index].position + particles[index].velocity;
239
+ output[index].velocity = particles[index].velocity * 2.0;
240
+ output[index].mass = particles[index].mass * 1.5;
241
+ `
242
+ });
243
+
244
+ await gpuComputed.initPipeline();
245
+
246
+ const data = {
247
+ particles: [
248
+ { position: [1, 2, 3], velocity: [0.1, 0.2, 0.3], mass: 1.0 },
249
+ { position: [4, 5, 6], velocity: [0.4, 0.5, 0.6], mass: 2.0 }
250
+ ],
251
+ output: [
252
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 },
253
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 }
254
+ ]
255
+ };
256
+
257
+ const bindGroup = gpuComputed.createBindGroup(data);
258
+ const results = await gpuComputed.computed(bindGroup, [1], ['output']);
259
+
260
+ console.log(results[0]); // Mapped data
261
+ ```
262
+
263
+ #### Data Mapping
264
+
265
+ When using structs, you can use the `dataMap` method to map results back to the original structure:
266
+
267
+ ```javascript
268
+ const mappedData = gpuComputed.dataMap(results[0], 'output');
269
+ console.log(mappedData); // Returns structured object array
185
270
  ```
186
271
 
187
272
  ## API Reference
@@ -194,41 +279,358 @@ console.log(results[0]);
194
279
 
195
280
  Initializes the WebGPU environment. Must be called before using other features.
196
281
 
282
+ **Returns**: `Promise<void>`
283
+
284
+ **Throws**: If the browser does not support WebGPU or fails to get adapter/device
285
+
197
286
  ##### `GpuComputed.computed(options)`
198
287
 
199
- Executes a GPU computation task.
288
+ Executes a GPU compute task.
200
289
 
201
290
  **Parameters**:
202
291
 
203
- * `code`: WGSL computation code
204
- * `data`: Input/output data object
205
- * `workgroupCount`: Workgroup count
206
- * `workgroupSize`: Workgroup size
207
- * `globalInvocationIdName`: Global invocation ID variable name
208
- * `workgroupIndexName`: Workgroup index variable name
209
- * `synchronize`: Buffers to synchronize back to CPU
210
- * `beforeCodes`: WGSL code snippets before the main code
211
- * `onSuccess`: Success callback
212
-
213
- ## Supported Types
214
-
215
- * `f32`
216
- * `u32`
217
- * `vec2`
218
- * `vec3`
219
- * `vec4`
220
- * `mat3x3`
221
- * `mat4x4`
292
+ - `code` (string): WGSL compute code
293
+ - `data` (object): Input/output data object
294
+ - `workgroupCount` (array): Workgroup count [x, y?, z?]
295
+ - `workgroupSize` (array, optional): Workgroup size, default [32, 1, 1]
296
+ - `globalInvocationIdName` (string, optional): Global invocation ID variable name, default "grid"
297
+ - `workgroupIndexName` (string, optional): Workgroup index variable name, default "index"
298
+ - `synchronize` (array, optional): Array of buffer names to sync back to CPU
299
+ - `beforeCodes` (array, optional): WGSL code snippets before the compute function
300
+ - `onSuccess` (function, optional): Success callback function
301
+
302
+ **Returns**: `Promise<Array<Float32Array | Uint32Array | Int32Array>>` - Data of synchronized buffers
303
+
304
+ ### Data Types
305
+
306
+ Supports the following WGSL types:
307
+
308
+ - `f32`: Single-precision float
309
+ - `u32`: Unsigned 32-bit integer
310
+ - `vec2`: 2D vector
311
+ - `vec3`: 3D vector
312
+ - `vec4`: 4D vector
313
+ - `mat3x3`: 3x3 matrix
314
+ - `mat4x4`: 4x4 matrix
315
+
316
+ ### Supported JavaScript Types
317
+
318
+ - `number[]`: Number array (automatically converted to Float32Array)
319
+ - `Float32Array`: 32-bit float array
320
+ - `Uint32Array`: 32-bit unsigned integer array
321
+ - `Int32Array`: 32-bit signed integer array
322
+ - `AtomicUint32Array`: Atomic unsigned integer array
323
+
324
+ ### Built-in WGSL Functions
325
+
326
+ The library provides some common WGSL helper functions:
327
+
328
+ #### Quaternion Rotation
329
+
330
+ ```wgsl
331
+ fn quat_rotate(q: vec4<f32>, v: vec3<f32>) -> vec3<f32>
332
+ ```
333
+
334
+ Usage example:
335
+
336
+ ```javascript
337
+ import { WGSL_Fun } from 'webgpu-computed';
338
+
339
+ await GpuComputed.computed({
340
+ code: "",
341
+ data: {....},
342
+ beforeCodes:[WGSL_Fun.quat_rotate]
343
+ })
344
+ ```
345
+
346
+ #### Point in OBB Detection
347
+
348
+ ```wgsl
349
+ fn point_in_obb(point: vec3<f32>, center: vec3<f32>, halfSize: vec3<f32>, quat: vec4<f32>) -> bool
350
+ ```
351
+
352
+ ## Advanced Usage
353
+
354
+ ### Custom Workgroup Configuration
355
+
356
+ ```javascript
357
+ await GpuComputed.computed({
358
+ code: '...',
359
+ data: {...},
360
+ workgroupCount: [4, 4], // 16 workgroups
361
+ workgroupSize: [16, 16], // 256 threads per workgroup
362
+ });
363
+ ```
364
+
365
+ ### Buffer Reuse
366
+
367
+ ```javascript
368
+ // Create initial bind group
369
+ const initialData = { buffer: new Float32Array(1000) };
370
+ const bindGroup = gpuComputed.createBindGroup(initialData);
371
+
372
+ // Reuse buffer for multiple computations
373
+ for (let i = 0; i < 10; i++) {
374
+ const newData = { buffer: new Float32Array(1000).fill(i) };
375
+ const reusedBindGroup = gpuComputed.createBindGroup(newData, bindGroup);
376
+ const results = await gpuComputed.computed(reusedBindGroup, [32], ['buffer']);
377
+ // Process results...
378
+ }
379
+ ```
380
+
381
+ ### Synchronizing Data Back to CPU
382
+
383
+ ```javascript
384
+ const results = await GpuComputed.computed({
385
+ code: '...',
386
+ data: {...},
387
+ synchronize: ['output'], // Specify buffers to sync
388
+ workgroupCount: [1]
389
+ });
390
+
391
+ // results contains synchronized data
392
+ ```
393
+
394
+ ### Callback Functions
395
+
396
+ ```javascript
397
+ await GpuComputed.computed({
398
+ code: '...',
399
+ data: {...},
400
+ workgroupCount: [1],
401
+ onSuccess: ({ gpuComputed, group, results }) => {
402
+ console.log('Computation complete', results);
403
+ }
404
+ });
405
+ ```
406
+
407
+ ## Example Project
408
+
409
+ ```js
410
+ import { GpuComputed } from "webgpu-computed"
411
+ import * as WGSL_Fun from "webgpu-computed"
412
+
413
+ // 1. Initialize WebGPU
414
+ console.log('Initializing WebGPU...');
415
+ await GpuComputed.init();
416
+ console.log('WebGPU initialized successfully');
417
+
418
+ // 2. Simple array computation example
419
+ console.log('\n=== Simple Array Computation ===');
420
+ const simpleData = {
421
+ inputA: [1.0, 2.0, 3.0, 4.0],
422
+ inputB: [0.5, 1.5, 2.5, 3.5],
423
+ output: new Array(4).fill(0)
424
+ };
425
+
426
+ const simpleCode = `
427
+ output[index] = inputA[index] + inputB[index];
428
+ `;
429
+
430
+ const simpleResults = await GpuComputed.computed({
431
+ code: simpleCode,
432
+ data: simpleData,
433
+ workgroupCount: [1],
434
+ synchronize: ['output']
435
+ });
436
+
437
+ console.log('Simple computation results:', simpleResults[0]); // [1.5, 3.5, 5.5, 7.5]
438
+
439
+ // 3. Using u32 type example
440
+ console.log('\n=== Using u32 Type ===');
441
+ const u32Data = {
442
+ counters: new Uint32Array([10, 20, 30, 40]),
443
+ output: new Uint32Array(4)
444
+ };
445
+
446
+ const u32Code = `
447
+ output[index] = counters[index] + 5u;
448
+ `;
449
+
450
+ const u32Results = await GpuComputed.computed({
451
+ code: u32Code,
452
+ data: u32Data,
453
+ workgroupCount: [1],
454
+ synchronize: ['output']
455
+ });
456
+
457
+ console.log('u32 computation results:', u32Results[0]); // [15, 25, 35, 45]
458
+
459
+ // 4. Atomic operations example
460
+ console.log('\n=== Atomic Operations Example ===');
461
+ const atomicData = {
462
+ counter: new AtomicUint32Array([0]),
463
+ results: new Uint32Array(4)
464
+ };
465
+
466
+ const atomicCode = `
467
+ let oldValue = atomicAdd(&counter[0], 1u);
468
+ results[index] = oldValue;
469
+ `;
470
+
471
+ const atomicResults = await GpuComputed.computed({
472
+ code: atomicCode,
473
+ data: atomicData,
474
+ workgroupCount: [1],
475
+ synchronize: ['results']
476
+ });
477
+
478
+ console.log('Atomic operation results:', atomicResults[0]); // [0, 1, 2, 3]
479
+
480
+ // 5. Complex data structure example (structs)
481
+ console.log('\n=== Complex Data Structure Computation ===');
482
+ const complexData = {
483
+ particles: [
484
+ { position: [1.0, 2.0, 3.0], velocity: [0.1, 0.2, 0.3], mass: 1.0 },
485
+ { position: [4.0, 5.0, 6.0], velocity: [0.4, 0.5, 0.6], mass: 2.0 }
486
+ ],
487
+ output: [
488
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 },
489
+ { position: [0, 0, 0], velocity: [0, 0, 0], mass: 0 }
490
+ ]
491
+ };
492
+
493
+ const complexCode = `
494
+ output[index].position = particles[index].position + particles[index].velocity;
495
+ output[index].velocity = particles[index].velocity * 2.0;
496
+ output[index].mass = particles[index].mass * 1.5;
497
+ `;
498
+
499
+ const complexResults = await GpuComputed.computed({
500
+ code: complexCode,
501
+ data: complexData,
502
+ workgroupCount: [1],
503
+ synchronize: ['output']
504
+ });
505
+
506
+ console.log('Complex computation results:', complexResults[0]);
507
+
508
+ // 6. Using built-in WGSL functions example
509
+ console.log('\n=== Using Built-in WGSL Functions ===');
510
+ const wgslFunData = {
511
+ points: [
512
+ {
513
+ x: 1.0, y: 0.0, z: 0.0
514
+ },
515
+ {
516
+ x: 0.0, y: 1.0, z: 0.0
517
+ },
518
+ {
519
+ x: -1.0, y: 0.0, z: 0.0
520
+ }
521
+ ],
522
+ obbCenter: [0.0, 0.0, 0.0],
523
+ obbHalfSize: [2.0, 2.0, 2.0],
524
+ obbRotation: [0.0, 0.0, 0.0, 1.0], // Unit quaternion, no rotation
525
+ results: new Array(3).fill(0)
526
+ };
527
+
528
+ const wgslFunCode = `
529
+ let point = vec3(points[index].x, points[index].y, points[index].z);
530
+ let center = vec3<f32>(obbCenter[0], obbCenter[1], obbCenter[2]);
531
+ let halfSize = vec3<f32>(obbHalfSize[0], obbHalfSize[1], obbHalfSize[2]);
532
+ let quat = vec4<f32>(obbRotation[0], obbRotation[1], obbRotation[2], obbRotation[3]);
533
+
534
+ if (point_in_obb(point, center, halfSize, quat)) {
535
+ results[index] = 1.0;
536
+ } else {
537
+ results[index] = 0.0;
538
+ }
539
+ `;
540
+
541
+ const wgslFunResults = await GpuComputed.computed({
542
+ code: wgslFunCode,
543
+ data: wgslFunData,
544
+ workgroupCount: [1],
545
+ beforeCodes: [WGSL_Fun.quat_rotate, WGSL_Fun.point_in_obb, /** Add your own function code */],
546
+ synchronize: ['results']
547
+ });
548
+
549
+ console.log('OBB detection results:', wgslFunResults[0]); // [1, 1, 1] All points inside OBB
550
+
551
+ // 7. Custom workgroup configuration example
552
+ console.log('\n=== Custom Workgroup Configuration ===');
553
+ const largeData = {
554
+ largeArray: new Array(1024).fill(0).map((_, i) => i * 1.0),
555
+ output: new Array(1024).fill(0)
556
+ };
557
+
558
+ const largeCode = `
559
+ output[index] = largeArray[index] * 2.0;
560
+ `;
561
+
562
+ const largeResults = await GpuComputed.computed({
563
+ code: largeCode,
564
+ data: largeData,
565
+ workgroupCount: [32], // 32 workgroups
566
+ workgroupSize: [32, 1, 1], // 32 threads per workgroup, total 1024 threads
567
+ synchronize: ['output']
568
+ });
569
+
570
+ console.log('Large array computation results (first 10):', largeResults[0].slice(0, 10));
571
+
572
+ // 8. Using callback functions example
573
+ console.log('\n=== Using Callback Functions ===');
574
+ const callbackData = {
575
+ values: [10.0, 20.0, 30.0],
576
+ squares: new Array(3).fill(0)
577
+ };
578
+
579
+ const callbackCode = `
580
+ squares[index] = values[index] * values[index];
581
+ `;
582
+
583
+ await GpuComputed.computed({
584
+ code: callbackCode,
585
+ data: callbackData,
586
+ workgroupCount: [1],
587
+ synchronize: ['squares'],
588
+ onSuccess: ({ gpuComputed, group, results }) => {
589
+ console.log('Callback triggered, square computation results:', results[0]); // [100, 400, 900]
590
+ }
591
+ });
592
+
593
+ // 9. Multi-dimensional workgroups example
594
+ console.log('\n=== Multi-dimensional Workgroups ===');
595
+ const matrixData = {
596
+ matrixA: new Array(16).fill(0).map((_, i) => i * 1.0),
597
+ matrixB: new Array(16).fill(0).map((_, i) => (i + 1) * 1.0),
598
+ result: new Array(16).fill(0)
599
+ };
600
+
601
+ const matrixCode = `
602
+ let x = index % 4u;
603
+ let y = index / 4u;
604
+ let idx = y * 4u + x;
605
+ result[idx] = matrixA[idx] + matrixB[idx];
606
+ `;
607
+
608
+ const matrixResults = await GpuComputed.computed({
609
+ code: matrixCode,
610
+ data: matrixData,
611
+ workgroupCount: [4, 4], // 4x4 workgroup grid
612
+ workgroupSize: [1, 1, 1], // 1 thread per workgroup
613
+ synchronize: ['result']
614
+ });
615
+
616
+ console.log('Matrix computation results:', matrixResults[0]);
617
+
618
+ console.log('\nAll feature examples completed!');
619
+ ```
222
620
 
223
621
  ## Browser Support
224
622
 
225
- * Chrome 113+
226
- * Edge 113+
227
- * Firefox (partial)
228
- * Safari (partial)
623
+ - Chrome 113+
624
+ - Edge 113+
625
+ - Firefox (partial support)
626
+ - Safari (partial support)
229
627
 
230
628
  Ensure the browser supports the WebGPU API.
231
629
 
630
+ ## Contributing
631
+
632
+ Issues and Pull Requests are welcome!
633
+
232
634
  ## License
233
635
 
234
- ISC License
636
+ ISC License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webgpu-computed",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "对webgpu的封装,处理了繁琐的前置工作,只关注wgsl本身逻辑",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {