@shuvi/platform-web 1.0.63 → 2.0.0-dev.6
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.
- package/lib/node/features/html-render/index.js +5 -5
- package/lib/node/features/html-render/lib/buildHtml.js +1 -0
- package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.d.ts +209 -1
- package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.js +208 -6
- package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.rspack.d.ts +249 -0
- package/lib/node/features/html-render/lib/webpack/build-manifest-plugin.rspack.js +498 -0
- package/lib/node/targets/react/bundler/index.js +5 -16
- package/package.json +12 -12
|
@@ -0,0 +1,498 @@
|
|
|
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
|
+
console.debug(`[Rspack] chunk="${chunk.name}" rawRequests length > 1: length=${rawRequests.length}`);
|
|
228
|
+
/**
|
|
229
|
+
* @rspack-diff
|
|
230
|
+
* @TODO workaround: because Rspack's behavior is different from webpack
|
|
231
|
+
* if rawRequests length > 1,
|
|
232
|
+
* then try to return the sideEffectFree module's rawRequest
|
|
233
|
+
*/
|
|
234
|
+
const sideEffectFreeModules = modules.filter(m => {
|
|
235
|
+
const factoryMeta = m.factoryMeta;
|
|
236
|
+
return factoryMeta && factoryMeta.sideEffectFree === true;
|
|
237
|
+
});
|
|
238
|
+
if (sideEffectFreeModules.length) {
|
|
239
|
+
const rawRequest = sideEffectFreeModules[0]
|
|
240
|
+
.rawRequest;
|
|
241
|
+
console.debug(`[Rspack] chunk="${chunk.name}" try to pick sideEffectFreeModules="${rawRequest}"`);
|
|
242
|
+
if (rawRequest) {
|
|
243
|
+
return rawRequest;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return rawRequests[0] || '';
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Collects entry point information from chunk groups
|
|
251
|
+
* @param entrypoint - The entry point chunk group to process
|
|
252
|
+
*
|
|
253
|
+
* This method processes entry points and maps them to their output files,
|
|
254
|
+
* filtering out source maps and hot update files.
|
|
255
|
+
*/
|
|
256
|
+
_collectEntries(entrypoint) {
|
|
257
|
+
for (const chunk of entrypoint.chunks) {
|
|
258
|
+
// If there's no name or no files
|
|
259
|
+
if (!chunk.name || !chunk.files) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
for (const file of chunk.files) {
|
|
263
|
+
if (/\.map$/.test(file) || /\.hot-update\.js$/.test(file)) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
const ext = getFileExt(file);
|
|
267
|
+
this._pushEntries(entrypoint.name, ext, file.replace(/\\/g, '/'));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Collects information from chunk groups including chunks and modules
|
|
273
|
+
* @param chunkGroup - The chunk group to process
|
|
274
|
+
* @param compiler - Rspack compiler instance
|
|
275
|
+
* @param compilation - Rspack compilation instance
|
|
276
|
+
*
|
|
277
|
+
* This method processes chunk groups to collect:
|
|
278
|
+
* - Chunk information (files, requests)
|
|
279
|
+
* - Module information (if enabled)
|
|
280
|
+
* - Loadable modules and their relationships
|
|
281
|
+
*/
|
|
282
|
+
_collect(chunkGroup, compiler, compilation) {
|
|
283
|
+
const collectModules = this._options.modules;
|
|
284
|
+
// Rspack chunk groups may have origins with request information
|
|
285
|
+
const origins = chunkGroup.origins || [];
|
|
286
|
+
origins.forEach(chunkGroupOrigin => {
|
|
287
|
+
const { request } = chunkGroupOrigin;
|
|
288
|
+
const ctx = { request: request || '', compiler, compilation };
|
|
289
|
+
chunkGroup.chunks.forEach(chunk => {
|
|
290
|
+
const rawRequest = this._getFirstRawRequest(compilation, chunk);
|
|
291
|
+
if (rawRequest) {
|
|
292
|
+
// @TODO lodable support
|
|
293
|
+
// ctx.request = rawRequest;
|
|
294
|
+
}
|
|
295
|
+
this._collectChunk(chunk, ctx);
|
|
296
|
+
if (collectModules) {
|
|
297
|
+
this._collectChunkModule(chunk, ctx);
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
// If no origins, still process chunks
|
|
302
|
+
if (origins.length === 0) {
|
|
303
|
+
chunkGroup.chunks.forEach(chunk => {
|
|
304
|
+
this._collectChunk(chunk, { request: '', compilation, compiler });
|
|
305
|
+
if (collectModules) {
|
|
306
|
+
this._collectChunkModule(chunk, {
|
|
307
|
+
request: '',
|
|
308
|
+
compiler,
|
|
309
|
+
compilation
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Collects information from individual chunks
|
|
317
|
+
* @param chunk - The rspack chunk to process
|
|
318
|
+
* @param request - The request that generated this chunk
|
|
319
|
+
*
|
|
320
|
+
* This method processes chunks to:
|
|
321
|
+
* - Identify bundle files
|
|
322
|
+
* - Map chunk requests to files
|
|
323
|
+
* - Filter out source maps and hot update files
|
|
324
|
+
*/
|
|
325
|
+
_collectChunk(chunk, { request, compilation, compiler }) {
|
|
326
|
+
if (!chunk.files) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
for (const file of chunk.files) {
|
|
330
|
+
if (/\.map$/.test(file) || /\.hot-update\.js$/.test(file)) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
const ext = getFileExt(file);
|
|
334
|
+
const normalizedPath = file.replace(/\\/g, '/');
|
|
335
|
+
// normal chunk
|
|
336
|
+
if (ext === 'js') {
|
|
337
|
+
if (chunk.isOnlyInitial()) {
|
|
338
|
+
this._pushBundle({
|
|
339
|
+
name: chunk.name,
|
|
340
|
+
file: normalizedPath
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
this._pushChunkRequest({
|
|
344
|
+
file: normalizedPath,
|
|
345
|
+
request: request
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Collects module information from chunks (when modules option is enabled)
|
|
352
|
+
* @param chunk - The rspack chunk to process
|
|
353
|
+
* @param request - The request that generated this chunk
|
|
354
|
+
* @param compiler - Rspack compiler instance
|
|
355
|
+
* @param compilation - Rspack compilation instance
|
|
356
|
+
*
|
|
357
|
+
* This method processes chunks to collect:
|
|
358
|
+
* - Loadable module files (JS and CSS)
|
|
359
|
+
* - Module metadata (ID, name) - simplified for Rspack
|
|
360
|
+
* - Root modules for code splitting analysis
|
|
361
|
+
*/
|
|
362
|
+
_collectChunkModule(chunk, { request, compiler, compilation }) {
|
|
363
|
+
if (chunk.canBeInitial()) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const context = compiler.options.context;
|
|
367
|
+
// Collect files from chunk
|
|
368
|
+
chunk.files.forEach((file) => {
|
|
369
|
+
const isJs = file.match(/\.js$/) && file.match(/^static\/chunks\//);
|
|
370
|
+
const isCss = file.match(/\.css$/) && file.match(/^static\/css\//);
|
|
371
|
+
if (isJs || isCss) {
|
|
372
|
+
this._pushLoadableModules(request, file);
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
// TODO: Rspack 模块收集需要适配
|
|
376
|
+
// Webpack 版本使用 chunkGraph.getChunkModulesIterable() 和 chunkRootModulesMap
|
|
377
|
+
// Rspack 可能需要使用不同的 API 或等待相关功能支持
|
|
378
|
+
// 当前实现是简化版本,可能需要根据 Rspack 的实际 API 进行调整
|
|
379
|
+
try {
|
|
380
|
+
const { chunkGraph } = compilation;
|
|
381
|
+
if (chunkGraph &&
|
|
382
|
+
typeof chunkGraph.getChunkModulesIterable === 'function') {
|
|
383
|
+
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
|
384
|
+
let id = chunkGraph.getModuleId(module);
|
|
385
|
+
if (!module.type || !module.type.startsWith('javascript')) {
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
let name = null;
|
|
389
|
+
if (typeof module.libIdent === 'function') {
|
|
390
|
+
name = module.libIdent({ context });
|
|
391
|
+
}
|
|
392
|
+
if (!name || name.endsWith('.css')) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
// TODO: Rspack 需要实现 chunk root modules 检查
|
|
396
|
+
// Webpack 版本使用 chunkRootModulesMap.has(id) 来检查是否为根模块
|
|
397
|
+
// Rspack 可能需要使用不同的方式来判断模块是否为根模块
|
|
398
|
+
// 当前暂时将所有模块都作为 loadable 模块处理
|
|
399
|
+
// const isRootModule = chunkRootModulesMap.has(id);
|
|
400
|
+
// if (isRootModule) {
|
|
401
|
+
this._pushLoadableModules(request, {
|
|
402
|
+
id,
|
|
403
|
+
name
|
|
404
|
+
});
|
|
405
|
+
// }
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
// Rspack might not have the same module APIs as webpack
|
|
411
|
+
// This is a fallback for compatibility
|
|
412
|
+
console.warn('RspackBuildManifestPlugin: Module collection not fully supported in this Rspack version');
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Adds entry information to the manifest
|
|
417
|
+
* @param name - Entry point name
|
|
418
|
+
* @param ext - File extension
|
|
419
|
+
* @param value - File path
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* ```typescript
|
|
423
|
+
* this._pushEntries('main', 'js', '/static/js/main.abc123.js')
|
|
424
|
+
* // Results in: { entries: { main: { js: ['/static/js/main.abc123.js'] } } }
|
|
425
|
+
* ```
|
|
426
|
+
*/
|
|
427
|
+
_pushEntries(name, ext, value) {
|
|
428
|
+
const entries = this._manifest.entries;
|
|
429
|
+
if (!entries[name]) {
|
|
430
|
+
entries[name] = {
|
|
431
|
+
js: []
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
if (!entries[name][ext]) {
|
|
435
|
+
entries[name][ext] = [value];
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
entries[name][ext].push(value);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Adds bundle information to the manifest
|
|
443
|
+
* @param name - Bundle name
|
|
444
|
+
* @param file - Bundle file path
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```typescript
|
|
448
|
+
* this._pushBundle({ name: 'main', file: '/static/js/main.abc123.js' })
|
|
449
|
+
* // Results in: { bundles: { main: '/static/js/main.abc123.js' } }
|
|
450
|
+
* ```
|
|
451
|
+
*/
|
|
452
|
+
_pushBundle({ name, file }) {
|
|
453
|
+
if (name) {
|
|
454
|
+
this._manifest.bundles[name] = file;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Adds chunk request information to the manifest (when chunkRequest option is enabled)
|
|
459
|
+
* @param file - Chunk file path
|
|
460
|
+
* @param request - Request that generated the chunk
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```typescript
|
|
464
|
+
* this._pushChunkRequest({
|
|
465
|
+
* file: '/static/js/chunk.xyz789.js',
|
|
466
|
+
* request: '/pages/about'
|
|
467
|
+
* })
|
|
468
|
+
* // Results in: { chunkRequest: { '/static/js/chunk.xyz789.js': '/pages/about' } }
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
_pushChunkRequest({ file, request }) {
|
|
472
|
+
if (this._options.chunkRequest && request) {
|
|
473
|
+
this._manifest.chunkRequest[file] = request;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
_pushLoadableModules(request, value) {
|
|
477
|
+
const modules = this._manifest.loadble;
|
|
478
|
+
if (!modules[request]) {
|
|
479
|
+
modules[request] = {
|
|
480
|
+
files: [],
|
|
481
|
+
children: []
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
if (typeof value === 'string') {
|
|
485
|
+
const existed = modules[request].files.some(file => file === value);
|
|
486
|
+
if (!existed) {
|
|
487
|
+
modules[request].files.push(value);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
const existed = modules[request].children.some(item => item.id === value.id);
|
|
492
|
+
if (!existed) {
|
|
493
|
+
modules[request].children.push(value);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
exports.default = RspackBuildManifestPlugin;
|
|
@@ -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
|
|
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,
|
|
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(
|
|
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": "
|
|
3
|
+
"version": "2.0.0-dev.6",
|
|
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
|
-
"@
|
|
75
|
-
"@shuvi/error-overlay": "
|
|
76
|
-
"@shuvi/hook": "
|
|
77
|
-
"@shuvi/platform-shared": "
|
|
78
|
-
"@shuvi/router": "
|
|
79
|
-
"@shuvi/router-react": "
|
|
80
|
-
"@shuvi/runtime": "
|
|
81
|
-
"@shuvi/shared": "
|
|
82
|
-
"@shuvi/toolpack": "
|
|
83
|
-
"@shuvi/utils": "
|
|
74
|
+
"@rspack/plugin-react-refresh": "^1.4.3",
|
|
75
|
+
"@shuvi/error-overlay": "2.0.0-dev.6",
|
|
76
|
+
"@shuvi/hook": "2.0.0-dev.6",
|
|
77
|
+
"@shuvi/platform-shared": "2.0.0-dev.6",
|
|
78
|
+
"@shuvi/router": "2.0.0-dev.6",
|
|
79
|
+
"@shuvi/router-react": "2.0.0-dev.6",
|
|
80
|
+
"@shuvi/runtime": "2.0.0-dev.6",
|
|
81
|
+
"@shuvi/shared": "2.0.0-dev.6",
|
|
82
|
+
"@shuvi/toolpack": "2.0.0-dev.6",
|
|
83
|
+
"@shuvi/utils": "2.0.0-dev.6",
|
|
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": "
|
|
101
|
+
"@shuvi/service": "2.0.0-dev.6"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
104
|
"@shuvi/service": "workspace:*",
|