@shuvi/platform-web 1.0.63 → 2.0.0-dev.7

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.
@@ -0,0 +1,496 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const shared_1 = require("../../../../../shared");
4
+ const webpack_1 = require("@shuvi/toolpack/lib/webpack");
5
+ const { RawSource } = webpack_1.sources;
6
+ // TODO: Rspack 需要确认 ModuleId 类型定义
7
+ // 当前 Rspack 的模块 ID 类型可能与 webpack 不同
8
+ // 需要根据 Rspack 的实际 API 来定义正确的类型
9
+ // type ModuleId = string | number;
10
+ /**
11
+ * Default configuration options for RspackBuildManifestPlugin
12
+ */
13
+ const defaultOptions = {
14
+ filename: 'build-manifest.json',
15
+ modules: false,
16
+ chunkRequest: false
17
+ };
18
+ /**
19
+ * Extracts file extension from a filepath
20
+ * @param filepath - The file path to extract extension from
21
+ * @returns The file extension (without dot) or empty string if no extension
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * getFileExt('app.js') // returns 'js'
26
+ * getFileExt('styles.css') // returns 'css'
27
+ * getFileExt('README') // returns ''
28
+ * ```
29
+ */
30
+ function getFileExt(filepath) {
31
+ const match = filepath.match(/\.(\w+)$/);
32
+ if (!match)
33
+ return '';
34
+ return match[1];
35
+ }
36
+ /**
37
+ * Rspack plugin that generates a build manifest JSON file containing mappings
38
+ * of entry filenames to their actual output filenames (which may be hashed in production).
39
+ *
40
+ * This plugin is adapted from the webpack version to work with Rspack's API.
41
+ * It provides the same functionality for frameworks that need to know the relationship
42
+ * between entry points and their corresponding built assets.
43
+ *
44
+ * ## Features
45
+ * - Maps entry points to their output files
46
+ * - Tracks bundle files and their relationships
47
+ * - Collects polyfill files
48
+ * - Supports loadable modules/chunks
49
+ * - Handles both development and production builds
50
+ *
51
+ * ## Generated Manifest Structure
52
+ * ```json
53
+ * {
54
+ * "entries": {
55
+ * "main": {
56
+ * "js": ["/static/js/main.abc123.js"],
57
+ * "css": ["/static/css/main.def456.css"]
58
+ * }
59
+ * },
60
+ * "bundles": {
61
+ * "main": "/static/js/main.abc123.js"
62
+ * },
63
+ * "chunkRequest": {
64
+ * "/static/js/chunk.xyz789.js": "/pages/about"
65
+ * },
66
+ * "loadble": {
67
+ * "/pages/about": {
68
+ * "files": ["/static/js/chunk.xyz789.js"],
69
+ * "children": [
70
+ * {
71
+ * "id": "module-id",
72
+ * "name": "AboutPage"
73
+ * }
74
+ * ]
75
+ * }
76
+ * },
77
+ * "polyfillFiles": ["/static/js/polyfills.ghi012.js"]
78
+ * }
79
+ * ```
80
+ *
81
+ * ## Usage Example
82
+ * ```typescript
83
+ * // In rspack configuration
84
+ * const RspackBuildManifestPlugin = require('./rspack-build-manifest-plugin');
85
+ *
86
+ * module.exports = {
87
+ * plugins: [
88
+ * new RspackBuildManifestPlugin({
89
+ * filename: 'build-manifest.json',
90
+ * modules: true,
91
+ * chunkRequest: true
92
+ * })
93
+ * ]
94
+ * };
95
+ * ```
96
+ *
97
+ * ## Use Cases
98
+ * - **SSR Frameworks**: Map entry points to built assets for server-side rendering
99
+ * - **Asset Loading**: Determine which files to load for specific routes
100
+ * - **Cache Management**: Track hashed filenames for cache invalidation
101
+ * - **Code Splitting**: Understand relationships between chunks and their requests
102
+ *
103
+ * ## Differences from Webpack Version
104
+ * - Uses Rspack's API instead of Webpack's
105
+ * - Simplified module collection (Rspack has different module APIs)
106
+ * - Adapted to Rspack's chunk and compilation structure
107
+ * - Some features are marked with TODO comments for future Rspack API support
108
+ */
109
+ class RspackBuildManifestPlugin {
110
+ /**
111
+ * Creates a new RspackBuildManifestPlugin instance
112
+ * @param options - Configuration options for the plugin
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * // Basic usage with default options
117
+ * new RspackBuildManifestPlugin()
118
+ *
119
+ * // Custom configuration
120
+ * new RspackBuildManifestPlugin({
121
+ * filename: 'assets-manifest.json',
122
+ * modules: true,
123
+ * chunkRequest: true
124
+ * })
125
+ * ```
126
+ */
127
+ constructor(options = {}) {
128
+ this._options = Object.assign(Object.assign({}, defaultOptions), options);
129
+ }
130
+ /**
131
+ * Creates the build manifest by analyzing compilation assets and chunks
132
+ * @param compiler - Rspack compiler instance
133
+ * @param compilation - Rspack compilation instance
134
+ * @returns The generated manifest object
135
+ *
136
+ * This method performs the following operations:
137
+ * 1. Initializes the manifest structure
138
+ * 2. Collects entry point information
139
+ * 3. Processes chunk groups and their assets
140
+ * 4. Identifies polyfill files
141
+ * 5. Sorts and organizes loadable modules
142
+ */
143
+ createAssets(compiler, compilation) {
144
+ const assetMap = (this._manifest = {
145
+ entries: {},
146
+ bundles: {},
147
+ chunkRequest: {},
148
+ loadble: {}
149
+ });
150
+ // TODO: Rspack 需要实现 chunk root modules 映射
151
+ // Webpack 版本使用 chunkGraph.getChunkRootModules() 来创建映射
152
+ // Rspack 可能需要使用不同的 API 或等待相关功能支持
153
+ // const chunkRootModulesMap = new Map<ModuleId, Boolean>();
154
+ // compilation.chunks.forEach(chunk => {
155
+ // const { chunkGraph } = compilation;
156
+ // if (chunkGraph) {
157
+ // chunkGraph.getChunkRootModules(chunk).forEach(module => {
158
+ // const id = chunkGraph.getModuleId(module);
159
+ // if (id !== '') {
160
+ // chunkRootModulesMap.set(id, true);
161
+ // }
162
+ // });
163
+ // }
164
+ // });
165
+ // Process all chunk groups
166
+ compilation.chunkGroups.forEach(chunkGroup => {
167
+ // Check if this is an entry point
168
+ if (chunkGroup.isInitial()) {
169
+ this._collectEntries(chunkGroup);
170
+ }
171
+ this._collect(chunkGroup, compiler, compilation);
172
+ });
173
+ const compilationAssets = compilation.getAssets();
174
+ // Collect polyfill files
175
+ this._manifest.polyfillFiles = compilationAssets
176
+ .filter(p => {
177
+ // Ensure only .js files are passed through
178
+ if (!p.name.endsWith('.js')) {
179
+ return false;
180
+ }
181
+ return p.info && shared_1.BUILD_CLIENT_RUNTIME_POLYFILLS_SYMBOL in p.info;
182
+ })
183
+ .map(v => v.name);
184
+ // Sort loadable modules for consistent output
185
+ this._manifest.loadble = Object.keys(this._manifest.loadble)
186
+ .sort()
187
+ // eslint-disable-next-line no-sequences
188
+ .reduce((a, c) => ((a[c] = this._manifest.loadble[c]), a), {});
189
+ return assetMap;
190
+ }
191
+ /**
192
+ * Applies the plugin to the rspack compiler
193
+ * @param compiler - Rspack compiler instance
194
+ *
195
+ * This method hooks into the rspack compilation process to:
196
+ * 1. Listen for the 'make' hook to prepare for asset processing
197
+ * 2. Hook into 'processAssets' to generate the manifest file
198
+ * 3. Create the JSON file as a compilation asset
199
+ */
200
+ apply(compiler) {
201
+ compiler.hooks.make.tap('RspackBuildManifestPlugin', compilation => {
202
+ compilation.hooks.processAssets.tap({
203
+ name: 'RspackBuildManifestPlugin',
204
+ stage: webpack_1.rspack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
205
+ }, assets => {
206
+ assets[this._options.filename] = new RawSource(JSON.stringify(this.createAssets(compiler, compilation), null, 2), true);
207
+ });
208
+ });
209
+ }
210
+ /**
211
+ * Get the raw request of the chunk
212
+ * @param compilation - Rspack compilation instance
213
+ * @param chunk - Rspack chunk instance
214
+ * @returns The raw request of the chunk
215
+ */
216
+ _getFirstRawRequest(compilation, chunk) {
217
+ const modules = compilation.chunkGraph.getChunkModules(chunk);
218
+ const rawRequests = modules
219
+ .map(m => {
220
+ const rawRequest = m.rawRequest;
221
+ if (rawRequest) {
222
+ return rawRequest;
223
+ }
224
+ })
225
+ .filter(Boolean);
226
+ if (rawRequests.length > 1) {
227
+ /**
228
+ * @rspack-diff
229
+ * @TODO workaround: because Rspack's behavior is different from webpack
230
+ * if rawRequests length > 1,
231
+ * then try to return the sideEffectFree module's rawRequest
232
+ */
233
+ const sideEffectFreeModules = modules.filter(m => {
234
+ const factoryMeta = m.factoryMeta;
235
+ return factoryMeta && factoryMeta.sideEffectFree === true;
236
+ });
237
+ if (sideEffectFreeModules.length) {
238
+ const rawRequest = sideEffectFreeModules[0]
239
+ .rawRequest;
240
+ if (rawRequest) {
241
+ return rawRequest;
242
+ }
243
+ }
244
+ }
245
+ return rawRequests[0] || '';
246
+ }
247
+ /**
248
+ * Collects entry point information from chunk groups
249
+ * @param entrypoint - The entry point chunk group to process
250
+ *
251
+ * This method processes entry points and maps them to their output files,
252
+ * filtering out source maps and hot update files.
253
+ */
254
+ _collectEntries(entrypoint) {
255
+ for (const chunk of entrypoint.chunks) {
256
+ // If there's no name or no files
257
+ if (!chunk.name || !chunk.files) {
258
+ continue;
259
+ }
260
+ for (const file of chunk.files) {
261
+ if (/\.map$/.test(file) || /\.hot-update\.js$/.test(file)) {
262
+ continue;
263
+ }
264
+ const ext = getFileExt(file);
265
+ this._pushEntries(entrypoint.name, ext, file.replace(/\\/g, '/'));
266
+ }
267
+ }
268
+ }
269
+ /**
270
+ * Collects information from chunk groups including chunks and modules
271
+ * @param chunkGroup - The chunk group to process
272
+ * @param compiler - Rspack compiler instance
273
+ * @param compilation - Rspack compilation instance
274
+ *
275
+ * This method processes chunk groups to collect:
276
+ * - Chunk information (files, requests)
277
+ * - Module information (if enabled)
278
+ * - Loadable modules and their relationships
279
+ */
280
+ _collect(chunkGroup, compiler, compilation) {
281
+ const collectModules = this._options.modules;
282
+ // Rspack chunk groups may have origins with request information
283
+ const origins = chunkGroup.origins || [];
284
+ origins.forEach(chunkGroupOrigin => {
285
+ const { request } = chunkGroupOrigin;
286
+ const ctx = { request: request || '', compiler, compilation };
287
+ chunkGroup.chunks.forEach(chunk => {
288
+ const rawRequest = this._getFirstRawRequest(compilation, chunk);
289
+ if (rawRequest) {
290
+ // @TODO lodable support
291
+ // ctx.request = rawRequest;
292
+ }
293
+ this._collectChunk(chunk, ctx);
294
+ if (collectModules) {
295
+ this._collectChunkModule(chunk, ctx);
296
+ }
297
+ });
298
+ });
299
+ // If no origins, still process chunks
300
+ if (origins.length === 0) {
301
+ chunkGroup.chunks.forEach(chunk => {
302
+ this._collectChunk(chunk, { request: '', compilation, compiler });
303
+ if (collectModules) {
304
+ this._collectChunkModule(chunk, {
305
+ request: '',
306
+ compiler,
307
+ compilation
308
+ });
309
+ }
310
+ });
311
+ }
312
+ }
313
+ /**
314
+ * Collects information from individual chunks
315
+ * @param chunk - The rspack chunk to process
316
+ * @param request - The request that generated this chunk
317
+ *
318
+ * This method processes chunks to:
319
+ * - Identify bundle files
320
+ * - Map chunk requests to files
321
+ * - Filter out source maps and hot update files
322
+ */
323
+ _collectChunk(chunk, { request, compilation, compiler }) {
324
+ if (!chunk.files) {
325
+ return;
326
+ }
327
+ for (const file of chunk.files) {
328
+ if (/\.map$/.test(file) || /\.hot-update\.js$/.test(file)) {
329
+ continue;
330
+ }
331
+ const ext = getFileExt(file);
332
+ const normalizedPath = file.replace(/\\/g, '/');
333
+ // normal chunk
334
+ if (ext === 'js') {
335
+ if (chunk.isOnlyInitial()) {
336
+ this._pushBundle({
337
+ name: chunk.name,
338
+ file: normalizedPath
339
+ });
340
+ }
341
+ this._pushChunkRequest({
342
+ file: normalizedPath,
343
+ request: request
344
+ });
345
+ }
346
+ }
347
+ }
348
+ /**
349
+ * Collects module information from chunks (when modules option is enabled)
350
+ * @param chunk - The rspack chunk to process
351
+ * @param request - The request that generated this chunk
352
+ * @param compiler - Rspack compiler instance
353
+ * @param compilation - Rspack compilation instance
354
+ *
355
+ * This method processes chunks to collect:
356
+ * - Loadable module files (JS and CSS)
357
+ * - Module metadata (ID, name) - simplified for Rspack
358
+ * - Root modules for code splitting analysis
359
+ */
360
+ _collectChunkModule(chunk, { request, compiler, compilation }) {
361
+ if (chunk.canBeInitial()) {
362
+ return;
363
+ }
364
+ const context = compiler.options.context;
365
+ // Collect files from chunk
366
+ chunk.files.forEach((file) => {
367
+ const isJs = file.match(/\.js$/) && file.match(/^static\/chunks\//);
368
+ const isCss = file.match(/\.css$/) && file.match(/^static\/css\//);
369
+ if (isJs || isCss) {
370
+ this._pushLoadableModules(request, file);
371
+ }
372
+ });
373
+ // TODO: Rspack 模块收集需要适配
374
+ // Webpack 版本使用 chunkGraph.getChunkModulesIterable() 和 chunkRootModulesMap
375
+ // Rspack 可能需要使用不同的 API 或等待相关功能支持
376
+ // 当前实现是简化版本,可能需要根据 Rspack 的实际 API 进行调整
377
+ try {
378
+ const { chunkGraph } = compilation;
379
+ if (chunkGraph &&
380
+ typeof chunkGraph.getChunkModulesIterable === 'function') {
381
+ for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
382
+ let id = chunkGraph.getModuleId(module);
383
+ if (!module.type || !module.type.startsWith('javascript')) {
384
+ continue;
385
+ }
386
+ let name = null;
387
+ if (typeof module.libIdent === 'function') {
388
+ name = module.libIdent({ context });
389
+ }
390
+ if (!name || name.endsWith('.css')) {
391
+ continue;
392
+ }
393
+ // TODO: Rspack 需要实现 chunk root modules 检查
394
+ // Webpack 版本使用 chunkRootModulesMap.has(id) 来检查是否为根模块
395
+ // Rspack 可能需要使用不同的方式来判断模块是否为根模块
396
+ // 当前暂时将所有模块都作为 loadable 模块处理
397
+ // const isRootModule = chunkRootModulesMap.has(id);
398
+ // if (isRootModule) {
399
+ this._pushLoadableModules(request, {
400
+ id,
401
+ name
402
+ });
403
+ // }
404
+ }
405
+ }
406
+ }
407
+ catch (error) {
408
+ // Rspack might not have the same module APIs as webpack
409
+ // This is a fallback for compatibility
410
+ console.warn('RspackBuildManifestPlugin: Module collection not fully supported in this Rspack version');
411
+ }
412
+ }
413
+ /**
414
+ * Adds entry information to the manifest
415
+ * @param name - Entry point name
416
+ * @param ext - File extension
417
+ * @param value - File path
418
+ *
419
+ * @example
420
+ * ```typescript
421
+ * this._pushEntries('main', 'js', '/static/js/main.abc123.js')
422
+ * // Results in: { entries: { main: { js: ['/static/js/main.abc123.js'] } } }
423
+ * ```
424
+ */
425
+ _pushEntries(name, ext, value) {
426
+ const entries = this._manifest.entries;
427
+ if (!entries[name]) {
428
+ entries[name] = {
429
+ js: []
430
+ };
431
+ }
432
+ if (!entries[name][ext]) {
433
+ entries[name][ext] = [value];
434
+ }
435
+ else {
436
+ entries[name][ext].push(value);
437
+ }
438
+ }
439
+ /**
440
+ * Adds bundle information to the manifest
441
+ * @param name - Bundle name
442
+ * @param file - Bundle file path
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * this._pushBundle({ name: 'main', file: '/static/js/main.abc123.js' })
447
+ * // Results in: { bundles: { main: '/static/js/main.abc123.js' } }
448
+ * ```
449
+ */
450
+ _pushBundle({ name, file }) {
451
+ if (name) {
452
+ this._manifest.bundles[name] = file;
453
+ }
454
+ }
455
+ /**
456
+ * Adds chunk request information to the manifest (when chunkRequest option is enabled)
457
+ * @param file - Chunk file path
458
+ * @param request - Request that generated the chunk
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * this._pushChunkRequest({
463
+ * file: '/static/js/chunk.xyz789.js',
464
+ * request: '/pages/about'
465
+ * })
466
+ * // Results in: { chunkRequest: { '/static/js/chunk.xyz789.js': '/pages/about' } }
467
+ * ```
468
+ */
469
+ _pushChunkRequest({ file, request }) {
470
+ if (this._options.chunkRequest && request) {
471
+ this._manifest.chunkRequest[file] = request;
472
+ }
473
+ }
474
+ _pushLoadableModules(request, value) {
475
+ const modules = this._manifest.loadble;
476
+ if (!modules[request]) {
477
+ modules[request] = {
478
+ files: [],
479
+ children: []
480
+ };
481
+ }
482
+ if (typeof value === 'string') {
483
+ const existed = modules[request].files.some(file => file === value);
484
+ if (!existed) {
485
+ modules[request].files.push(value);
486
+ }
487
+ }
488
+ else {
489
+ const existed = modules[request].children.some(item => item.id === value.id);
490
+ if (!existed) {
491
+ modules[request].children.push(value);
492
+ }
493
+ }
494
+ }
495
+ }
496
+ exports.default = RspackBuildManifestPlugin;
@@ -7,7 +7,7 @@ exports.OnDemandRouteManager = void 0;
7
7
  const service_1 = require("@shuvi/service");
8
8
  const escapeRegExp_1 = require("@shuvi/utils/escapeRegExp");
9
9
  const module_replace_plugin_1 = __importDefault(require("@shuvi/toolpack/lib/webpack/plugins/module-replace-plugin"));
10
- const require_cache_hot_reloader_plugin_1 = __importDefault(require("@shuvi/toolpack/lib/webpack/plugins/require-cache-hot-reloader-plugin"));
10
+ const require_cache_hot_reloader_plugin_rspack_1 = __importDefault(require("@shuvi/toolpack/lib/webpack/plugins/require-cache-hot-reloader-plugin.rspack"));
11
11
  const constants_1 = require("@shuvi/shared/constants");
12
12
  const dumbRouteComponent = require.resolve('./emptyComponent');
13
13
  const plugin = (0, service_1.createPlugin)({
@@ -27,7 +27,7 @@ const plugin = (0, service_1.createPlugin)({
27
27
  // This is because the client compilation generates the build manifest that's used on the server side
28
28
  config
29
29
  .plugin('private/require-cache-hot-reloader')
30
- .use(require_cache_hot_reloader_plugin_1.default);
30
+ .use(require_cache_hot_reloader_plugin_rspack_1.default);
31
31
  }
32
32
  return config;
33
33
  }
@@ -28,11 +28,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const path = __importStar(require("path"));
30
30
  const service_1 = require("@shuvi/service");
31
- const ReactRefreshWebpackPlugin_1 = __importDefault(require("@next/react-refresh-utils/ReactRefreshWebpackPlugin"));
31
+ const plugin_react_refresh_1 = __importDefault(require("@rspack/plugin-react-refresh"));
32
32
  const paths_1 = require("../../../paths");
33
33
  const shared_1 = require("../../../../shared");
34
34
  const isDefined = (value) => Boolean(value);
35
- const configWebpack = (config, { name, webpack }, context) => {
35
+ const configWebpack = (config, { name, rspack }, context) => {
36
36
  const resolveUser = (m, sub) => {
37
37
  const { rootDir } = context.paths;
38
38
  let userPkg = {
@@ -93,30 +93,19 @@ const configWebpack = (config, { name, webpack }, context) => {
93
93
  // @ts-ignore
94
94
  [resolveUser('react-dom'), (0, paths_1.resolveLocal)('react-dom')].filter(isDefined));
95
95
  if (name === shared_1.BUNDLER_TARGET_CLIENT) {
96
- config.plugin('version-env-plugin').use(webpack.DefinePlugin, [
96
+ config.plugin('version-env-plugin').use(rspack.DefinePlugin, [
97
97
  {
98
98
  'process.env.__SHUVI__AFTER__REACT__18__': JSON.stringify(isReactVersionAfter18())
99
99
  }
100
100
  ]);
101
101
  if (context.mode === 'development') {
102
- config
103
- .plugin('react-refresh-plugin')
104
- .use(ReactRefreshWebpackPlugin_1.default, [webpack]);
102
+ config.plugin('react-refresh-plugin').use(plugin_react_refresh_1.default);
105
103
  }
106
104
  }
107
105
  return config;
108
106
  };
109
107
  exports.default = {
110
108
  core: (0, service_1.createPlugin)({
111
- configWebpack,
112
- addEntryCode(context) {
113
- if (context.mode === 'development') {
114
- const fastRefreshRuntime = require.resolve(`@next/react-refresh-utils/runtime`);
115
- return `import "${fastRefreshRuntime}"`;
116
- }
117
- else {
118
- return '';
119
- }
120
- }
109
+ configWebpack
121
110
  })
122
111
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuvi/platform-web",
3
- "version": "1.0.63",
3
+ "version": "2.0.0-dev.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/shuvijs/shuvi.git",
@@ -71,16 +71,16 @@
71
71
  "node": ">= 16.0.0"
72
72
  },
73
73
  "dependencies": {
74
- "@next/react-refresh-utils": "12.1.6",
75
- "@shuvi/error-overlay": "1.0.63",
76
- "@shuvi/hook": "1.0.63",
77
- "@shuvi/platform-shared": "1.0.63",
78
- "@shuvi/router": "1.0.63",
79
- "@shuvi/router-react": "1.0.63",
80
- "@shuvi/runtime": "1.0.63",
81
- "@shuvi/shared": "1.0.63",
82
- "@shuvi/toolpack": "1.0.63",
83
- "@shuvi/utils": "1.0.63",
74
+ "@rspack/plugin-react-refresh": "^1.4.3",
75
+ "@shuvi/error-overlay": "2.0.0-dev.7",
76
+ "@shuvi/hook": "2.0.0-dev.7",
77
+ "@shuvi/platform-shared": "2.0.0-dev.7",
78
+ "@shuvi/router": "2.0.0-dev.7",
79
+ "@shuvi/router-react": "2.0.0-dev.7",
80
+ "@shuvi/runtime": "2.0.0-dev.7",
81
+ "@shuvi/shared": "2.0.0-dev.7",
82
+ "@shuvi/toolpack": "2.0.0-dev.7",
83
+ "@shuvi/utils": "2.0.0-dev.7",
84
84
  "content-type": "1.0.4",
85
85
  "core-js": "3.6.5",
86
86
  "doura": "0.0.13",
@@ -98,7 +98,7 @@
98
98
  "whatwg-fetch": "3.0.0"
99
99
  },
100
100
  "peerDependencies": {
101
- "@shuvi/service": "1.0.63"
101
+ "@shuvi/service": "2.0.0-dev.7"
102
102
  },
103
103
  "devDependencies": {
104
104
  "@shuvi/service": "workspace:*",