@jsenv/plugin-bundling 2.8.1 → 2.8.3

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.1",
3
+ "version": "2.8.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,8 +24,8 @@
24
24
  "dependencies": {
25
25
  "@jsenv/humanize": "1.3.1",
26
26
  "@jsenv/url-meta": "8.5.4",
27
- "@jsenv/urls": "2.6.2",
28
- "@jsenv/sourcemap": "1.3.1",
27
+ "@jsenv/urls": "2.6.3",
28
+ "@jsenv/sourcemap": "1.3.2",
29
29
  "lightningcss": "1.29.2",
30
30
  "rollup": "4.35.0"
31
31
  },
@@ -1,9 +1,10 @@
1
- import { lookupPackageDirectory } from "@jsenv/filesystem";
1
+ import { lookupPackageDirectory, readPackageAtOrNull } from "@jsenv/filesystem";
2
2
  import { createDetailedMessage } from "@jsenv/humanize";
3
+ import { applyNodeEsmResolution } from "@jsenv/node-esm-resolution";
3
4
  import { isSpecifierForNodeBuiltin } from "@jsenv/node-esm-resolution/src/node_builtin_specifiers.js";
4
5
  import { sourcemapConverter } from "@jsenv/sourcemap";
5
6
  import { URL_META } from "@jsenv/url-meta";
6
- import { fileSystemPathToUrl, isFileSystemPath } from "@jsenv/urls";
7
+ import { isFileSystemPath } from "@jsenv/urls";
7
8
  import { readFileSync } from "node:fs";
8
9
  import { fileUrlConverter } from "../file_url_converter.js";
9
10
 
@@ -38,44 +39,44 @@ export const bundleJsModules = async (
38
39
 
39
40
  let manualChunks;
40
41
  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
- }
42
+ let workspaces;
43
+ let packageName;
51
44
  const packageDirectoryUrl = lookupPackageDirectory(rootDirectoryUrl);
52
45
  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 {}
46
+ const packageJSON = readPackageAtOrNull(packageDirectoryUrl);
47
+ if (packageJSON) {
48
+ packageName = packageJSON.name;
49
+ workspaces = packageJSON.workspaces;
50
+ }
51
+ }
52
+ let nodeModuleChunkName = "node_modules";
53
+ let packagesChunkName = "packages";
54
+
55
+ if (packageName) {
56
+ let packageNameAsFilename = packageName
57
+ .replaceAll("@", "")
58
+ .replaceAll("-", "_")
59
+ .replaceAll("/", "_");
60
+ nodeModuleChunkName = `${packageNameAsFilename}_node_modules`;
61
+ packagesChunkName = `${packageNameAsFilename}_packages`;
62
+ }
63
+ chunks[nodeModuleChunkName] = {
64
+ "file:///**/node_modules/": true,
65
+ ...chunks.vendors,
66
+ };
67
+ if (workspaces) {
68
+ const workspacePatterns = {};
69
+ for (const workspace of workspaces) {
70
+ const workspacePattern = new URL(
71
+ workspace.endsWith("/*") ? workspace.slice(0, -1) : workspace,
72
+ packageDirectoryUrl,
73
+ ).href;
74
+ workspacePatterns[workspacePattern] = true;
75
+ }
76
+ chunks[packagesChunkName] = {
77
+ ...workspacePatterns,
78
+ ...chunks.workspaces,
79
+ };
79
80
  }
80
81
 
81
82
  const associations = URL_META.resolveAssociations(chunks, rootDirectoryUrl);
@@ -149,7 +150,8 @@ export const bundleJsModules = async (
149
150
  }
150
151
  if (
151
152
  warning.code === "EMPTY_BUNDLE" &&
152
- warning.names.join("") === "vendors"
153
+ (warning.names.join("").endsWith("node_modules") ||
154
+ warning.names.join("").endsWith("packages"))
153
155
  ) {
154
156
  return;
155
157
  }
@@ -191,8 +193,9 @@ const rollupPluginJsenv = ({
191
193
  buildDirectoryUrl,
192
194
  graph,
193
195
  jsModuleUrlInfos,
194
- sourcemaps,
195
196
 
197
+ runtimeCompat,
198
+ sourcemaps,
196
199
  include,
197
200
  preserveDynamicImport,
198
201
  augmentDynamicImportUrlSearchParams,
@@ -226,7 +229,13 @@ const rollupPluginJsenv = ({
226
229
  }
227
230
 
228
231
  const getOriginalUrl = (rollupFileInfo) => {
229
- if (rollupFileInfo.isEntry) {
232
+ if (
233
+ // - explicitely emitted by emitChunk
234
+ // - import.meta.resolve("")
235
+ rollupFileInfo.isEntry ||
236
+ // - new URL("", import.meta.url)
237
+ rollupFileInfo.isImplicitEntry
238
+ ) {
230
239
  const { facadeModuleId } = rollupFileInfo;
231
240
  if (facadeModuleId) {
232
241
  return fileUrlConverter.asFileUrl(facadeModuleId);
@@ -240,6 +249,94 @@ const rollupPluginJsenv = ({
240
249
  return new URL(rollupFileInfo.fileName, buildDirectoryUrl).href;
241
250
  };
242
251
 
252
+ const packageSideEffectsCacheMap = new Map();
253
+ const readClosestPackageJsonSideEffects = (url) => {
254
+ const packageDirectoryUrl = lookupPackageDirectory(url);
255
+ if (!packageDirectoryUrl) {
256
+ return undefined;
257
+ }
258
+ const fromCache = packageSideEffectsCacheMap.get(packageDirectoryUrl);
259
+ if (fromCache) {
260
+ return fromCache.value;
261
+ }
262
+ try {
263
+ const packageFileContent = readFileSync(
264
+ new URL("./package.json", packageDirectoryUrl),
265
+ "utf8",
266
+ );
267
+ const packageJSON = JSON.parse(packageFileContent);
268
+ const value = packageJSON.sideEffects;
269
+ if (Array.isArray(value)) {
270
+ const sideEffectPatterns = {};
271
+ for (const v of value) {
272
+ sideEffectPatterns[v] = true;
273
+ }
274
+ const associations = URL_META.resolveAssociations(
275
+ { sideEffects: sideEffectPatterns },
276
+ packageDirectoryUrl,
277
+ );
278
+ const isMatching = (url) => {
279
+ const meta = URL_META.applyAssociations({ url, associations });
280
+ return meta.sideEffects || false;
281
+ };
282
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
283
+ value: isMatching,
284
+ });
285
+ } else {
286
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, { value });
287
+ }
288
+ return value;
289
+ } catch {
290
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, { value: undefined });
291
+ return undefined;
292
+ }
293
+ };
294
+ const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
295
+ const packageConditions = [nodeRuntimeEnabled ? "node" : "browser", "import"];
296
+ const inferSideEffectsFromResolvedUrl = (url) => {
297
+ if (url.startsWith("ignore:")) {
298
+ // console.log(`may have side effect: ${url}`);
299
+ // double ignore we must keep the import
300
+ return null;
301
+ }
302
+ if (isSpecifierForNodeBuiltin(url)) {
303
+ return false;
304
+ }
305
+ const closestPackageJsonSideEffects =
306
+ readClosestPackageJsonSideEffects(url);
307
+ if (closestPackageJsonSideEffects === undefined) {
308
+ // console.log(`may have side effect: ${url}`);
309
+ return null;
310
+ }
311
+ if (typeof closestPackageJsonSideEffects === "function") {
312
+ const haveSideEffect = closestPackageJsonSideEffects(url);
313
+ // if (haveSideEffect) {
314
+ // console.log(`have side effect: ${url}`);
315
+ // }
316
+ return haveSideEffect;
317
+ }
318
+ return closestPackageJsonSideEffects;
319
+ };
320
+ const getModuleSideEffects = (url, importer) => {
321
+ if (!url.startsWith("ignore:")) {
322
+ return inferSideEffectsFromResolvedUrl(url);
323
+ }
324
+ url = url.slice("ignore:".length);
325
+ if (url.startsWith("file:")) {
326
+ return inferSideEffectsFromResolvedUrl(url);
327
+ }
328
+ try {
329
+ const result = applyNodeEsmResolution({
330
+ conditions: packageConditions,
331
+ parentUrl: importer,
332
+ specifier: url,
333
+ });
334
+ return inferSideEffectsFromResolvedUrl(result.url);
335
+ } catch {
336
+ return null;
337
+ }
338
+ };
339
+
243
340
  return {
244
341
  name: "jsenv",
245
342
  async buildStart() {
@@ -476,22 +573,43 @@ const rollupPluginJsenv = ({
476
573
  } else {
477
574
  url = new URL(specifier, importer).href;
478
575
  }
576
+
479
577
  if (!url.startsWith("file:")) {
480
- return { id: url, external: true };
578
+ return {
579
+ id: url,
580
+ external: true,
581
+ moduleSideEffects: getModuleSideEffects(url, importer),
582
+ };
481
583
  }
482
584
  if (!importCanBeBundled(url)) {
483
- return { id: url, external: true };
585
+ return {
586
+ id: url,
587
+ external: true,
588
+ moduleSideEffects: getModuleSideEffects(url, importer),
589
+ };
484
590
  }
485
591
  const urlInfo = graph.getUrlInfo(url);
486
592
  if (!urlInfo) {
487
593
  // happen when excluded by referenceAnalysis.include
488
- return { id: url, external: true };
594
+ return {
595
+ id: url,
596
+ external: true,
597
+ moduleSideEffects: getModuleSideEffects(url, importer),
598
+ };
489
599
  }
490
600
  if (url.startsWith("ignore:")) {
491
- return { id: url, external: true };
601
+ return {
602
+ id: url,
603
+ external: true,
604
+ moduleSideEffects: getModuleSideEffects(url, importer),
605
+ };
492
606
  }
493
607
  const filePath = fileUrlConverter.asFilePath(url);
494
- return filePath;
608
+ return {
609
+ id: filePath,
610
+ external: false,
611
+ moduleSideEffects: getModuleSideEffects(url, importer),
612
+ };
495
613
  },
496
614
  async load(rollupId) {
497
615
  const fileUrl = fileUrlConverter.asFileUrl(rollupId);
@@ -519,81 +637,10 @@ const applyRollupPlugins = async ({
519
637
  rollup = rollupModule.rollup;
520
638
  }
521
639
 
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
-
565
640
  const rollupReturnValue = await rollup({
566
641
  ...rollupInput,
567
642
  treeshake: {
568
643
  ...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
644
  },
598
645
  plugins: rollupPlugins,
599
646
  });