@jsenv/plugin-bundling 2.8.0 → 2.8.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.
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.2",
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.3",
28
+ "@jsenv/sourcemap": "1.3.2",
29
+ "lightningcss": "1.29.2",
30
+ "rollup": "4.35.0"
30
31
  },
31
32
  "peerDependencies": {
32
33
  "@jsenv/core": "*"
@@ -1,8 +1,9 @@
1
- import { lookupPackageDirectory } from "@jsenv/filesystem";
1
+ import { lookupPackageDirectory, readPackageAtOrNull } 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
 
@@ -37,44 +38,44 @@ export const bundleJsModules = async (
37
38
 
38
39
  let manualChunks;
39
40
  if (chunks) {
40
- if (chunks.vendors) {
41
- chunks.vendors = {
42
- "file:///**/node_modules/": true,
43
- ...chunks.vendors,
44
- };
45
- } else {
46
- chunks.vendors = {
47
- "file:///**/node_modules/": true,
48
- };
49
- }
41
+ let workspaces;
42
+ let packageName;
50
43
  const packageDirectoryUrl = lookupPackageDirectory(rootDirectoryUrl);
51
44
  if (packageDirectoryUrl) {
52
- try {
53
- const packageFileContent = readFileSync(
54
- new URL("package.json", packageDirectoryUrl),
55
- "utf8",
56
- );
57
- const packageJSON = JSON.parse(packageFileContent);
58
- const workspaces = packageJSON.workspaces;
59
- if (workspaces) {
60
- const workspacePatterns = {};
61
- for (const workspace of workspaces) {
62
- const workspacePattern = new URL(
63
- workspace.endsWith("/*") ? workspace.slice(0, -1) : workspace,
64
- packageDirectoryUrl,
65
- ).href;
66
- workspacePatterns[workspacePattern] = true;
67
- }
68
- if (chunks.workspaces) {
69
- chunks.workspaces = {
70
- ...workspacePatterns,
71
- ...chunks.workspaces,
72
- };
73
- } else {
74
- chunks.workspaces = workspacePatterns;
75
- }
76
- }
77
- } catch {}
45
+ const packageJSON = readPackageAtOrNull(packageDirectoryUrl);
46
+ if (packageJSON) {
47
+ packageName = packageJSON.name;
48
+ workspaces = packageJSON.workspaces;
49
+ }
50
+ }
51
+ let nodeModuleChunkName = "node_modules";
52
+ let packagesChunkName = "packages";
53
+
54
+ if (packageName) {
55
+ let packageNameAsFilename = packageName
56
+ .replaceAll("@", "")
57
+ .replaceAll("-", "_")
58
+ .replaceAll("/", "_");
59
+ nodeModuleChunkName = `${packageNameAsFilename}_node_modules`;
60
+ packagesChunkName = `${packageNameAsFilename}_packages`;
61
+ }
62
+ chunks[nodeModuleChunkName] = {
63
+ "file:///**/node_modules/": true,
64
+ ...chunks.vendors,
65
+ };
66
+ if (workspaces) {
67
+ const workspacePatterns = {};
68
+ for (const workspace of workspaces) {
69
+ const workspacePattern = new URL(
70
+ workspace.endsWith("/*") ? workspace.slice(0, -1) : workspace,
71
+ packageDirectoryUrl,
72
+ ).href;
73
+ workspacePatterns[workspacePattern] = true;
74
+ }
75
+ chunks[packagesChunkName] = {
76
+ ...workspacePatterns,
77
+ ...chunks.workspaces,
78
+ };
78
79
  }
79
80
 
80
81
  const associations = URL_META.resolveAssociations(chunks, rootDirectoryUrl);
@@ -146,6 +147,13 @@ export const bundleJsModules = async (
146
147
  ) {
147
148
  return;
148
149
  }
150
+ if (
151
+ warning.code === "EMPTY_BUNDLE" &&
152
+ (warning.names.join("").endsWith("node_modules") ||
153
+ warning.names.join("").endsWith("packages"))
154
+ ) {
155
+ return;
156
+ }
149
157
  logger.warn(String(warning));
150
158
  },
151
159
  ...rollupInput,
@@ -181,6 +189,7 @@ export const bundleJsModules = async (
181
189
  const rollupPluginJsenv = ({
182
190
  // logger,
183
191
  rootDirectoryUrl,
192
+ buildDirectoryUrl,
184
193
  graph,
185
194
  jsModuleUrlInfos,
186
195
  sourcemaps,
@@ -218,16 +227,24 @@ const rollupPluginJsenv = ({
218
227
  }
219
228
 
220
229
  const getOriginalUrl = (rollupFileInfo) => {
221
- const { facadeModuleId } = rollupFileInfo;
222
- if (facadeModuleId) {
223
- return fileUrlConverter.asFileUrl(facadeModuleId);
230
+ if (
231
+ // - explicitely emitted by emitChunk
232
+ // - import.meta.resolve("")
233
+ rollupFileInfo.isEntry ||
234
+ // - new URL("", import.meta.url)
235
+ rollupFileInfo.isImplicitEntry
236
+ ) {
237
+ const { facadeModuleId } = rollupFileInfo;
238
+ if (facadeModuleId) {
239
+ return fileUrlConverter.asFileUrl(facadeModuleId);
240
+ }
224
241
  }
225
242
  if (rollupFileInfo.isDynamicEntry) {
226
243
  const { moduleIds } = rollupFileInfo;
227
244
  const lastModuleId = moduleIds[moduleIds.length - 1];
228
245
  return fileUrlConverter.asFileUrl(lastModuleId);
229
246
  }
230
- return new URL(rollupFileInfo.fileName, rootDirectoryUrl).href;
247
+ return new URL(rollupFileInfo.fileName, buildDirectoryUrl).href;
231
248
  };
232
249
 
233
250
  return {
@@ -381,11 +398,19 @@ const rollupPluginJsenv = ({
381
398
 
382
399
  const jsModuleBundleUrlInfos = {};
383
400
  const fileNames = Object.keys(rollupResult);
401
+ const originalUrlSet = new Set();
384
402
  for (const fileName of fileNames) {
385
403
  const rollupFileInfo = rollupResult[fileName];
386
404
  // there is 3 types of file: "placeholder", "asset", "chunk"
387
405
  if (rollupFileInfo.type === "chunk") {
388
406
  const jsModuleInfo = createBundledFileInfo(rollupFileInfo);
407
+ const originalUrl = jsModuleInfo.originalUrl;
408
+ if (originalUrlSet.has(originalUrl)) {
409
+ throw new Error(
410
+ `duplicate bundle info, cannot override ${originalUrl}`,
411
+ );
412
+ }
413
+ originalUrlSet.add(originalUrl);
389
414
  jsModuleBundleUrlInfos[jsModuleInfo.originalUrl] = jsModuleInfo;
390
415
  }
391
416
  }
@@ -408,6 +433,15 @@ const rollupPluginJsenv = ({
408
433
  return `[name].js`;
409
434
  },
410
435
  chunkFileNames: (chunkInfo) => {
436
+ if (chunkInfo.isEntry) {
437
+ const originalFileUrl = getOriginalUrl(chunkInfo);
438
+ const jsModuleUrlInfo = jsModuleUrlInfos.find(
439
+ (candidate) => candidate.url === originalFileUrl,
440
+ );
441
+ if (jsModuleUrlInfo && jsModuleUrlInfo.filenameHint) {
442
+ return jsModuleUrlInfo.filenameHint;
443
+ }
444
+ }
411
445
  return `${chunkInfo.name}.js`;
412
446
  },
413
447
  });
@@ -460,7 +494,7 @@ const rollupPluginJsenv = ({
460
494
  // happen when excluded by referenceAnalysis.include
461
495
  return { id: url, external: true };
462
496
  }
463
- if (urlInfo.url.startsWith("ignore:")) {
497
+ if (url.startsWith("ignore:")) {
464
498
  return { id: url, external: true };
465
499
  }
466
500
  const filePath = fileUrlConverter.asFilePath(url);
@@ -491,8 +525,83 @@ const applyRollupPlugins = async ({
491
525
  const rollupModule = await import("rollup");
492
526
  rollup = rollupModule.rollup;
493
527
  }
528
+
529
+ const packageSideEffectsCacheMap = new Map();
530
+ const readClosestPackageJsonSideEffects = (url) => {
531
+ const packageDirectoryUrl = lookupPackageDirectory(url);
532
+ if (!packageDirectoryUrl) {
533
+ return undefined;
534
+ }
535
+ const fromCache = packageSideEffectsCacheMap.get(packageDirectoryUrl);
536
+ if (fromCache) {
537
+ return fromCache.value;
538
+ }
539
+ try {
540
+ const packageFileContent = readFileSync(
541
+ new URL("./package.json", packageDirectoryUrl),
542
+ "utf8",
543
+ );
544
+ const packageJSON = JSON.parse(packageFileContent);
545
+ const value = packageJSON.sideEffects;
546
+ if (Array.isArray(value)) {
547
+ const sideEffectPatterns = {};
548
+ for (const v of value) {
549
+ sideEffectPatterns[v] = true;
550
+ }
551
+ const associations = URL_META.resolveAssociations(
552
+ { sideEffects: sideEffectPatterns },
553
+ packageDirectoryUrl,
554
+ );
555
+ const isMatching = (url) => {
556
+ const meta = URL_META.applyAssociations({ url, associations });
557
+ return meta.sideEffects || false;
558
+ };
559
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
560
+ value: isMatching,
561
+ });
562
+ } else {
563
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, { value });
564
+ }
565
+ return value;
566
+ } catch {
567
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, { value: undefined });
568
+ return undefined;
569
+ }
570
+ };
571
+
494
572
  const rollupReturnValue = await rollup({
495
573
  ...rollupInput,
574
+ treeshake: {
575
+ ...rollupInput.treeshake,
576
+ moduleSideEffects: (id, external) => {
577
+ if (id.startsWith("ignore:node:")) {
578
+ return false;
579
+ }
580
+ if (isSpecifierForNodeBuiltin(id)) {
581
+ return false;
582
+ }
583
+ if (id.startsWith("ignore:")) {
584
+ return null;
585
+ }
586
+ const url = id.startsWith("file:") ? id : fileSystemPathToUrl(id);
587
+ const closestPackageJsonSideEffects =
588
+ readClosestPackageJsonSideEffects(url);
589
+ if (closestPackageJsonSideEffects !== undefined) {
590
+ if (typeof closestPackageJsonSideEffects === "function") {
591
+ return closestPackageJsonSideEffects(url);
592
+ }
593
+ return closestPackageJsonSideEffects;
594
+ }
595
+ const moduleSideEffects = rollupInput.treeshake?.moduleSideEffects;
596
+ if (moduleSideEffects) {
597
+ if (typeof moduleSideEffects === "function") {
598
+ return moduleSideEffects(id, external);
599
+ }
600
+ return moduleSideEffects;
601
+ }
602
+ return null;
603
+ },
604
+ },
496
605
  plugins: rollupPlugins,
497
606
  });
498
607
  const rollupOutputArray = await rollupReturnValue.generate(rollupOutput);