@jsenv/plugin-bundling 2.7.25 → 2.8.1
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/package.json +8 -7
- package/src/js_module/bundle_js_modules.js +220 -46
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/plugin-bundling",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"/src/"
|
|
22
22
|
],
|
|
23
|
+
"sideEffects": false,
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@jsenv/humanize": "1.
|
|
25
|
-
"@jsenv/url-meta": "8.5.
|
|
26
|
-
"@jsenv/urls": "2.6.
|
|
27
|
-
"@jsenv/sourcemap": "1.
|
|
28
|
-
"lightningcss": "1.29.
|
|
29
|
-
"rollup": "4.
|
|
25
|
+
"@jsenv/humanize": "1.3.1",
|
|
26
|
+
"@jsenv/url-meta": "8.5.4",
|
|
27
|
+
"@jsenv/urls": "2.6.2",
|
|
28
|
+
"@jsenv/sourcemap": "1.3.1",
|
|
29
|
+
"lightningcss": "1.29.2",
|
|
30
|
+
"rollup": "4.35.0"
|
|
30
31
|
},
|
|
31
32
|
"peerDependencies": {
|
|
32
33
|
"@jsenv/core": "*"
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { lookupPackageDirectory } from "@jsenv/filesystem";
|
|
1
2
|
import { createDetailedMessage } from "@jsenv/humanize";
|
|
3
|
+
import { isSpecifierForNodeBuiltin } from "@jsenv/node-esm-resolution/src/node_builtin_specifiers.js";
|
|
2
4
|
import { sourcemapConverter } from "@jsenv/sourcemap";
|
|
3
5
|
import { URL_META } from "@jsenv/url-meta";
|
|
4
|
-
import { isFileSystemPath } from "@jsenv/urls";
|
|
5
|
-
|
|
6
|
+
import { fileSystemPathToUrl, isFileSystemPath } from "@jsenv/urls";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
6
8
|
import { fileUrlConverter } from "../file_url_converter.js";
|
|
7
9
|
|
|
8
10
|
export const bundleJsModules = async (
|
|
@@ -35,15 +37,59 @@ export const bundleJsModules = async (
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
let manualChunks;
|
|
38
|
-
if (
|
|
40
|
+
if (chunks) {
|
|
41
|
+
if (chunks.vendors) {
|
|
42
|
+
chunks.vendors = {
|
|
43
|
+
"file:///**/node_modules/": true,
|
|
44
|
+
...chunks.vendors,
|
|
45
|
+
};
|
|
46
|
+
} else {
|
|
47
|
+
chunks.vendors = {
|
|
48
|
+
"file:///**/node_modules/": true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const packageDirectoryUrl = lookupPackageDirectory(rootDirectoryUrl);
|
|
52
|
+
if (packageDirectoryUrl) {
|
|
53
|
+
try {
|
|
54
|
+
const packageFileContent = readFileSync(
|
|
55
|
+
new URL("package.json", packageDirectoryUrl),
|
|
56
|
+
"utf8",
|
|
57
|
+
);
|
|
58
|
+
const packageJSON = JSON.parse(packageFileContent);
|
|
59
|
+
const workspaces = packageJSON.workspaces;
|
|
60
|
+
if (workspaces) {
|
|
61
|
+
const workspacePatterns = {};
|
|
62
|
+
for (const workspace of workspaces) {
|
|
63
|
+
const workspacePattern = new URL(
|
|
64
|
+
workspace.endsWith("/*") ? workspace.slice(0, -1) : workspace,
|
|
65
|
+
packageDirectoryUrl,
|
|
66
|
+
).href;
|
|
67
|
+
workspacePatterns[workspacePattern] = true;
|
|
68
|
+
}
|
|
69
|
+
if (chunks.workspaces) {
|
|
70
|
+
chunks.workspaces = {
|
|
71
|
+
...workspacePatterns,
|
|
72
|
+
...chunks.workspaces,
|
|
73
|
+
};
|
|
74
|
+
} else {
|
|
75
|
+
chunks.workspaces = workspacePatterns;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch {}
|
|
79
|
+
}
|
|
80
|
+
|
|
39
81
|
const associations = URL_META.resolveAssociations(chunks, rootDirectoryUrl);
|
|
40
|
-
manualChunks = (id) => {
|
|
82
|
+
manualChunks = (id, manualChunksApi) => {
|
|
41
83
|
if (rollupOutput.manualChunks) {
|
|
42
|
-
const manualChunkName = rollupOutput.manualChunks(id);
|
|
84
|
+
const manualChunkName = rollupOutput.manualChunks(id, manualChunksApi);
|
|
43
85
|
if (manualChunkName) {
|
|
44
86
|
return manualChunkName;
|
|
45
87
|
}
|
|
46
88
|
}
|
|
89
|
+
const moduleInfo = manualChunksApi.getModuleInfo(id);
|
|
90
|
+
if (moduleInfo.isEntry || moduleInfo.dynamicImporters.length) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
47
93
|
const url = fileUrlConverter.asFileUrl(id);
|
|
48
94
|
const urlObject = new URL(url);
|
|
49
95
|
urlObject.search = "";
|
|
@@ -52,8 +98,12 @@ export const bundleJsModules = async (
|
|
|
52
98
|
url: urlWithoutSearch,
|
|
53
99
|
associations,
|
|
54
100
|
});
|
|
55
|
-
const
|
|
56
|
-
|
|
101
|
+
for (const chunkNameCandidate of Object.keys(meta)) {
|
|
102
|
+
if (meta[chunkNameCandidate]) {
|
|
103
|
+
return chunkNameCandidate;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
57
107
|
};
|
|
58
108
|
}
|
|
59
109
|
|
|
@@ -91,6 +141,18 @@ export const bundleJsModules = async (
|
|
|
91
141
|
// ideally we should disable only for jsenv files
|
|
92
142
|
return;
|
|
93
143
|
}
|
|
144
|
+
if (
|
|
145
|
+
warning.code === "INVALID_ANNOTATION" &&
|
|
146
|
+
warning.loc.file.includes("/node_modules/")
|
|
147
|
+
) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (
|
|
151
|
+
warning.code === "EMPTY_BUNDLE" &&
|
|
152
|
+
warning.names.join("") === "vendors"
|
|
153
|
+
) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
94
156
|
logger.warn(String(warning));
|
|
95
157
|
},
|
|
96
158
|
...rollupInput,
|
|
@@ -126,6 +188,7 @@ export const bundleJsModules = async (
|
|
|
126
188
|
const rollupPluginJsenv = ({
|
|
127
189
|
// logger,
|
|
128
190
|
rootDirectoryUrl,
|
|
191
|
+
buildDirectoryUrl,
|
|
129
192
|
graph,
|
|
130
193
|
jsModuleUrlInfos,
|
|
131
194
|
sourcemaps,
|
|
@@ -163,16 +226,18 @@ const rollupPluginJsenv = ({
|
|
|
163
226
|
}
|
|
164
227
|
|
|
165
228
|
const getOriginalUrl = (rollupFileInfo) => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
229
|
+
if (rollupFileInfo.isEntry) {
|
|
230
|
+
const { facadeModuleId } = rollupFileInfo;
|
|
231
|
+
if (facadeModuleId) {
|
|
232
|
+
return fileUrlConverter.asFileUrl(facadeModuleId);
|
|
233
|
+
}
|
|
169
234
|
}
|
|
170
235
|
if (rollupFileInfo.isDynamicEntry) {
|
|
171
236
|
const { moduleIds } = rollupFileInfo;
|
|
172
237
|
const lastModuleId = moduleIds[moduleIds.length - 1];
|
|
173
238
|
return fileUrlConverter.asFileUrl(lastModuleId);
|
|
174
239
|
}
|
|
175
|
-
return new URL(rollupFileInfo.fileName,
|
|
240
|
+
return new URL(rollupFileInfo.fileName, buildDirectoryUrl).href;
|
|
176
241
|
};
|
|
177
242
|
|
|
178
243
|
return {
|
|
@@ -180,13 +245,13 @@ const rollupPluginJsenv = ({
|
|
|
180
245
|
async buildStart() {
|
|
181
246
|
_rollupEmitFile = (...args) => this.emitFile(...args);
|
|
182
247
|
let previousNonEntryPointModuleId;
|
|
183
|
-
|
|
248
|
+
for (const jsModuleUrlInfo of jsModuleUrlInfos) {
|
|
184
249
|
const id = jsModuleUrlInfo.url;
|
|
185
250
|
if (jsModuleUrlInfo.isEntryPoint) {
|
|
186
251
|
emitChunk({
|
|
187
252
|
id,
|
|
188
253
|
});
|
|
189
|
-
|
|
254
|
+
continue;
|
|
190
255
|
}
|
|
191
256
|
let preserveSignature;
|
|
192
257
|
if (strictExports) {
|
|
@@ -218,8 +283,10 @@ const rollupPluginJsenv = ({
|
|
|
218
283
|
: null,
|
|
219
284
|
preserveSignature,
|
|
220
285
|
});
|
|
221
|
-
|
|
222
|
-
|
|
286
|
+
if (jsModuleUrlInfo.originalUrl.startsWith("file:")) {
|
|
287
|
+
previousNonEntryPointModuleId = id;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
223
290
|
},
|
|
224
291
|
async generateBundle(outputOptions, rollupResult) {
|
|
225
292
|
_rollupEmitFile = (...args) => this.emitFile(...args);
|
|
@@ -291,16 +358,32 @@ const rollupPluginJsenv = ({
|
|
|
291
358
|
remapReference:
|
|
292
359
|
specifierToUrlMap.size > 0
|
|
293
360
|
? (reference) => {
|
|
294
|
-
// rollup generate specifiers only for static and dynamic imports
|
|
295
|
-
// other references (like new URL()) are ignored
|
|
296
|
-
// there is no need to remap them back
|
|
297
361
|
if (
|
|
298
|
-
|
|
299
|
-
reference.subtype
|
|
362
|
+
preserveDynamicImport &&
|
|
363
|
+
reference.subtype === "dynamic_import"
|
|
364
|
+
) {
|
|
365
|
+
// when dynamic import are preserved, no need to remap them
|
|
366
|
+
return reference.specifier;
|
|
367
|
+
}
|
|
368
|
+
if (
|
|
369
|
+
reference.type !== "js_import" ||
|
|
370
|
+
reference.subtype === "import_meta_resolve"
|
|
300
371
|
) {
|
|
301
|
-
|
|
372
|
+
// rollup generate specifiers only for static and dynamic imports
|
|
373
|
+
// other references (like new URL()) are ignored
|
|
374
|
+
// there is no need to remap them back
|
|
375
|
+
return reference.specifier;
|
|
302
376
|
}
|
|
303
|
-
|
|
377
|
+
const specifierBeforeRollup = specifierToUrlMap.get(
|
|
378
|
+
reference.specifier,
|
|
379
|
+
);
|
|
380
|
+
if (!specifierBeforeRollup) {
|
|
381
|
+
console.warn(
|
|
382
|
+
`cannot remap "${reference.specifier}" back to specifier before rollup, this is unexpected.`,
|
|
383
|
+
);
|
|
384
|
+
return reference.specifier;
|
|
385
|
+
}
|
|
386
|
+
return specifierBeforeRollup;
|
|
304
387
|
}
|
|
305
388
|
: undefined,
|
|
306
389
|
};
|
|
@@ -308,11 +391,19 @@ const rollupPluginJsenv = ({
|
|
|
308
391
|
|
|
309
392
|
const jsModuleBundleUrlInfos = {};
|
|
310
393
|
const fileNames = Object.keys(rollupResult);
|
|
394
|
+
const originalUrlSet = new Set();
|
|
311
395
|
for (const fileName of fileNames) {
|
|
312
396
|
const rollupFileInfo = rollupResult[fileName];
|
|
313
397
|
// there is 3 types of file: "placeholder", "asset", "chunk"
|
|
314
398
|
if (rollupFileInfo.type === "chunk") {
|
|
315
399
|
const jsModuleInfo = createBundledFileInfo(rollupFileInfo);
|
|
400
|
+
const originalUrl = jsModuleInfo.originalUrl;
|
|
401
|
+
if (originalUrlSet.has(originalUrl)) {
|
|
402
|
+
throw new Error(
|
|
403
|
+
`duplicate bundle info, cannot override ${originalUrl}`,
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
originalUrlSet.add(originalUrl);
|
|
316
407
|
jsModuleBundleUrlInfos[jsModuleInfo.originalUrl] = jsModuleInfo;
|
|
317
408
|
}
|
|
318
409
|
}
|
|
@@ -335,37 +426,45 @@ const rollupPluginJsenv = ({
|
|
|
335
426
|
return `[name].js`;
|
|
336
427
|
},
|
|
337
428
|
chunkFileNames: (chunkInfo) => {
|
|
429
|
+
if (chunkInfo.isEntry) {
|
|
430
|
+
const originalFileUrl = getOriginalUrl(chunkInfo);
|
|
431
|
+
const jsModuleUrlInfo = jsModuleUrlInfos.find(
|
|
432
|
+
(candidate) => candidate.url === originalFileUrl,
|
|
433
|
+
);
|
|
434
|
+
if (jsModuleUrlInfo && jsModuleUrlInfo.filenameHint) {
|
|
435
|
+
return jsModuleUrlInfo.filenameHint;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
338
438
|
return `${chunkInfo.name}.js`;
|
|
339
439
|
},
|
|
340
440
|
});
|
|
341
441
|
},
|
|
342
442
|
// https://rollupjs.org/guide/en/#resolvedynamicimport
|
|
343
443
|
resolveDynamicImport: (specifier, importer) => {
|
|
344
|
-
if (preserveDynamicImport) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
const searchParamsToAdd =
|
|
355
|
-
augmentDynamicImportUrlSearchParams(urlObject);
|
|
356
|
-
if (searchParamsToAdd) {
|
|
357
|
-
Object.keys(searchParamsToAdd).forEach((key) => {
|
|
358
|
-
const value = searchParamsToAdd[key];
|
|
359
|
-
if (value === undefined) {
|
|
360
|
-
urlObject.searchParams.delete(key);
|
|
361
|
-
} else {
|
|
362
|
-
urlObject.searchParams.set(key, value);
|
|
363
|
-
}
|
|
364
|
-
});
|
|
444
|
+
if (!preserveDynamicImport) {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
let urlObject;
|
|
448
|
+
if (specifier[0] === "/") {
|
|
449
|
+
urlObject = new URL(specifier.slice(1), rootDirectoryUrl);
|
|
450
|
+
} else {
|
|
451
|
+
if (isFileSystemPath(importer)) {
|
|
452
|
+
importer = fileUrlConverter.asFileUrl(importer);
|
|
365
453
|
}
|
|
366
|
-
|
|
454
|
+
urlObject = new URL(specifier, importer);
|
|
455
|
+
}
|
|
456
|
+
const searchParamsToAdd = augmentDynamicImportUrlSearchParams(urlObject);
|
|
457
|
+
if (searchParamsToAdd) {
|
|
458
|
+
Object.keys(searchParamsToAdd).forEach((key) => {
|
|
459
|
+
const value = searchParamsToAdd[key];
|
|
460
|
+
if (value === undefined) {
|
|
461
|
+
urlObject.searchParams.delete(key);
|
|
462
|
+
} else {
|
|
463
|
+
urlObject.searchParams.set(key, value);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
367
466
|
}
|
|
368
|
-
return
|
|
467
|
+
return { external: true, id: urlObject.href };
|
|
369
468
|
},
|
|
370
469
|
resolveId: (specifier, importer = rootDirectoryUrl) => {
|
|
371
470
|
if (isFileSystemPath(importer)) {
|
|
@@ -388,7 +487,7 @@ const rollupPluginJsenv = ({
|
|
|
388
487
|
// happen when excluded by referenceAnalysis.include
|
|
389
488
|
return { id: url, external: true };
|
|
390
489
|
}
|
|
391
|
-
if (
|
|
490
|
+
if (url.startsWith("ignore:")) {
|
|
392
491
|
return { id: url, external: true };
|
|
393
492
|
}
|
|
394
493
|
const filePath = fileUrlConverter.asFilePath(url);
|
|
@@ -419,8 +518,83 @@ const applyRollupPlugins = async ({
|
|
|
419
518
|
const rollupModule = await import("rollup");
|
|
420
519
|
rollup = rollupModule.rollup;
|
|
421
520
|
}
|
|
521
|
+
|
|
522
|
+
const packageSideEffectsCacheMap = new Map();
|
|
523
|
+
const readClosestPackageJsonSideEffects = (url) => {
|
|
524
|
+
const packageDirectoryUrl = lookupPackageDirectory(url);
|
|
525
|
+
if (!packageDirectoryUrl) {
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
const fromCache = packageSideEffectsCacheMap.get(packageDirectoryUrl);
|
|
529
|
+
if (fromCache) {
|
|
530
|
+
return fromCache.value;
|
|
531
|
+
}
|
|
532
|
+
try {
|
|
533
|
+
const packageFileContent = readFileSync(
|
|
534
|
+
new URL("./package.json", packageDirectoryUrl),
|
|
535
|
+
"utf8",
|
|
536
|
+
);
|
|
537
|
+
const packageJSON = JSON.parse(packageFileContent);
|
|
538
|
+
const value = packageJSON.sideEffects;
|
|
539
|
+
if (Array.isArray(value)) {
|
|
540
|
+
const sideEffectPatterns = {};
|
|
541
|
+
for (const v of value) {
|
|
542
|
+
sideEffectPatterns[v] = true;
|
|
543
|
+
}
|
|
544
|
+
const associations = URL_META.resolveAssociations(
|
|
545
|
+
{ sideEffects: sideEffectPatterns },
|
|
546
|
+
packageDirectoryUrl,
|
|
547
|
+
);
|
|
548
|
+
const isMatching = (url) => {
|
|
549
|
+
const meta = URL_META.applyAssociations({ url, associations });
|
|
550
|
+
return meta.sideEffects || false;
|
|
551
|
+
};
|
|
552
|
+
packageSideEffectsCacheMap.set(packageDirectoryUrl, {
|
|
553
|
+
value: isMatching,
|
|
554
|
+
});
|
|
555
|
+
} else {
|
|
556
|
+
packageSideEffectsCacheMap.set(packageDirectoryUrl, { value });
|
|
557
|
+
}
|
|
558
|
+
return value;
|
|
559
|
+
} catch {
|
|
560
|
+
packageSideEffectsCacheMap.set(packageDirectoryUrl, { value: undefined });
|
|
561
|
+
return undefined;
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
|
|
422
565
|
const rollupReturnValue = await rollup({
|
|
423
566
|
...rollupInput,
|
|
567
|
+
treeshake: {
|
|
568
|
+
...rollupInput.treeshake,
|
|
569
|
+
moduleSideEffects: (id, external) => {
|
|
570
|
+
if (id.startsWith("ignore:node:")) {
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
if (isSpecifierForNodeBuiltin(id)) {
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
if (id.startsWith("ignore:")) {
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
const url = id.startsWith("file:") ? id : fileSystemPathToUrl(id);
|
|
580
|
+
const closestPackageJsonSideEffects =
|
|
581
|
+
readClosestPackageJsonSideEffects(url);
|
|
582
|
+
if (closestPackageJsonSideEffects !== undefined) {
|
|
583
|
+
if (typeof closestPackageJsonSideEffects === "function") {
|
|
584
|
+
return closestPackageJsonSideEffects(url);
|
|
585
|
+
}
|
|
586
|
+
return closestPackageJsonSideEffects;
|
|
587
|
+
}
|
|
588
|
+
const moduleSideEffects = rollupInput.treeshake?.moduleSideEffects;
|
|
589
|
+
if (moduleSideEffects) {
|
|
590
|
+
if (typeof moduleSideEffects === "function") {
|
|
591
|
+
return moduleSideEffects(id, external);
|
|
592
|
+
}
|
|
593
|
+
return moduleSideEffects;
|
|
594
|
+
}
|
|
595
|
+
return null;
|
|
596
|
+
},
|
|
597
|
+
},
|
|
424
598
|
plugins: rollupPlugins,
|
|
425
599
|
});
|
|
426
600
|
const rollupOutputArray = await rollupReturnValue.generate(rollupOutput);
|