@modern-js/main-doc 2.68.0 → 2.68.2

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.
@@ -175,7 +175,7 @@ Options:
175
175
 
176
176
  ## modern inspect
177
177
 
178
- The `modern inspect` command is used to view the [Rsbuild config](https://rsbuild.rs/config/index) and webpack or Rspack config of the project.
178
+ The `modern inspect` command is used to view the Modern.js config, [Rsbuild config](https://rsbuild.rs/config/index) and webpack or Rspack config of the project.
179
179
 
180
180
  ```bash
181
181
  Usage: modern inspect [options]
@@ -190,6 +190,7 @@ Options:
190
190
 
191
191
  After executing the command `npx modern inspect` in the project root directory, the following files will be generated in the `dist` directory of the project:
192
192
 
193
+ - `modern.js.config.mjs`:The Modern.js configuration currently used.
193
194
  - `rsbuild.config.mjs`: The Rsbuild config to use at build time.
194
195
  - `webpack.config.web.mjs`: The webpack config used by to use at build time.
195
196
 
@@ -200,6 +201,7 @@ Inspect config succeed, open following files to view the content:
200
201
 
201
202
  - Rsbuild Config: /root/my-project/dist/rsbuild.config.mjs
202
203
  - Webpack Config (web): /root/my-project/dist/webpack.config.web.mjs
204
+ - Modern.js Config: /root/my-project/dist/modern.js.config.mjs
203
205
  ```
204
206
 
205
207
  ### Configuration Env
@@ -230,6 +232,7 @@ Inspect config succeed, open following files to view the content:
230
232
  - Rsbuild Config: /root/my-project/dist/rsbuild.config.mjs
231
233
  - Webpack Config (web): /root/my-project/dist/webpack.config.web.mjs
232
234
  - Webpack Config (node): /root/my-project/dist/webpack.config.node.mjs
235
+ - Modern.js Config: /root/my-project/dist/modern.js.config.mjs
233
236
  ```
234
237
 
235
238
  import DeployCommand from '@site-docs-en/components/deploy-command';
@@ -74,7 +74,7 @@ EdenX's `cache` function can be used in any frontend or server-side code.
74
74
 
75
75
  ## Detailed Usage
76
76
 
77
- ### Without `options` Parameter
77
+ ### Without options Parameter
78
78
 
79
79
  When no `options` parameter is provided, it's primarily useful in SSR projects, the cache lifecycle is limited to a single SSR rendering request. For example, when the same cachedFn is called in multiple data loaders, the cachedFn function won't be executed repeatedly. This allows data sharing between different data loaders while avoiding duplicate requests. EdenX will re-execute the `fn` function with each server request.
80
80
 
@@ -97,7 +97,7 @@ const loader = async () => {
97
97
  ```
98
98
 
99
99
 
100
- ### With `options` Parameter
100
+ ### With options Parameter
101
101
 
102
102
  #### `maxAge` Parameter
103
103
 
@@ -166,13 +166,15 @@ const getComplexStatistics = cache(
166
166
  }
167
167
  );
168
168
 
169
- revalidateTag('dashboard'); // Invalidates the cache for both getDashboardStats and getComplexStatistics functions
169
+ await revalidateTag('dashboard-stats'); // Invalidates the cache for both getDashboardStats and getComplexStatistics functions
170
170
  ```
171
171
 
172
172
 
173
173
  #### `getKey` Parameter
174
174
 
175
- The `getKey` parameter simplifies cache key generation, especially useful when you only need to rely on part of the function parameters to differentiate caches. It's a function that receives the same parameters as the original function and returns a string or number as the cache key:
175
+ The `getKey` parameter simplifies cache key generation, especially useful when you only need to rely on part of the function parameters to differentiate caches. It's a function that receives the same parameters as the original function and returns a string.
176
+
177
+ Its return value becomes part of the final cache key, but the key is still combined with a unique function identifier, making the cache **function-scoped**.
176
178
 
177
179
  ```ts
178
180
  import { cache, CacheTime } from '@modern-js/runtime/cache';
@@ -238,7 +240,9 @@ await getUserById(42); // Uses 42 as the cache key
238
240
 
239
241
  #### `customKey` parameter
240
242
 
241
- The `customKey` parameter is used to customize the cache key. It is a function that receives an object with the following properties and returns a string or Symbol type as the cache key:
243
+ The `customKey` parameter is used to **fully customize** the cache key. It is a function that receives an object with the following properties and returns a string as the cache key.
244
+
245
+ Its return value **directly becomes** the final cache key, **overriding** the default combination of a function identifier and parameter-based key. This allows you to create **globally unique** keys and share cache across different functions.
242
246
 
243
247
  - `params`: Array of arguments passed to the cached function
244
248
  - `fn`: Reference to the original function being cached
@@ -247,16 +251,15 @@ The `customKey` parameter is used to customize the cache key. It is a function t
247
251
  :::info
248
252
 
249
253
  Generally, the cache will be invalidated in the following scenarios:
250
- 1. The referenced cached function changes
251
- 2. The function's input parameters change
252
- 3. The maxAge condition is no longer satisfied
253
- 4. The `revalidateTag` method has been called
254
+ 1. The function's input parameters change
255
+ 2. The maxAge condition is no longer satisfied
256
+ 3. The `revalidateTag` method has been called
254
257
 
255
- `customKey` can be used in scenarios where function references are different but shared caching is desired. If it's just for customizing the cache key, it is recommended to use `getKey`.
258
+ By default, the framework generates a stable function ID based on the function's string representation and combines it with the generated parameter key. `customKey` can be used when you need complete control over the cache key generation, especially useful for sharing cache across different function instances. If you just need to customize how parameters are converted to cache keys, it is recommended to use `getKey`.
256
259
 
257
260
  :::
258
261
 
259
- This is very useful in some scenarios, such as when the function reference changes , but you want to still return the cached data.
262
+ This is very useful in some scenarios, such as when you want to share cache across different function instances or when you need predictable cache keys for external cache management.
260
263
 
261
264
  ```ts
262
265
  import { cache } from '@modern-js/runtime/cache';
@@ -287,21 +290,26 @@ const getUserB = cache(
287
290
  }
288
291
  );
289
292
 
290
- // You can also use Symbol as a cache key (usually used to share cache within the same application)
291
- const USER_CACHE_KEY = Symbol('user-cache');
293
+ // Now you can share cache across different function implementations
294
+ await getUserA(123); // Fetches data and caches with key "user-123"
295
+ await getUserB(123); // Cache hit, returns cached data
296
+
297
+ // You can utilize the generatedKey parameter to modify the default key
292
298
  const getUserC = cache(
293
299
  fetchUserData,
294
300
  {
295
- maxAge: CacheTime.MINUTE * 5,
296
- customKey: () => USER_CACHE_KEY,
301
+ customKey: ({ generatedKey }) => `prefix-${generatedKey}`,
297
302
  }
298
303
  );
299
304
 
300
- // You can utilize the generatedKey parameter to modify the default key
305
+ // For predictable cache keys that can be managed externally
301
306
  const getUserD = cache(
302
- fetchUserData,
307
+ async (userId: string) => {
308
+ return await fetchUserData(userId);
309
+ },
303
310
  {
304
- customKey: ({ generatedKey }) => `prefix-${generatedKey}`,
311
+ maxAge: CacheTime.MINUTE * 5,
312
+ customKey: ({ params }) => `app:user:${params[0]}`,
305
313
  }
306
314
  );
307
315
  ```
@@ -370,6 +378,8 @@ The `onCache` callback is useful for:
370
378
 
371
379
  ### Storage
372
380
 
381
+ #### Default Storage
382
+
373
383
  Currently, both client and server caches are stored in memory.
374
384
  The default storage limit for all cached functions is 1GB. When this limit is reached, the oldest cache is removed using an LRU algorithm.
375
385
 
@@ -386,3 +396,132 @@ configureCache({
386
396
  maxSize: CacheSize.MB * 10, // 10MB
387
397
  });
388
398
  ```
399
+
400
+ #### Custom Storage Container
401
+
402
+ In addition to the default memory storage, you can use custom storage containers such as Redis, file systems, databases, etc. This enables cache sharing across processes and servers.
403
+
404
+ ##### Container Interface
405
+
406
+ Custom storage containers need to implement the `Container` interface:
407
+
408
+ ```ts
409
+ interface Container {
410
+ get: (key: string) => Promise<string | undefined | null>;
411
+ set: (key: string, value: string, options?: { ttl?: number }) => Promise<any>;
412
+ has: (key: string) => Promise<boolean>;
413
+ delete: (key: string) => Promise<boolean>;
414
+ clear: () => Promise<void>;
415
+ }
416
+ ```
417
+
418
+ ##### Basic Usage
419
+
420
+ ```ts
421
+ import { configureCache } from '@modern-js/runtime/cache';
422
+
423
+ // Use custom storage container
424
+ configureCache({
425
+ container: customContainer,
426
+ });
427
+ ```
428
+
429
+ ##### Using `customKey` to Ensure Cache Key Stability
430
+
431
+ :::note
432
+
433
+ When using custom storage containers (such as Redis), **it's recommended to configure `customKey`** to ensure cache key stability. This ensures:
434
+
435
+ 1. **Cross-process sharing**: Different server instances can share the same cache
436
+ 2. **Cache validity after application restart**: Cache remains valid after restarting the application
437
+ 3. **Cache persistence after code deployment**: Cache for the same logic remains effective after code updates
438
+
439
+ :::
440
+
441
+ The default cache key generation mechanism is based on function references, which may not be stable enough in distributed environments. It's recommended to use `customKey` to provide stable cache keys:
442
+
443
+ ```ts
444
+ import { cache, configureCache } from '@modern-js/runtime/cache';
445
+
446
+ // Configure Redis container
447
+ configureCache({
448
+ container: redisContainer,
449
+ });
450
+
451
+ // Recommended: Use customKey to ensure key stability
452
+ const getUser = cache(
453
+ async (userId: string) => {
454
+ return await fetchUserData(userId);
455
+ },
456
+ {
457
+ maxAge: CacheTime.MINUTE * 5,
458
+ // Use stable identifiers related to the cached function as cache keys
459
+ customKey: () => `fetchUserData`,
460
+ }
461
+ );
462
+ ```
463
+
464
+ ##### Redis Storage Example
465
+
466
+ Here's an example of using Redis as a storage backend:
467
+
468
+ ```ts
469
+ import { Redis } from 'ioredis';
470
+ import { Container, configureCache } from '@modern-js/runtime/cache';
471
+
472
+ class RedisContainer implements Container {
473
+ private client: Redis;
474
+
475
+ constructor(client: Redis) {
476
+ this.client = client;
477
+ }
478
+
479
+ async get(key: string): Promise<string | null> {
480
+ const value = await this.redis.get(key);
481
+ return value ? JSON.parse(value) : null;
482
+ }
483
+
484
+ async set(
485
+ key: string,
486
+ value: string,
487
+ options?: { ttl?: number },
488
+ ): Promise<'OK'> {
489
+ if (options?.ttl) {
490
+ return this.client.set(key, JSON.stringify(value), 'EX', options.ttl);
491
+ }
492
+ return this.client.set(key, JSON.stringify(value));
493
+ }
494
+
495
+ async has(key: string): Promise<boolean> {
496
+ const result = await this.client.exists(key);
497
+ return result === 1;
498
+ }
499
+
500
+ async delete(key: string): Promise<boolean> {
501
+ const result = await this.client.del(key);
502
+ return result > 0;
503
+ }
504
+
505
+ async clear(): Promise<void> {
506
+ // Be cautious with this in production. It will clear the entire Redis database.
507
+ // A more robust implementation might use a key prefix and delete keys matching that prefix.
508
+ await this.client.flushdb();
509
+ }
510
+ }
511
+
512
+ // Configure Redis storage
513
+ const redisClient = new Redis({
514
+ host: 'localhost',
515
+ port: 6379,
516
+ });
517
+
518
+ configureCache({
519
+ container: new RedisContainer(redisClient),
520
+ });
521
+ ```
522
+
523
+ ##### Important Notes
524
+
525
+ 1. **Serialization**: All cached data will be serialized to strings for storage. The container only needs to handle string get/set operations.
526
+
527
+ 2. **TTL Support**: If your storage backend supports TTL (Time To Live), you can use the `options.ttl` parameter in the `set` method (in seconds).
@@ -175,7 +175,7 @@ Options:
175
175
 
176
176
  ## modern inspect
177
177
 
178
- `modern inspect` 命令用于查看项目的 [Rsbuild 配置](https://rsbuild.rs/zh/config/index) 以及 webpack 或 Rspack 配置。
178
+ `modern inspect` 命令用于查看项目的 Modern.js 配置、[Rsbuild 配置](https://rsbuild.rs/zh/config/index) 以及 webpack 或 Rspack 配置。
179
179
 
180
180
  ```bash
181
181
  Usage: modern inspect [options]
@@ -190,6 +190,7 @@ Options:
190
190
 
191
191
  在项目根目录下执行命令 `npx modern inspect` 后,会在项目的 `dist` 目录生成以下文件:
192
192
 
193
+ - `modern.js.config.mjs`: 表示当前使用的 Modern.js 配置。
193
194
  - `rsbuild.config.mjs`: 表示在构建时使用的 Rsbuild 配置。
194
195
  - `webpack.config.web.mjs`: 表示在构建时使用的 webpack 配置。
195
196
 
@@ -200,6 +201,7 @@ Inspect config succeed, open following files to view the content:
200
201
 
201
202
  - Rsbuild Config: /root/my-project/dist/rsbuild.config.mjs
202
203
  - Webpack Config (web): /root/my-project/dist/webpack.config.web.mjs
204
+ - Modern.js Config: /root/my-project/dist/modern.js.config.mjs
203
205
  ```
204
206
 
205
207
  ### 指定环境
@@ -230,6 +232,7 @@ Inspect config succeed, open following files to view the content:
230
232
  - Rsbuild Config: /root/my-project/dist/rsbuild.config.mjs
231
233
  - Webpack Config (web): /root/my-project/dist/webpack.config.web.mjs
232
234
  - Webpack Config (node): /root/my-project/dist/webpack.config.node.mjs
235
+ - Modern.js Config: /root/my-project/dist/modern.js.config.mjs
233
236
  ```
234
237
 
235
238
  import DeployCommand from '@site-docs/components/deploy-command';
@@ -159,12 +159,14 @@ const getComplexStatistics = cache(
159
159
  }
160
160
  );
161
161
 
162
- revalidateTag('dashboard'); // 会使 getDashboardStats 函数和 getComplexStatistics 函数的缓存都失效
162
+ await revalidateTag('dashboard-stats'); // 会使 getDashboardStats 函数和 getComplexStatistics 函数的缓存都失效
163
163
  ```
164
164
 
165
165
  #### `getKey` 参数
166
166
 
167
- `getKey` 参数用于自定义缓存键的生成方式,例如你可能只需要依赖函数参数的一部分来区分缓存。它是一个函数,接收与原始函数相同的参数,返回一个字符串作为缓存键:
167
+ `getKey` 参数用于**简化**缓存键的生成方式,例如你可能只需要依赖函数参数的一部分来区分缓存。它是一个函数,接收与原始函数相同的参数,返回一个字符串。
168
+
169
+ 它的返回值会作为参数部分参与最终缓存键的生成,但最终的键仍然会包含函数的唯一标识,因此缓存是**函数级别**的。
168
170
 
169
171
  ```ts
170
172
  import { cache, CacheTime } from '@modern-js/runtime/cache';
@@ -216,7 +218,9 @@ const getUser = cache(
216
218
 
217
219
  #### `customKey` 参数
218
220
 
219
- `customKey` 参数用于定制缓存的键,它是一个函数,接收一个包含以下属性的对象,返回值必须是字符串或 Symbol 类型,将作为缓存的键:
221
+ `customKey` 参数用于**完全定制**缓存的键,它是一个函数,接收一个包含以下属性的对象,返回值必须是字符串类型。
222
+
223
+ 它的返回值将**直接**作为最终的缓存键,**覆盖**了默认的函数标识和参数组合。这允许你创建**全局唯一**的缓存键,从而实现跨函数共享缓存。
220
224
 
221
225
  - `params`:调用缓存函数时传入的参数数组
222
226
  - `fn`:原始被缓存的函数引用
@@ -225,16 +229,15 @@ const getUser = cache(
225
229
  :::info
226
230
 
227
231
  一般在以下场景,缓存会失效:
228
- 1. 缓存的函数引用发生变化
229
- 2. 函数的入参发生变化
230
- 3. 不满足 maxAge
231
- 4. 调用了 `revalidateTag`
232
+ 1. 函数的入参发生变化
233
+ 2. 不满足 maxAge 条件
234
+ 3. 调用了 `revalidateTag`
232
235
 
233
- `customKey` 可以用在函数引用不同,但希望共享缓存的场景,如果只是自定义缓存键,推荐使用 `getKey`
236
+ 默认情况下,框架会基于函数的字符串表示生成稳定的函数 ID,并与生成的参数键组合。`customKey` 可以用于完全控制缓存键的生成,特别适用于在不同函数实例间共享缓存。如果只是需要自定义参数如何转换为缓存键,推荐使用 `getKey`。
234
237
 
235
238
  :::
236
239
 
237
- 这在某些场景下非常有用,比如当函数引用发生变化时,但你希望仍然返回缓存的数据。
240
+ 这在某些场景下非常有用,比如当你希望在不同函数实例间共享缓存,或者需要可预测的缓存键用于外部缓存管理时。
238
241
 
239
242
  ```ts
240
243
  import { cache } from '@modern-js/runtime/cache';
@@ -264,26 +267,26 @@ const getUserB = cache(
264
267
  }
265
268
  );
266
269
 
267
- // 即使 getUserA 和 getUserB 是不同的函数引用,但由于它们的 customKey 返回相同的值
268
- // 所以当调用参数相同时,它们会共享缓存
269
- const dataA = await getUserA(1);
270
- const dataB = await getUserB(1); // 这里会命中缓存,不会再次发起请求
270
+ // 现在你可以在不同的函数实现间共享缓存
271
+ await getUserA(123); // 获取数据并使用键 "user-123" 缓存
272
+ await getUserB(123); // 缓存命中,返回缓存的数据
271
273
 
272
- // 也可以使用 Symbol 作为缓存键(通常用于共享同一个应用内的缓存)
273
- const USER_CACHE_KEY = Symbol('user-cache');
274
+ // 可以利用 generatedKey 参数在默认键的基础上进行修改
274
275
  const getUserC = cache(
275
276
  fetchUserData,
276
277
  {
277
- maxAge: CacheTime.MINUTE * 5,
278
- customKey: () => USER_CACHE_KEY,
278
+ customKey: ({ generatedKey }) => `prefix-${generatedKey}`,
279
279
  }
280
280
  );
281
281
 
282
- // 可以利用 generatedKey 参数在默认键的基础上进行修改
282
+ // 用于可预测的缓存键,便于外部管理
283
283
  const getUserD = cache(
284
- fetchUserData,
284
+ async (userId: string) => {
285
+ return await fetchUserData(userId);
286
+ },
285
287
  {
286
- customKey: ({ generatedKey }) => `prefix-${generatedKey}`,
288
+ maxAge: CacheTime.MINUTE * 5,
289
+ customKey: ({ params }) => `app:user:${params[0]}`,
287
290
  }
288
291
  );
289
292
  ```
@@ -352,6 +355,8 @@ await getUser(2); // 缓存未命中
352
355
 
353
356
  ### 存储
354
357
 
358
+ #### 默认存储
359
+
355
360
  目前不管是客户端还是服务端,缓存都存储在内存中,默认情况下所有缓存函数共享的存储上限是 1GB,当达到存储上限后,使用 LRU 算法移除旧的缓存。
356
361
 
357
362
  :::info
@@ -368,3 +373,130 @@ configureCache({
368
373
  });
369
374
  ```
370
375
 
376
+ #### 自定义存储器
377
+
378
+ 除了默认的内存存储,你还可以使用自定义的存储容器,例如 Redis、文件系统、数据库等。这样可以实现跨进程、跨服务器的缓存共享。
379
+
380
+ ##### Container 接口
381
+
382
+ 自定义存储容器需要实现 `Container` 接口:
383
+
384
+ ```ts
385
+ interface Container {
386
+ get: (key: string) => Promise<string | undefined | null>;
387
+ set: (key: string, value: string, options?: { ttl?: number }) => Promise<any>;
388
+ has: (key: string) => Promise<boolean>;
389
+ delete: (key: string) => Promise<boolean>;
390
+ clear: () => Promise<void>;
391
+ }
392
+ ```
393
+
394
+ ##### 基本使用
395
+
396
+ ```ts
397
+ import { configureCache } from '@modern-js/runtime/cache';
398
+
399
+ // 使用自定义存储容器
400
+ configureCache({
401
+ container: customContainer,
402
+ });
403
+ ```
404
+
405
+ ##### 使用 `customKey` 确保缓存键稳定性
406
+
407
+ :::warning 重要建议
408
+ 当使用自定义存储容器(如 Redis)时,**建议配置 `customKey`** 来确保缓存键的稳定性。这样可以确保:
409
+
410
+ 1. **跨进程共享**:不同服务器实例能够共享相同的缓存
411
+ 2. **应用重启后缓存有效**:重启应用后仍能命中之前的缓存
412
+ 3. **代码部署后缓存保持**:代码更新后相同逻辑的缓存仍然有效
413
+ :::
414
+
415
+ 默认的缓存键生成机制基于函数引用,在分布式环境中可能不够稳定。建议使用 `customKey` 提供稳定的缓存键:
416
+
417
+ ```ts
418
+ import { cache, configureCache } from '@modern-js/runtime/cache';
419
+
420
+ // 配置 Redis 容器
421
+ configureCache({
422
+ container: redisContainer,
423
+ });
424
+
425
+ // 推荐:使用 customKey 确保键的稳定性
426
+ const getUser = cache(
427
+ async (userId: string) => {
428
+ return await fetchUserData(userId);
429
+ },
430
+ {
431
+ maxAge: CacheTime.MINUTE * 5,
432
+ // 使用被缓存函数相关的稳定标识符作为缓存键
433
+ customKey: () => `fetchUserData`,
434
+ }
435
+ );
436
+ ```
437
+
438
+ ##### Redis 存储示例
439
+
440
+ 以下是一个使用 Redis 作为存储后端的示例:
441
+
442
+ ```ts
443
+ import { Redis } from 'ioredis';
444
+ import { Container, configureCache } from '@modern-js/runtime/cache';
445
+
446
+ class RedisContainer implements Container {
447
+ private client: Redis;
448
+
449
+ constructor(client: Redis) {
450
+ this.client = client;
451
+ }
452
+
453
+ async get(key: string): Promise<string | null> {
454
+ const value = await this.redis.get(key);
455
+ return value ? JSON.parse(value) : null;
456
+ }
457
+
458
+ async set(
459
+ key: string,
460
+ value: string,
461
+ options?: { ttl?: number },
462
+ ): Promise<'OK'> {
463
+ if (options?.ttl) {
464
+ return this.client.set(key, JSON.stringify(value), 'EX', options.ttl);
465
+ }
466
+ return this.client.set(key, JSON.stringify(value));
467
+ }
468
+
469
+ async has(key: string): Promise<boolean> {
470
+ const result = await this.client.exists(key);
471
+ return result === 1;
472
+ }
473
+
474
+ async delete(key: string): Promise<boolean> {
475
+ const result = await this.client.del(key);
476
+ return result > 0;
477
+ }
478
+
479
+ async clear(): Promise<void> {
480
+ // 注意:在生产环境中要谨慎使用,这会清空整个 Redis 数据库
481
+ // 更好的实现方式是使用键前缀,然后删除匹配该前缀的所有键
482
+ await this.client.flushdb();
483
+ }
484
+ }
485
+
486
+ // 配置 Redis 存储
487
+ const redisClient = new Redis({
488
+ host: 'localhost',
489
+ port: 6379,
490
+ });
491
+
492
+ configureCache({
493
+ container: new RedisContainer(redisClient),
494
+ });
495
+ ```
496
+
497
+ ##### 注意事项
498
+
499
+ 1. **序列化**:所有的缓存数据都会被序列化为字符串存储,容器只需要处理字符串的存取操作。
500
+
501
+ 2. **TTL 支持**:如果你的存储后端支持 TTL(生存时间),可以在 `set` 方法中使用 `options.ttl` 参数(单位为秒)。
502
+
package/package.json CHANGED
@@ -15,17 +15,17 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.68.0",
18
+ "version": "2.68.2",
19
19
  "publishConfig": {
20
20
  "registry": "https://registry.npmjs.org/",
21
21
  "access": "public"
22
22
  },
23
23
  "dependencies": {
24
24
  "mermaid": "^11.4.1",
25
- "@modern-js/sandpack-react": "2.68.0"
25
+ "@modern-js/sandpack-react": "2.68.2"
26
26
  },
27
27
  "devDependencies": {
28
- "@rsbuild/plugin-sass": "1.3.2",
28
+ "@rsbuild/plugin-sass": "1.3.3",
29
29
  "@shikijs/transformers": "^3.4.2",
30
30
  "@rspress/shared": "2.0.0-beta.16",
31
31
  "@rspress/plugin-llms": "2.0.0-beta.16",