@atlaspack/core 2.16.2-canary.13 → 2.16.2-canary.131

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.
Files changed (95) hide show
  1. package/CHANGELOG.md +300 -0
  2. package/index.d.ts +4 -0
  3. package/lib/AssetGraph.js +27 -7
  4. package/lib/Atlaspack.js +35 -27
  5. package/lib/AtlaspackConfig.schema.js +7 -1
  6. package/lib/BundleGraph.js +8 -5
  7. package/lib/Dependency.js +6 -2
  8. package/lib/Environment.js +5 -3
  9. package/lib/EnvironmentManager.js +137 -0
  10. package/lib/InternalConfig.js +3 -2
  11. package/lib/PackagerRunner.js +54 -16
  12. package/lib/RequestTracker.js +345 -132
  13. package/lib/SymbolPropagation.js +14 -0
  14. package/lib/Transformation.js +2 -2
  15. package/lib/UncommittedAsset.js +20 -2
  16. package/lib/applyRuntimes.js +2 -1
  17. package/lib/assetUtils.js +2 -1
  18. package/lib/atlaspack-v3/AtlaspackV3.js +16 -3
  19. package/lib/atlaspack-v3/worker/compat/environment.js +2 -2
  20. package/lib/atlaspack-v3/worker/compat/mutable-asset.js +6 -6
  21. package/lib/atlaspack-v3/worker/compat/plugin-config.js +5 -5
  22. package/lib/atlaspack-v3/worker/index.js +3 -0
  23. package/lib/atlaspack-v3/worker/worker.js +8 -0
  24. package/lib/dumpGraphToGraphViz.js +1 -1
  25. package/lib/index.js +29 -1
  26. package/lib/public/Asset.js +7 -9
  27. package/lib/public/Bundle.js +12 -13
  28. package/lib/public/BundleGraph.js +3 -2
  29. package/lib/public/BundleGroup.js +2 -3
  30. package/lib/public/Config.js +95 -8
  31. package/lib/public/Dependency.js +4 -4
  32. package/lib/public/Environment.js +2 -3
  33. package/lib/public/MutableBundleGraph.js +5 -4
  34. package/lib/public/PluginOptions.js +1 -2
  35. package/lib/public/Target.js +4 -4
  36. package/lib/requests/AssetGraphRequest.js +13 -1
  37. package/lib/requests/AssetGraphRequestRust.js +17 -2
  38. package/lib/requests/AssetRequest.js +2 -1
  39. package/lib/requests/BundleGraphRequest.js +13 -1
  40. package/lib/requests/ConfigRequest.js +27 -4
  41. package/lib/requests/DevDepRequest.js +11 -1
  42. package/lib/requests/PathRequest.js +10 -0
  43. package/lib/requests/TargetRequest.js +18 -16
  44. package/lib/requests/WriteBundleRequest.js +15 -3
  45. package/lib/requests/WriteBundlesRequest.js +22 -1
  46. package/lib/resolveOptions.js +7 -4
  47. package/lib/worker.js +18 -1
  48. package/package.json +18 -25
  49. package/src/AssetGraph.js +30 -7
  50. package/src/Atlaspack.js +40 -23
  51. package/src/BundleGraph.js +13 -8
  52. package/src/Dependency.js +13 -5
  53. package/src/Environment.js +9 -6
  54. package/src/EnvironmentManager.js +145 -0
  55. package/src/InternalConfig.js +6 -5
  56. package/src/PackagerRunner.js +72 -20
  57. package/src/RequestTracker.js +526 -157
  58. package/src/SymbolPropagation.js +13 -1
  59. package/src/UncommittedAsset.js +23 -3
  60. package/src/applyRuntimes.js +6 -1
  61. package/src/assetUtils.js +4 -3
  62. package/src/atlaspack-v3/AtlaspackV3.js +24 -3
  63. package/src/atlaspack-v3/worker/compat/plugin-config.js +9 -5
  64. package/src/atlaspack-v3/worker/index.js +2 -1
  65. package/src/atlaspack-v3/worker/worker.js +7 -0
  66. package/src/index.js +5 -1
  67. package/src/public/Asset.js +13 -6
  68. package/src/public/Bundle.js +12 -11
  69. package/src/public/BundleGraph.js +10 -2
  70. package/src/public/BundleGroup.js +2 -2
  71. package/src/public/Config.js +132 -18
  72. package/src/public/Dependency.js +4 -3
  73. package/src/public/Environment.js +2 -2
  74. package/src/public/MutableBundleGraph.js +8 -5
  75. package/src/public/PluginOptions.js +1 -1
  76. package/src/public/Target.js +4 -3
  77. package/src/requests/AssetGraphRequest.js +13 -3
  78. package/src/requests/AssetGraphRequestRust.js +14 -2
  79. package/src/requests/AssetRequest.js +2 -1
  80. package/src/requests/BundleGraphRequest.js +13 -3
  81. package/src/requests/ConfigRequest.js +33 -9
  82. package/src/requests/DevDepRequest.js +22 -9
  83. package/src/requests/PathRequest.js +4 -0
  84. package/src/requests/TargetRequest.js +19 -25
  85. package/src/requests/WriteBundleRequest.js +14 -8
  86. package/src/requests/WriteBundlesRequest.js +31 -3
  87. package/src/resolveOptions.js +4 -2
  88. package/src/types.js +10 -7
  89. package/test/Environment.test.js +43 -34
  90. package/test/EnvironmentManager.test.js +192 -0
  91. package/test/PublicEnvironment.test.js +10 -7
  92. package/test/RequestTracker.test.js +124 -29
  93. package/test/public/Config.test.js +108 -0
  94. package/test/requests/ConfigRequest.test.js +199 -7
  95. package/test/test-utils.js +4 -9
@@ -11,6 +11,7 @@ import type {
11
11
  } from '@atlaspack/types';
12
12
  import type {
13
13
  AtlaspackOptions,
14
+ BundleGraphNode,
14
15
  BundleGroup as InternalBundleGroup,
15
16
  BundleNode,
16
17
  } from '../types';
@@ -32,6 +33,7 @@ import {BundleBehavior} from '../types';
32
33
  import BundleGroup, {bundleGroupToInternalBundleGroup} from './BundleGroup';
33
34
  import type {ProjectPath} from '../projectPath';
34
35
  import {identifierRegistry} from '../IdentifierRegistry';
36
+ import {toEnvironmentRef} from '../EnvironmentManager';
35
37
 
36
38
  function createBundleId(data: {|
37
39
  entryAssetId: string | null,
@@ -53,9 +55,9 @@ export default class MutableBundleGraph
53
55
  extends BundleGraph<IBundle>
54
56
  implements IMutableBundleGraph
55
57
  {
56
- #graph /*: InternalBundleGraph */;
57
- #options /*: AtlaspackOptions */;
58
- #bundlePublicIds /*: Set<string> */ = new Set<string>();
58
+ #graph: InternalBundleGraph;
59
+ #options: AtlaspackOptions;
60
+ #bundlePublicIds: Set<string> = new Set<string>();
59
61
 
60
62
  constructor(graph: InternalBundleGraph, options: AtlaspackOptions) {
61
63
  super(graph, Bundle.get.bind(Bundle), options);
@@ -206,7 +208,8 @@ export default class MutableBundleGraph
206
208
  bundleBehavior: opts.bundleBehavior ?? null,
207
209
  });
208
210
 
209
- let existing = this.#graph._graph.getNodeByContentKey(bundleId);
211
+ let existing: ?BundleGraphNode =
212
+ this.#graph._graph.getNodeByContentKey(bundleId);
210
213
  if (existing != null) {
211
214
  invariant(existing.type === 'bundle');
212
215
  return Bundle.get(existing.value, this.#graph, this.#options);
@@ -236,7 +239,7 @@ export default class MutableBundleGraph
236
239
  : bundleId.slice(-8),
237
240
  type: opts.entryAsset ? opts.entryAsset.type : opts.type,
238
241
  env: opts.env
239
- ? environmentToInternalEnvironment(opts.env)
242
+ ? toEnvironmentRef(environmentToInternalEnvironment(opts.env))
240
243
  : nullthrows(entryAsset).env,
241
244
  entryAssetIds: entryAsset ? [entryAsset.id] : [],
242
245
  mainEntryId: entryAsset?.id,
@@ -18,7 +18,7 @@ let parcelOptionsToPluginOptions: WeakMap<AtlaspackOptions, PluginOptions> =
18
18
  new WeakMap();
19
19
 
20
20
  export default class PluginOptions implements IPluginOptions {
21
- #options /*: AtlaspackOptions */;
21
+ #options: AtlaspackOptions;
22
22
 
23
23
  constructor(options: AtlaspackOptions): PluginOptions {
24
24
  let existing = parcelOptionsToPluginOptions.get(options);
@@ -11,6 +11,7 @@ import nullthrows from 'nullthrows';
11
11
  import Environment from './Environment';
12
12
  import {fromProjectPath} from '../projectPath';
13
13
  import {fromInternalSourceLocation} from '../utils';
14
+ import {fromEnvironmentId} from '../EnvironmentManager';
14
15
 
15
16
  const inspect = Symbol.for('nodejs.util.inspect.custom');
16
17
 
@@ -21,8 +22,8 @@ export function targetToInternalTarget(target: ITarget): TargetValue {
21
22
  }
22
23
 
23
24
  export default class Target implements ITarget {
24
- #target /*: TargetValue */;
25
- #options /*: AtlaspackOptions */;
25
+ #target: TargetValue;
26
+ #options: AtlaspackOptions;
26
27
 
27
28
  constructor(target: TargetValue, options: AtlaspackOptions): Target {
28
29
  let existing = internalTargetToTarget.get(target);
@@ -46,7 +47,7 @@ export default class Target implements ITarget {
46
47
  }
47
48
 
48
49
  get env(): IEnvironment {
49
- return new Environment(this.#target.env, this.#options);
50
+ return new Environment(fromEnvironmentId(this.#target.env), this.#options);
50
51
  }
51
52
 
52
53
  get name(): string {
@@ -20,6 +20,7 @@ import logger from '@atlaspack/logger';
20
20
 
21
21
  import invariant from 'assert';
22
22
  import nullthrows from 'nullthrows';
23
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
23
24
  import {PromiseQueue, setEqual} from '@atlaspack/utils';
24
25
  import {hashString} from '@atlaspack/rust';
25
26
  import ThrowableDiagnostic from '@atlaspack/diagnostic';
@@ -161,12 +162,21 @@ export class AssetGraphBuilder {
161
162
  this.shouldBuildLazily = shouldBuildLazily ?? false;
162
163
  this.lazyIncludes = lazyIncludes ?? [];
163
164
  this.lazyExcludes = lazyExcludes ?? [];
164
- this.cacheKey =
165
- hashString(
165
+ if (getFeatureFlag('cachePerformanceImprovements')) {
166
+ const key = hashString(
166
167
  `${ATLASPACK_VERSION}${name}${JSON.stringify(entries) ?? ''}${
167
168
  options.mode
168
169
  }${options.shouldBuildLazily ? 'lazy' : 'eager'}`,
169
- ) + '-AssetGraph';
170
+ );
171
+ this.cacheKey = `AssetGraph/${ATLASPACK_VERSION}/${options.mode}/${key}`;
172
+ } else {
173
+ this.cacheKey =
174
+ hashString(
175
+ `${ATLASPACK_VERSION}${name}${JSON.stringify(entries) ?? ''}${
176
+ options.mode
177
+ }${options.shouldBuildLazily ? 'lazy' : 'eager'}`,
178
+ ) + '-AssetGraph';
179
+ }
170
180
 
171
181
  this.isSingleChangeRebuild =
172
182
  api
@@ -5,6 +5,7 @@ import invariant from 'assert';
5
5
  import ThrowableDiagnostic from '@atlaspack/diagnostic';
6
6
  import type {Async} from '@atlaspack/types';
7
7
  import {instrument} from '@atlaspack/logger';
8
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
8
9
 
9
10
  import AssetGraph, {nodeFromAssetGroup} from '../AssetGraph';
10
11
  import type {AtlaspackV3} from '../atlaspack-v3';
@@ -16,6 +17,8 @@ import type {
16
17
  AssetGraphRequestInput,
17
18
  AssetGraphRequestResult,
18
19
  } from './AssetGraphRequest';
20
+ import {toEnvironmentRef} from '../EnvironmentManager';
21
+ import {getEnvironmentHash} from '../Environment';
19
22
 
20
23
  type RunInput = {|
21
24
  input: AssetGraphRequestInput,
@@ -166,9 +169,14 @@ export function getAssetGraph(serializedGraph: any): {
166
169
 
167
170
  asset.committed = true;
168
171
  asset.contentKey = id;
169
- asset.env.id = getEnvId(asset.env);
172
+ asset.env.id = getFeatureFlag('environmentDeduplication')
173
+ ? // TODO: Rust can do this and avoid copying a significant amount of data over
174
+ getEnvironmentHash(asset.env)
175
+ : getEnvId(asset.env);
170
176
  asset.mapKey = `map:${asset.id}`;
171
177
 
178
+ asset.env = toEnvironmentRef(asset.env);
179
+
172
180
  // This is populated later when we map the edges between assets and dependencies
173
181
  asset.dependencies = new Map();
174
182
 
@@ -195,7 +203,11 @@ export function getAssetGraph(serializedGraph: any): {
195
203
  let dependency = node.value.dependency;
196
204
 
197
205
  dependency.id = id;
198
- dependency.env.id = getEnvId(dependency.env);
206
+ dependency.env.id = getFeatureFlag('environmentDeduplication')
207
+ ? // TODO: Rust can do this and avoid copying a significant amount of data over
208
+ getEnvironmentHash(dependency.env)
209
+ : getEnvId(dependency.env);
210
+ dependency.env = toEnvironmentRef(dependency.env);
199
211
 
200
212
  if (dependency.symbols != null) {
201
213
  dependency.symbols = new Map(dependency.symbols?.map(mapSymbols));
@@ -21,6 +21,7 @@ import {fromProjectPath, fromProjectPathRelative} from '../projectPath';
21
21
  import {report} from '../ReporterRunner';
22
22
  import {requestTypes} from '../RequestTracker';
23
23
  import type {DevDepRequestResult} from './DevDepRequest';
24
+ import {toEnvironmentId} from '../EnvironmentManager';
24
25
 
25
26
  type RunInput<TResult> = {|
26
27
  input: AssetRequestInput,
@@ -51,7 +52,7 @@ function getId(input: AssetRequestInput) {
51
52
  return hashString(
52
53
  type +
53
54
  fromProjectPathRelative(input.filePath) +
54
- input.env.id +
55
+ toEnvironmentId(input.env) +
55
56
  String(input.isSource) +
56
57
  String(input.sideEffects) +
57
58
  (input.code ?? '') +
@@ -20,6 +20,7 @@ import invariant from 'assert';
20
20
  import assert from 'assert';
21
21
  import nullthrows from 'nullthrows';
22
22
  import {PluginLogger} from '@atlaspack/logger';
23
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
23
24
  import ThrowableDiagnostic, {errorToDiagnostic} from '@atlaspack/diagnostic';
24
25
  import AssetGraph from '../AssetGraph';
25
26
  import BundleGraph from '../public/BundleGraph';
@@ -282,12 +283,21 @@ class BundlerRunner {
282
283
  this.pluginOptions = new PluginOptions(
283
284
  optionsProxy(this.options, api.invalidateOnOptionChange),
284
285
  );
285
- this.cacheKey =
286
- hashString(
286
+ if (getFeatureFlag('cachePerformanceImprovements')) {
287
+ const key = hashString(
287
288
  `${ATLASPACK_VERSION}:BundleGraph:${
288
289
  JSON.stringify(options.entries) ?? ''
289
290
  }${options.mode}${options.shouldBuildLazily ? 'lazy' : 'eager'}`,
290
- ) + '-BundleGraph';
291
+ );
292
+ this.cacheKey = `BundleGraph/${ATLASPACK_VERSION}/${options.mode}/${key}`;
293
+ } else {
294
+ this.cacheKey =
295
+ hashString(
296
+ `${ATLASPACK_VERSION}:BundleGraph:${
297
+ JSON.stringify(options.entries) ?? ''
298
+ }${options.mode}${options.shouldBuildLazily ? 'lazy' : 'eager'}`,
299
+ ) + '-BundleGraph';
300
+ }
291
301
  }
292
302
 
293
303
  async loadConfigs() {
@@ -63,7 +63,7 @@ export type ConfigRequest = {
63
63
  invalidateOnFileChange: Set<ProjectPath>,
64
64
  invalidateOnConfigKeyChange: Array<{|
65
65
  filePath: ProjectPath,
66
- configKey: string,
66
+ configKey: string[],
67
67
  |}>,
68
68
  invalidateOnFileCreate: Array<InternalFileCreateInvalidation>,
69
69
  invalidateOnEnvChange: Set<string>,
@@ -108,34 +108,58 @@ export async function loadPluginConfig<T: PluginWithLoadConfig>(
108
108
  }
109
109
  }
110
110
 
111
+ /**
112
+ * Return value at a given key path within an object.
113
+ *
114
+ * @example
115
+ * const obj = { a: { b: { c: 'd' } } };
116
+ * getValueAtPath(obj, ['a', 'b', 'c']); // 'd'
117
+ * getValueAtPath(obj, ['a', 'b', 'd']); // undefined
118
+ * getValueAtPath(obj, ['a', 'b']); // { c: 'd' }
119
+ * getValueAtPath(obj, ['a', 'b', 'c', 'd']); // undefined
120
+ */
121
+ export function getValueAtPath(obj: Object, key: string[]): any {
122
+ let current = obj;
123
+ for (let part of key) {
124
+ if (current == null) {
125
+ return undefined;
126
+ }
127
+ current = current[part];
128
+ }
129
+ return current;
130
+ }
131
+
111
132
  const configKeyCache = createBuildCache();
112
133
 
113
134
  export async function getConfigKeyContentHash(
114
135
  filePath: ProjectPath,
115
- configKey: string,
136
+ configKey: string[],
116
137
  options: AtlaspackOptions,
117
138
  ): Async<string> {
118
- let cacheKey = `${fromProjectPathRelative(filePath)}:${configKey}`;
139
+ let cacheKey = `${fromProjectPathRelative(filePath)}:${JSON.stringify(
140
+ configKey,
141
+ )}`;
119
142
  let cachedValue = configKeyCache.get(cacheKey);
120
143
 
121
144
  if (cachedValue) {
122
145
  return cachedValue;
123
146
  }
124
147
 
125
- let conf = await readConfig(
148
+ const conf = await readConfig(
126
149
  options.inputFS,
127
150
  fromProjectPath(options.projectRoot, filePath),
128
151
  );
129
152
 
130
- if (conf == null || conf.config[configKey] == null) {
153
+ const value = getValueAtPath(conf?.config, configKey);
154
+ if (conf == null || value == null) {
131
155
  // This can occur when a config key has been removed entirely during `respondToFSEvents`
132
156
  return '';
133
157
  }
134
158
 
135
- let contentHash =
136
- typeof conf.config[configKey] === 'object'
137
- ? hashObject(conf.config[configKey])
138
- : hashString(JSON.stringify(conf.config[configKey]));
159
+ const contentHash =
160
+ typeof value === 'object'
161
+ ? hashObject(value)
162
+ : hashString(JSON.stringify(value));
139
163
 
140
164
  configKeyCache.set(cacheKey, contentHash);
141
165
 
@@ -1,4 +1,5 @@
1
- // @flow
1
+ // @flow strict-local
2
+
2
3
  import type {
3
4
  DependencySpecifier,
4
5
  SemverRange,
@@ -116,17 +117,29 @@ type DevDepRequests = {|
116
117
  export async function getDevDepRequests<TResult: RequestResult>(
117
118
  api: RunAPI<TResult>,
118
119
  ): Promise<DevDepRequests> {
119
- let previousDevDepRequests: Map<string, DevDepRequestResult> = new Map(
120
- await Promise.all(
120
+ async function getPreviousDevDepRequests() {
121
+ const allDevDepRequests = await Promise.all(
121
122
  api
122
123
  .getSubRequests()
123
124
  .filter((req) => req.requestType === requestTypes.dev_dep_request)
124
- .map(async (req) => [
125
- req.id,
126
- nullthrows(await api.getRequestResult<DevDepRequestResult>(req.id)),
127
- ]),
128
- ),
129
- );
125
+ .map(
126
+ async (req): Promise<[string, DevDepRequestResult | null | void]> => [
127
+ req.id,
128
+ await api.getRequestResult<DevDepRequestResult>(req.id),
129
+ ],
130
+ ),
131
+ );
132
+ const nonNullDevDepRequests = [];
133
+ for (const [id, result] of allDevDepRequests) {
134
+ if (result != null) {
135
+ nonNullDevDepRequests.push([id, result]);
136
+ }
137
+ }
138
+
139
+ return new Map(nonNullDevDepRequests);
140
+ }
141
+
142
+ const previousDevDepRequests = await getPreviousDevDepRequests();
130
143
 
131
144
  return {
132
145
  devDeps: new Map(
@@ -24,6 +24,7 @@ import ThrowableDiagnostic, {
24
24
  md,
25
25
  } from '@atlaspack/diagnostic';
26
26
  import {PluginLogger} from '@atlaspack/logger';
27
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
27
28
  import nullthrows from 'nullthrows';
28
29
  import path from 'path';
29
30
  import {normalizePath} from '@atlaspack/utils';
@@ -320,6 +321,9 @@ export class ResolverRunner {
320
321
 
321
322
  if (result.priority != null) {
322
323
  dependency.priority = Priority[result.priority];
324
+ if (getFeatureFlag('hmrImprovements')) {
325
+ dependency.resolverPriority = dependency.priority;
326
+ }
323
327
  }
324
328
 
325
329
  if (result.invalidateOnEnvChange) {
@@ -49,6 +49,7 @@ import {BROWSER_ENVS} from '../public/Environment';
49
49
  import {optionsProxy, toInternalSourceLocation} from '../utils';
50
50
  import {fromProjectPath, toProjectPath, joinProjectPath} from '../projectPath';
51
51
  import {requestTypes} from '../RequestTracker';
52
+ import {fromEnvironmentId} from '../EnvironmentManager';
52
53
 
53
54
  type RunOpts<TResult> = {|
54
55
  input: Entry,
@@ -345,7 +346,7 @@ export class TargetResolver {
345
346
  },
346
347
  });
347
348
  }
348
- if (!BROWSER_ENVS.has(targets[0].env.context)) {
349
+ if (!BROWSER_ENVS.has(fromEnvironmentId(targets[0].env).context)) {
349
350
  throw new ThrowableDiagnostic({
350
351
  diagnostic: {
351
352
  message: `Only browser targets are supported in serve mode`,
@@ -1491,21 +1492,22 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1491
1492
 
1492
1493
  // Resolve relevant engines for context.
1493
1494
  let engines;
1494
- switch (target.env.context) {
1495
+ const env = fromEnvironmentId(target.env);
1496
+ switch (env.context) {
1495
1497
  case 'browser':
1496
1498
  case 'web-worker':
1497
1499
  case 'service-worker':
1498
1500
  case 'worklet': {
1499
- let browsers = target.env.engines.browsers;
1501
+ let browsers = env.engines.browsers;
1500
1502
  engines = Array.isArray(browsers) ? browsers.join(', ') : browsers;
1501
1503
  break;
1502
1504
  }
1503
1505
  case 'node':
1504
- engines = target.env.engines.node;
1506
+ engines = env.engines.node;
1505
1507
  break;
1506
1508
  case 'electron-main':
1507
1509
  case 'electron-renderer':
1508
- engines = target.env.engines.electron;
1510
+ engines = env.engines.electron;
1509
1511
  break;
1510
1512
  }
1511
1513
 
@@ -1547,9 +1549,7 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1547
1549
  }
1548
1550
 
1549
1551
  if (keyInfo.inferred) {
1550
- highlight.inferred.push(
1551
- md`${key} to be ${JSON.stringify(target.env[key])}`,
1552
- );
1552
+ highlight.inferred.push(md`${key} to be ${JSON.stringify(env[key])}`);
1553
1553
  }
1554
1554
  }
1555
1555
 
@@ -1578,22 +1578,20 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1578
1578
 
1579
1579
  // Format includeNodeModules to be human readable.
1580
1580
  let includeNodeModules;
1581
- if (typeof target.env.includeNodeModules === 'boolean') {
1582
- includeNodeModules = String(target.env.includeNodeModules);
1583
- } else if (Array.isArray(target.env.includeNodeModules)) {
1581
+ if (typeof env.includeNodeModules === 'boolean') {
1582
+ includeNodeModules = String(env.includeNodeModules);
1583
+ } else if (Array.isArray(env.includeNodeModules)) {
1584
1584
  includeNodeModules =
1585
1585
  'only ' +
1586
- listFormat.format(
1587
- target.env.includeNodeModules.map((m) => JSON.stringify(m)),
1588
- );
1586
+ listFormat.format(env.includeNodeModules.map((m) => JSON.stringify(m)));
1589
1587
  } else if (
1590
- target.env.includeNodeModules &&
1591
- typeof target.env.includeNodeModules === 'object'
1588
+ env.includeNodeModules &&
1589
+ typeof env.includeNodeModules === 'object'
1592
1590
  ) {
1593
1591
  includeNodeModules =
1594
1592
  'all except ' +
1595
1593
  listFormat.format(
1596
- Object.entries(target.env.includeNodeModules)
1594
+ Object.entries(env.includeNodeModules)
1597
1595
  .filter(([, v]) => v === false)
1598
1596
  .map(([k]) => JSON.stringify(k)),
1599
1597
  );
@@ -1609,18 +1607,14 @@ async function debugResolvedTargets(input, targets, targetInfo, options) {
1609
1607
  fromProjectPath(options.projectRoot, input.filePath),
1610
1608
  )}
1611
1609
  **Output**: ${path.relative(process.cwd(), output)}
1612
- **Format**: ${target.env.outputFormat} ${format(
1613
- info.outputFormat,
1614
- )}
1615
- **Context**: ${target.env.context} ${format(info.context)}
1610
+ **Format**: ${env.outputFormat} ${format(info.outputFormat)}
1611
+ **Context**: ${env.context} ${format(info.context)}
1616
1612
  **Engines**: ${engines || ''} ${format(info.engines)}
1617
- **Library Mode**: ${String(target.env.isLibrary)} ${format(
1618
- info.isLibrary,
1619
- )}
1613
+ **Library Mode**: ${String(env.isLibrary)} ${format(info.isLibrary)}
1620
1614
  **Include Node Modules**: ${includeNodeModules} ${format(
1621
1615
  info.includeNodeModules,
1622
1616
  )}
1623
- **Optimize**: ${String(target.env.shouldOptimize)} ${format(
1617
+ **Optimize**: ${String(env.shouldOptimize)} ${format(
1624
1618
  info.shouldOptimize,
1625
1619
  )}`,
1626
1620
  codeFrames: target.loc
@@ -40,6 +40,8 @@ import {AtlaspackConfig} from '../AtlaspackConfig';
40
40
  import ThrowableDiagnostic, {errorToDiagnostic} from '@atlaspack/diagnostic';
41
41
  import {PluginTracer, tracer} from '@atlaspack/profiler';
42
42
  import {requestTypes} from '../RequestTracker';
43
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
44
+ import {fromEnvironmentId} from '../EnvironmentManager';
43
45
 
44
46
  const HASH_REF_PREFIX_LEN = HASH_REF_PREFIX.length;
45
47
  const BOUNDARY_LENGTH = HASH_REF_PREFIX.length + 32 - 1;
@@ -110,7 +112,9 @@ async function run({input, options, api}) {
110
112
  let cacheKeys = info.cacheKeys;
111
113
  let mapKey = cacheKeys.map;
112
114
  let fullPath = fromProjectPath(options.projectRoot, filePath);
113
- if (mapKey && bundle.env.sourceMap && !bundle.env.sourceMap.inline) {
115
+ const env = fromEnvironmentId(bundle.env);
116
+
117
+ if (mapKey && env.sourceMap && !env.sourceMap.inline) {
114
118
  api.invalidateOnFileDelete(
115
119
  toProjectPath(options.projectRoot, fullPath + '.map'),
116
120
  );
@@ -167,14 +171,15 @@ async function run({input, options, api}) {
167
171
  api,
168
172
  );
169
173
 
170
- if (
171
- mapKey &&
172
- bundle.env.sourceMap &&
173
- !bundle.env.sourceMap.inline &&
174
- (await options.cache.has(mapKey))
175
- ) {
174
+ const hasSourceMap = getFeatureFlag('cachePerformanceImprovements')
175
+ ? await options.cache.hasLargeBlob(mapKey)
176
+ : await options.cache.has(mapKey);
177
+ if (mapKey && env.sourceMap && !env.sourceMap.inline && hasSourceMap) {
178
+ const mapEntry = getFeatureFlag('cachePerformanceImprovements')
179
+ ? await options.cache.getLargeBlob(mapKey)
180
+ : await options.cache.getBlob(mapKey);
176
181
  await writeFiles(
177
- blobToStream(await options.cache.getBlob(mapKey)),
182
+ blobToStream(mapEntry),
178
183
  info,
179
184
  hashRefToNameHash,
180
185
  options,
@@ -189,6 +194,7 @@ async function run({input, options, api}) {
189
194
 
190
195
  let res = {
191
196
  filePath,
197
+ bundleId: bundle.id,
192
198
  type: info.type,
193
199
  stats: {
194
200
  size,
@@ -9,6 +9,7 @@ import {requestTypes} from '../RequestTracker';
9
9
  import type {PackagedBundleInfo} from '../types';
10
10
  import type BundleGraph from '../BundleGraph';
11
11
  import type {BundleInfo} from '../PackagerRunner';
12
+ import {report} from '../ReporterRunner';
12
13
 
13
14
  import {HASH_REF_PREFIX} from '../constants';
14
15
  import {joinProjectPath} from '../projectPath';
@@ -38,6 +39,22 @@ export type WriteBundlesRequest = {|
38
39
  input: WriteBundlesRequestInput,
39
40
  |};
40
41
 
42
+ function reportPackagingProgress(
43
+ completeBundles: number,
44
+ totalBundles: number,
45
+ ) {
46
+ if (!getFeatureFlag('cliProgressReportingImprovements')) {
47
+ return;
48
+ }
49
+
50
+ report({
51
+ type: 'buildProgress',
52
+ phase: 'packagingAndOptimizing',
53
+ totalBundles,
54
+ completeBundles,
55
+ });
56
+ }
57
+
41
58
  /**
42
59
  * Packages, optimizes, and writes all bundles to the dist directory.
43
60
  */
@@ -84,6 +101,7 @@ async function run({input, api, farm, options}) {
84
101
  ).replace(bundle.hashReference, hash);
85
102
  res.set(bundle.id, {
86
103
  filePath: joinProjectPath(bundle.target.distDir, name),
104
+ bundleId: bundle.id,
87
105
  type: bundle.type, // FIXME: this is wrong if the packager changes the type...
88
106
  stats: {
89
107
  time: 0,
@@ -96,14 +114,19 @@ async function run({input, api, farm, options}) {
96
114
  return true;
97
115
  });
98
116
 
117
+ let cachedBundles = new Set(
118
+ bundles.filter((b) => api.canSkipSubrequest(bundleGraph.getHash(b))),
119
+ );
120
+
99
121
  // Package on the main thread if there is only one bundle to package.
100
122
  // This avoids the cost of serializing the bundle graph for single file change builds.
101
123
  let useMainThread =
102
- bundles.length === 1 ||
103
- bundles.filter((b) => !api.canSkipSubrequest(bundleGraph.getHash(b)))
104
- .length === 1;
124
+ bundles.length === 1 || bundles.length - cachedBundles.size <= 1;
105
125
 
106
126
  try {
127
+ let completeBundles = cachedBundles.size;
128
+ reportPackagingProgress(completeBundles, bundles.length);
129
+
107
130
  await Promise.all(
108
131
  bundles.map(async (bundle) => {
109
132
  let request = createPackageRequest({
@@ -116,6 +139,11 @@ async function run({input, api, farm, options}) {
116
139
 
117
140
  let info = await api.runRequest(request);
118
141
 
142
+ if (!cachedBundles.has(bundle)) {
143
+ completeBundles++;
144
+ reportPackagingProgress(completeBundles, bundles.length);
145
+ }
146
+
119
147
  if (!useMainThread) {
120
148
  // Force a refresh of the cache to avoid a race condition
121
149
  // between threaded reads and writes that can result in an LMDB cache miss:
@@ -153,8 +153,10 @@ export default async function resolveOptions(
153
153
 
154
154
  const needsRustLmdbCache = getFeatureFlag('atlaspackV3');
155
155
 
156
- if (!needsRustLmdbCache && !(outputFS instanceof NodeFS)) {
157
- return new FSCache(outputFS, cacheDir);
156
+ if (!getFeatureFlag('cachePerformanceImprovements')) {
157
+ if (!needsRustLmdbCache && !(outputFS instanceof NodeFS)) {
158
+ return new FSCache(outputFS, cacheDir);
159
+ }
158
160
  }
159
161
 
160
162
  return new LMDBLiteCache(cacheDir);