@jsenv/plugin-bundling 2.8.0 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/plugin-bundling",
3
- "version": "2.8.0",
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.3.0",
25
+ "@jsenv/humanize": "1.3.1",
25
26
  "@jsenv/url-meta": "8.5.4",
26
- "@jsenv/urls": "2.6.1",
27
- "@jsenv/sourcemap": "1.3.0",
28
- "lightningcss": "1.29.1",
29
- "rollup": "4.31.0"
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,9 @@
1
1
  import { lookupPackageDirectory } from "@jsenv/filesystem";
2
2
  import { createDetailedMessage } from "@jsenv/humanize";
3
+ import { isSpecifierForNodeBuiltin } from "@jsenv/node-esm-resolution/src/node_builtin_specifiers.js";
3
4
  import { sourcemapConverter } from "@jsenv/sourcemap";
4
5
  import { URL_META } from "@jsenv/url-meta";
5
- import { isFileSystemPath } from "@jsenv/urls";
6
+ import { fileSystemPathToUrl, isFileSystemPath } from "@jsenv/urls";
6
7
  import { readFileSync } from "node:fs";
7
8
  import { fileUrlConverter } from "../file_url_converter.js";
8
9
 
@@ -146,6 +147,12 @@ export const bundleJsModules = async (
146
147
  ) {
147
148
  return;
148
149
  }
150
+ if (
151
+ warning.code === "EMPTY_BUNDLE" &&
152
+ warning.names.join("") === "vendors"
153
+ ) {
154
+ return;
155
+ }
149
156
  logger.warn(String(warning));
150
157
  },
151
158
  ...rollupInput,
@@ -181,6 +188,7 @@ export const bundleJsModules = async (
181
188
  const rollupPluginJsenv = ({
182
189
  // logger,
183
190
  rootDirectoryUrl,
191
+ buildDirectoryUrl,
184
192
  graph,
185
193
  jsModuleUrlInfos,
186
194
  sourcemaps,
@@ -218,16 +226,18 @@ const rollupPluginJsenv = ({
218
226
  }
219
227
 
220
228
  const getOriginalUrl = (rollupFileInfo) => {
221
- const { facadeModuleId } = rollupFileInfo;
222
- if (facadeModuleId) {
223
- return fileUrlConverter.asFileUrl(facadeModuleId);
229
+ if (rollupFileInfo.isEntry) {
230
+ const { facadeModuleId } = rollupFileInfo;
231
+ if (facadeModuleId) {
232
+ return fileUrlConverter.asFileUrl(facadeModuleId);
233
+ }
224
234
  }
225
235
  if (rollupFileInfo.isDynamicEntry) {
226
236
  const { moduleIds } = rollupFileInfo;
227
237
  const lastModuleId = moduleIds[moduleIds.length - 1];
228
238
  return fileUrlConverter.asFileUrl(lastModuleId);
229
239
  }
230
- return new URL(rollupFileInfo.fileName, rootDirectoryUrl).href;
240
+ return new URL(rollupFileInfo.fileName, buildDirectoryUrl).href;
231
241
  };
232
242
 
233
243
  return {
@@ -381,11 +391,19 @@ const rollupPluginJsenv = ({
381
391
 
382
392
  const jsModuleBundleUrlInfos = {};
383
393
  const fileNames = Object.keys(rollupResult);
394
+ const originalUrlSet = new Set();
384
395
  for (const fileName of fileNames) {
385
396
  const rollupFileInfo = rollupResult[fileName];
386
397
  // there is 3 types of file: "placeholder", "asset", "chunk"
387
398
  if (rollupFileInfo.type === "chunk") {
388
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);
389
407
  jsModuleBundleUrlInfos[jsModuleInfo.originalUrl] = jsModuleInfo;
390
408
  }
391
409
  }
@@ -408,6 +426,15 @@ const rollupPluginJsenv = ({
408
426
  return `[name].js`;
409
427
  },
410
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
+ }
411
438
  return `${chunkInfo.name}.js`;
412
439
  },
413
440
  });
@@ -460,7 +487,7 @@ const rollupPluginJsenv = ({
460
487
  // happen when excluded by referenceAnalysis.include
461
488
  return { id: url, external: true };
462
489
  }
463
- if (urlInfo.url.startsWith("ignore:")) {
490
+ if (url.startsWith("ignore:")) {
464
491
  return { id: url, external: true };
465
492
  }
466
493
  const filePath = fileUrlConverter.asFilePath(url);
@@ -491,8 +518,83 @@ const applyRollupPlugins = async ({
491
518
  const rollupModule = await import("rollup");
492
519
  rollup = rollupModule.rollup;
493
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
+
494
565
  const rollupReturnValue = await rollup({
495
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
+ },
496
598
  plugins: rollupPlugins,
497
599
  });
498
600
  const rollupOutputArray = await rollupReturnValue.generate(rollupOutput);