@atlaspack/core 2.17.3 → 2.18.0
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/CHANGELOG.md +52 -0
- package/lib/AssetGraph.js +17 -6
- package/lib/Atlaspack.js +3 -1
- package/lib/BundleGraph.js +6 -5
- package/lib/Dependency.js +6 -2
- package/lib/Environment.js +4 -3
- package/lib/EnvironmentManager.js +137 -0
- package/lib/InternalConfig.js +3 -2
- package/lib/PackagerRunner.js +52 -15
- package/lib/RequestTracker.js +191 -89
- package/lib/UncommittedAsset.js +20 -2
- package/lib/applyRuntimes.js +2 -1
- package/lib/assetUtils.js +2 -1
- package/lib/atlaspack-v3/worker/worker.js +8 -0
- package/lib/public/Asset.js +3 -2
- package/lib/public/Bundle.js +2 -1
- package/lib/public/BundleGraph.js +21 -5
- package/lib/public/Config.js +98 -3
- package/lib/public/Dependency.js +2 -1
- package/lib/public/MutableBundleGraph.js +2 -1
- package/lib/public/Target.js +2 -1
- package/lib/requests/AssetGraphRequest.js +13 -1
- package/lib/requests/AssetRequest.js +2 -1
- package/lib/requests/BundleGraphRequest.js +13 -1
- package/lib/requests/ConfigRequest.js +27 -4
- package/lib/requests/TargetRequest.js +18 -16
- package/lib/requests/WriteBundleRequest.js +15 -3
- package/lib/requests/WriteBundlesRequest.js +1 -0
- package/lib/resolveOptions.js +4 -2
- package/package.json +13 -13
- package/src/AssetGraph.js +12 -6
- package/src/Atlaspack.js +5 -4
- package/src/BundleGraph.js +13 -8
- package/src/Dependency.js +13 -5
- package/src/Environment.js +8 -5
- package/src/EnvironmentManager.js +145 -0
- package/src/InternalConfig.js +6 -5
- package/src/PackagerRunner.js +72 -20
- package/src/RequestTracker.js +330 -146
- package/src/UncommittedAsset.js +23 -3
- package/src/applyRuntimes.js +6 -1
- package/src/assetUtils.js +4 -3
- package/src/atlaspack-v3/worker/compat/plugin-config.js +9 -5
- package/src/atlaspack-v3/worker/worker.js +7 -0
- package/src/public/Asset.js +9 -2
- package/src/public/Bundle.js +2 -1
- package/src/public/BundleGraph.js +22 -5
- package/src/public/Config.js +129 -14
- package/src/public/Dependency.js +2 -1
- package/src/public/MutableBundleGraph.js +2 -1
- package/src/public/Target.js +2 -1
- package/src/requests/AssetGraphRequest.js +13 -3
- package/src/requests/AssetRequest.js +2 -1
- package/src/requests/BundleGraphRequest.js +13 -3
- package/src/requests/ConfigRequest.js +33 -9
- package/src/requests/TargetRequest.js +19 -25
- package/src/requests/WriteBundleRequest.js +14 -8
- package/src/requests/WriteBundlesRequest.js +1 -0
- package/src/resolveOptions.js +4 -2
- package/src/types.js +9 -7
- package/test/Environment.test.js +43 -34
- package/test/EnvironmentManager.test.js +192 -0
- package/test/PublicEnvironment.test.js +10 -7
- package/test/RequestTracker.test.js +115 -3
- package/test/public/Config.test.js +108 -0
- package/test/requests/ConfigRequest.test.js +187 -3
- package/test/test-utils.js +4 -9
package/src/UncommittedAsset.js
CHANGED
|
@@ -30,7 +30,13 @@ import {ATLASPACK_VERSION} from './constants';
|
|
|
30
30
|
import {createAsset, createAssetIdFromOptions} from './assetUtils';
|
|
31
31
|
import {BundleBehaviorNames} from './types';
|
|
32
32
|
import {invalidateOnFileCreateToInternal, createInvalidations} from './utils';
|
|
33
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
type ProjectPath,
|
|
35
|
+
fromProjectPath,
|
|
36
|
+
fromProjectPathRelative,
|
|
37
|
+
} from './projectPath';
|
|
38
|
+
import {getFeatureFlag} from '@atlaspack/feature-flags';
|
|
39
|
+
import {fromEnvironmentId} from './EnvironmentManager';
|
|
34
40
|
|
|
35
41
|
type UncommittedAssetOptions = {|
|
|
36
42
|
value: Asset,
|
|
@@ -153,7 +159,9 @@ export default class UncommittedAsset {
|
|
|
153
159
|
size = content.length;
|
|
154
160
|
}
|
|
155
161
|
|
|
162
|
+
// Maybe we should just store this in a file instead of LMDB
|
|
156
163
|
await this.options.cache.setBlob(contentKey, content);
|
|
164
|
+
|
|
157
165
|
return {size, hash};
|
|
158
166
|
}
|
|
159
167
|
|
|
@@ -214,6 +222,9 @@ export default class UncommittedAsset {
|
|
|
214
222
|
this.clearAST();
|
|
215
223
|
}
|
|
216
224
|
|
|
225
|
+
/**
|
|
226
|
+
* @deprecated This has been broken on any cache other than FSCache for a long time.
|
|
227
|
+
*/
|
|
217
228
|
setStream(stream: Readable) {
|
|
218
229
|
this.content = stream;
|
|
219
230
|
this.clearAST();
|
|
@@ -296,6 +307,11 @@ export default class UncommittedAsset {
|
|
|
296
307
|
}
|
|
297
308
|
|
|
298
309
|
getCacheKey(key: string): string {
|
|
310
|
+
if (getFeatureFlag('cachePerformanceImprovements')) {
|
|
311
|
+
const filePath = fromProjectPathRelative(this.value.filePath);
|
|
312
|
+
return `Asset/${ATLASPACK_VERSION}/${filePath}/${this.value.id}/${key}`;
|
|
313
|
+
}
|
|
314
|
+
|
|
299
315
|
return hashString(ATLASPACK_VERSION + key + this.value.id);
|
|
300
316
|
}
|
|
301
317
|
|
|
@@ -306,7 +322,11 @@ export default class UncommittedAsset {
|
|
|
306
322
|
...rest,
|
|
307
323
|
// $FlowFixMe "convert" the $ReadOnlyMaps to the interal mutable one
|
|
308
324
|
symbols,
|
|
309
|
-
env: mergeEnvironments(
|
|
325
|
+
env: mergeEnvironments(
|
|
326
|
+
this.options.projectRoot,
|
|
327
|
+
fromEnvironmentId(this.value.env),
|
|
328
|
+
env,
|
|
329
|
+
),
|
|
310
330
|
sourceAssetId: this.value.id,
|
|
311
331
|
sourcePath: fromProjectPath(
|
|
312
332
|
this.options.projectRoot,
|
|
@@ -371,7 +391,7 @@ export default class UncommittedAsset {
|
|
|
371
391
|
isSource: this.value.isSource,
|
|
372
392
|
env: mergeEnvironments(
|
|
373
393
|
this.options.projectRoot,
|
|
374
|
-
this.value.env,
|
|
394
|
+
fromEnvironmentId(this.value.env),
|
|
375
395
|
result.env,
|
|
376
396
|
),
|
|
377
397
|
dependencies:
|
package/src/applyRuntimes.js
CHANGED
|
@@ -34,6 +34,7 @@ import {createDevDependency, runDevDepRequest} from './requests/DevDepRequest';
|
|
|
34
34
|
import {toProjectPath, fromProjectPathRelative} from './projectPath';
|
|
35
35
|
import {tracer, PluginTracer} from '@atlaspack/profiler';
|
|
36
36
|
import {DefaultMap} from '@atlaspack/utils';
|
|
37
|
+
import {fromEnvironmentId} from './EnvironmentManager';
|
|
37
38
|
|
|
38
39
|
type RuntimeConnection = {|
|
|
39
40
|
bundle: InternalBundle,
|
|
@@ -159,7 +160,11 @@ export default async function applyRuntimes<TResult: RequestResult>({
|
|
|
159
160
|
let assetGroup = {
|
|
160
161
|
code,
|
|
161
162
|
filePath: toProjectPath(options.projectRoot, sourceName),
|
|
162
|
-
env: mergeEnvironments(
|
|
163
|
+
env: mergeEnvironments(
|
|
164
|
+
options.projectRoot,
|
|
165
|
+
fromEnvironmentId(bundle.env),
|
|
166
|
+
env,
|
|
167
|
+
),
|
|
163
168
|
// Runtime assets should be considered source, as they should be
|
|
164
169
|
// e.g. compiled to run in the target environment
|
|
165
170
|
isSource: true,
|
package/src/assetUtils.js
CHANGED
|
@@ -16,7 +16,6 @@ import type {
|
|
|
16
16
|
Asset,
|
|
17
17
|
RequestInvalidation,
|
|
18
18
|
Dependency,
|
|
19
|
-
Environment,
|
|
20
19
|
AtlaspackOptions,
|
|
21
20
|
} from './types';
|
|
22
21
|
|
|
@@ -40,6 +39,8 @@ import {hashString, createAssetId as createAssetIdRust} from '@atlaspack/rust';
|
|
|
40
39
|
import {BundleBehavior as BundleBehaviorMap} from './types';
|
|
41
40
|
import {PluginTracer} from '@atlaspack/profiler';
|
|
42
41
|
import {identifierRegistry} from './IdentifierRegistry';
|
|
42
|
+
import type {EnvironmentRef} from './EnvironmentManager';
|
|
43
|
+
import {toEnvironmentId} from './EnvironmentManager';
|
|
43
44
|
|
|
44
45
|
export type AssetOptions = {|
|
|
45
46
|
id?: string,
|
|
@@ -56,7 +57,7 @@ export type AssetOptions = {|
|
|
|
56
57
|
bundleBehavior?: ?BundleBehavior,
|
|
57
58
|
isBundleSplittable?: ?boolean,
|
|
58
59
|
isSource: boolean,
|
|
59
|
-
env:
|
|
60
|
+
env: EnvironmentRef,
|
|
60
61
|
meta?: Meta,
|
|
61
62
|
outputHash?: ?string,
|
|
62
63
|
pipeline?: ?string,
|
|
@@ -71,7 +72,7 @@ export type AssetOptions = {|
|
|
|
71
72
|
|
|
72
73
|
export function createAssetIdFromOptions(options: AssetOptions): string {
|
|
73
74
|
const data = {
|
|
74
|
-
environmentId: options.env
|
|
75
|
+
environmentId: toEnvironmentId(options.env),
|
|
75
76
|
filePath: options.filePath,
|
|
76
77
|
code: options.code,
|
|
77
78
|
pipeline: options.pipeline,
|
|
@@ -100,11 +100,15 @@ export class PluginConfig implements IPluginConfig {
|
|
|
100
100
|
// eslint-disable-next-line no-unused-vars
|
|
101
101
|
filePaths: Array<FilePath>,
|
|
102
102
|
// eslint-disable-next-line no-unused-vars
|
|
103
|
-
options?:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
options?:
|
|
104
|
+
| {|
|
|
105
|
+
packageKey?: string,
|
|
106
|
+
parse?: boolean,
|
|
107
|
+
exclude?: boolean,
|
|
108
|
+
|}
|
|
109
|
+
| {|
|
|
110
|
+
readTracking?: boolean,
|
|
111
|
+
|},
|
|
108
112
|
): Promise<?ConfigResultWithFilePath<T>> {
|
|
109
113
|
return this.#inner.getConfigFrom(searchPath, filePaths, options);
|
|
110
114
|
}
|
package/src/public/Asset.js
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
BundleBehaviorNames,
|
|
37
37
|
} from '../types';
|
|
38
38
|
import {toInternalSourceLocation} from '../utils';
|
|
39
|
+
import {fromEnvironmentId} from '../EnvironmentManager';
|
|
39
40
|
|
|
40
41
|
const inspect = Symbol.for('nodejs.util.inspect.custom');
|
|
41
42
|
|
|
@@ -101,7 +102,10 @@ class BaseAsset {
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
get env(): IEnvironment {
|
|
104
|
-
return new Environment(
|
|
105
|
+
return new Environment(
|
|
106
|
+
fromEnvironmentId(this.#asset.value.env),
|
|
107
|
+
this.#asset.options,
|
|
108
|
+
);
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
get fs(): FileSystem {
|
|
@@ -210,7 +214,10 @@ export class Asset extends BaseAsset implements IAsset {
|
|
|
210
214
|
}
|
|
211
215
|
|
|
212
216
|
get env(): IEnvironment {
|
|
213
|
-
this.#env ??= new Environment(
|
|
217
|
+
this.#env ??= new Environment(
|
|
218
|
+
fromEnvironmentId(this.#asset.value.env),
|
|
219
|
+
this.#asset.options,
|
|
220
|
+
);
|
|
214
221
|
return this.#env;
|
|
215
222
|
}
|
|
216
223
|
|
package/src/public/Bundle.js
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import Target from './Target';
|
|
35
35
|
import {BundleBehaviorNames} from '../types';
|
|
36
36
|
import {fromProjectPath} from '../projectPath';
|
|
37
|
+
import {fromEnvironmentId} from '../EnvironmentManager';
|
|
37
38
|
|
|
38
39
|
const inspect = Symbol.for('nodejs.util.inspect.custom');
|
|
39
40
|
|
|
@@ -123,7 +124,7 @@ export class Bundle implements IBundle {
|
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
get env(): IEnvironment {
|
|
126
|
-
return new Environment(this.#bundle.env, this.#options);
|
|
127
|
+
return new Environment(fromEnvironmentId(this.#bundle.env), this.#options);
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
get needsStableName(): ?boolean {
|
|
@@ -31,6 +31,7 @@ import Dependency, {
|
|
|
31
31
|
import {targetToInternalTarget} from './Target';
|
|
32
32
|
import {fromInternalSourceLocation} from '../utils';
|
|
33
33
|
import BundleGroup, {bundleGroupToInternalBundleGroup} from './BundleGroup';
|
|
34
|
+
import {getFeatureFlag} from '@atlaspack/feature-flags';
|
|
34
35
|
|
|
35
36
|
// Friendly access for other modules within this package that need access
|
|
36
37
|
// to the internal bundle.
|
|
@@ -489,11 +490,27 @@ export default class BundleGraph<TBundle: IBundle>
|
|
|
489
490
|
for (let bundle of bundles) {
|
|
490
491
|
const conditions = bundleConditions.get(bundle.id) ?? new Map();
|
|
491
492
|
|
|
492
|
-
conditions.
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
493
|
+
const currentCondition = conditions.get(cond.key);
|
|
494
|
+
|
|
495
|
+
if (getFeatureFlag('conditionalBundlingReporterSameConditionFix')) {
|
|
496
|
+
conditions.set(cond.key, {
|
|
497
|
+
bundle,
|
|
498
|
+
ifTrueBundles: [
|
|
499
|
+
...(currentCondition?.ifTrueBundles ?? []),
|
|
500
|
+
...ifTrueBundles,
|
|
501
|
+
],
|
|
502
|
+
ifFalseBundles: [
|
|
503
|
+
...(currentCondition?.ifFalseBundles ?? []),
|
|
504
|
+
...ifFalseBundles,
|
|
505
|
+
],
|
|
506
|
+
});
|
|
507
|
+
} else {
|
|
508
|
+
conditions.set(cond.key, {
|
|
509
|
+
bundle,
|
|
510
|
+
ifTrueBundles,
|
|
511
|
+
ifFalseBundles,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
497
514
|
|
|
498
515
|
bundleConditions.set(bundle.id, conditions);
|
|
499
516
|
}
|
package/src/public/Config.js
CHANGED
|
@@ -20,12 +20,90 @@ import {
|
|
|
20
20
|
} from '@atlaspack/utils';
|
|
21
21
|
import Environment from './Environment';
|
|
22
22
|
import {fromProjectPath, toProjectPath} from '../projectPath';
|
|
23
|
+
import {getFeatureFlag} from '@atlaspack/feature-flags';
|
|
24
|
+
import {fromEnvironmentId} from '../EnvironmentManager';
|
|
23
25
|
|
|
24
26
|
const internalConfigToConfig: DefaultWeakMap<
|
|
25
27
|
AtlaspackOptions,
|
|
26
28
|
WeakMap<Config, PublicConfig>,
|
|
27
29
|
> = new DefaultWeakMap(() => new WeakMap());
|
|
28
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Implements read tracking over an object.
|
|
33
|
+
*
|
|
34
|
+
* Calling this function with a non-trivial object like a class instance will fail to work.
|
|
35
|
+
*
|
|
36
|
+
* We track reads to fields that resolve to:
|
|
37
|
+
*
|
|
38
|
+
* - primitive values
|
|
39
|
+
* - arrays
|
|
40
|
+
*
|
|
41
|
+
* That is, reading a nested field `a.b.c` will make a single call to `onRead` with the path
|
|
42
|
+
* `['a', 'b', 'c']`.
|
|
43
|
+
*
|
|
44
|
+
* In case the value is null or an array, we will track the read as well.
|
|
45
|
+
*
|
|
46
|
+
* Iterating over `Object.keys(obj.field)` will register a read for the `['field']` path.
|
|
47
|
+
* Other reads work normally.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
*
|
|
51
|
+
* const usedPaths = new Set();
|
|
52
|
+
* const onRead = (path) => {
|
|
53
|
+
* usedPaths.add(path);
|
|
54
|
+
* };
|
|
55
|
+
*
|
|
56
|
+
* const config = makeConfigProxy(onRead, {a: {b: {c: 'd'}}})
|
|
57
|
+
* console.log(config.a.b.c);
|
|
58
|
+
* console.log(Array.from(usedPaths));
|
|
59
|
+
* // We get a single read for the path
|
|
60
|
+
* // ['a', 'b', 'c']
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
export function makeConfigProxy<T>(
|
|
64
|
+
onRead: (path: string[]) => void,
|
|
65
|
+
config: T,
|
|
66
|
+
): T {
|
|
67
|
+
const reportedPaths = new Set();
|
|
68
|
+
const reportPath = (path) => {
|
|
69
|
+
if (reportedPaths.has(path)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
reportedPaths.add(path);
|
|
73
|
+
onRead(path);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const makeProxy = (target, path) => {
|
|
77
|
+
return new Proxy(target, {
|
|
78
|
+
ownKeys(target) {
|
|
79
|
+
reportPath(path);
|
|
80
|
+
|
|
81
|
+
// $FlowFixMe
|
|
82
|
+
return Object.getOwnPropertyNames(target);
|
|
83
|
+
},
|
|
84
|
+
get(target, prop) {
|
|
85
|
+
// $FlowFixMe
|
|
86
|
+
const value = target[prop];
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
typeof value === 'object' &&
|
|
90
|
+
value != null &&
|
|
91
|
+
!Array.isArray(value)
|
|
92
|
+
) {
|
|
93
|
+
return makeProxy(value, [...path, prop]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
reportPath([...path, prop]);
|
|
97
|
+
|
|
98
|
+
return value;
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// $FlowFixMe
|
|
104
|
+
return makeProxy(config, []);
|
|
105
|
+
}
|
|
106
|
+
|
|
29
107
|
export default class PublicConfig implements IConfig {
|
|
30
108
|
#config /*: Config */;
|
|
31
109
|
#pkg /*: ?PackageJSON */;
|
|
@@ -45,7 +123,7 @@ export default class PublicConfig implements IConfig {
|
|
|
45
123
|
}
|
|
46
124
|
|
|
47
125
|
get env(): Environment {
|
|
48
|
-
return new Environment(this.#config.env, this.#options);
|
|
126
|
+
return new Environment(fromEnvironmentId(this.#config.env), this.#options);
|
|
49
127
|
}
|
|
50
128
|
|
|
51
129
|
get searchPath(): FilePath {
|
|
@@ -75,7 +153,7 @@ export default class PublicConfig implements IConfig {
|
|
|
75
153
|
);
|
|
76
154
|
}
|
|
77
155
|
|
|
78
|
-
invalidateOnConfigKeyChange(filePath: FilePath, configKey: string) {
|
|
156
|
+
invalidateOnConfigKeyChange(filePath: FilePath, configKey: string[]) {
|
|
79
157
|
this.#config.invalidateOnConfigKeyChange.push({
|
|
80
158
|
filePath: toProjectPath(this.#options.projectRoot, filePath),
|
|
81
159
|
configKey,
|
|
@@ -132,11 +210,22 @@ export default class PublicConfig implements IConfig {
|
|
|
132
210
|
async getConfigFrom<T>(
|
|
133
211
|
searchPath: FilePath,
|
|
134
212
|
fileNames: Array<string>,
|
|
135
|
-
options:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
213
|
+
options:
|
|
214
|
+
| ?{|
|
|
215
|
+
/**
|
|
216
|
+
* @deprecated Use `configKey` instead.
|
|
217
|
+
*/
|
|
218
|
+
packageKey?: string,
|
|
219
|
+
parse?: boolean,
|
|
220
|
+
exclude?: boolean,
|
|
221
|
+
|}
|
|
222
|
+
| ?{|
|
|
223
|
+
/**
|
|
224
|
+
* If specified, this function will return a proxy object that will track reads to
|
|
225
|
+
* config fields and only register invalidations for when those keys change.
|
|
226
|
+
*/
|
|
227
|
+
readTracking?: boolean,
|
|
228
|
+
|},
|
|
140
229
|
): Promise<?ConfigResultWithFilePath<T>> {
|
|
141
230
|
let packageKey = options?.packageKey;
|
|
142
231
|
if (packageKey != null) {
|
|
@@ -146,7 +235,7 @@ export default class PublicConfig implements IConfig {
|
|
|
146
235
|
|
|
147
236
|
if (pkg && pkg.contents[packageKey]) {
|
|
148
237
|
// Invalidate only when the package key changes
|
|
149
|
-
this.invalidateOnConfigKeyChange(pkg.filePath, packageKey);
|
|
238
|
+
this.invalidateOnConfigKeyChange(pkg.filePath, [packageKey]);
|
|
150
239
|
|
|
151
240
|
return {
|
|
152
241
|
contents: pkg.contents[packageKey],
|
|
@@ -155,6 +244,26 @@ export default class PublicConfig implements IConfig {
|
|
|
155
244
|
}
|
|
156
245
|
}
|
|
157
246
|
|
|
247
|
+
const readTracking = options?.readTracking;
|
|
248
|
+
if (readTracking === true) {
|
|
249
|
+
for (let fileName of fileNames) {
|
|
250
|
+
const config = await this.getConfigFrom(searchPath, [fileName], {
|
|
251
|
+
exclude: true,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
if (config != null) {
|
|
255
|
+
return Promise.resolve({
|
|
256
|
+
contents: makeConfigProxy((keyPath) => {
|
|
257
|
+
this.invalidateOnConfigKeyChange(config.filePath, keyPath);
|
|
258
|
+
}, config.contents),
|
|
259
|
+
filePath: config.filePath,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// fall through so that file above invalidations are registered
|
|
265
|
+
}
|
|
266
|
+
|
|
158
267
|
if (fileNames.length === 0) {
|
|
159
268
|
return null;
|
|
160
269
|
}
|
|
@@ -234,11 +343,15 @@ export default class PublicConfig implements IConfig {
|
|
|
234
343
|
|
|
235
344
|
getConfig<T>(
|
|
236
345
|
filePaths: Array<FilePath>,
|
|
237
|
-
options:
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
346
|
+
options:
|
|
347
|
+
| ?{|
|
|
348
|
+
packageKey?: string,
|
|
349
|
+
parse?: boolean,
|
|
350
|
+
exclude?: boolean,
|
|
351
|
+
|}
|
|
352
|
+
| {|
|
|
353
|
+
readTracking?: boolean,
|
|
354
|
+
|},
|
|
242
355
|
): Promise<?ConfigResultWithFilePath<T>> {
|
|
243
356
|
return this.getConfigFrom(this.searchPath, filePaths, options);
|
|
244
357
|
}
|
|
@@ -248,7 +361,9 @@ export default class PublicConfig implements IConfig {
|
|
|
248
361
|
return this.#pkg;
|
|
249
362
|
}
|
|
250
363
|
|
|
251
|
-
let pkgConfig = await this.getConfig<PackageJSON>(['package.json']
|
|
364
|
+
let pkgConfig = await this.getConfig<PackageJSON>(['package.json'], {
|
|
365
|
+
readTracking: getFeatureFlag('granularTsConfigInvalidation'),
|
|
366
|
+
});
|
|
252
367
|
if (!pkgConfig) {
|
|
253
368
|
return null;
|
|
254
369
|
}
|
package/src/public/Dependency.js
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from '../types';
|
|
28
28
|
import {fromProjectPath} from '../projectPath';
|
|
29
29
|
import {fromInternalSourceLocation} from '../utils';
|
|
30
|
+
import {fromEnvironmentId} from '../EnvironmentManager';
|
|
30
31
|
|
|
31
32
|
const SpecifierTypeNames = Object.keys(SpecifierTypeMap);
|
|
32
33
|
const PriorityNames = Object.keys(Priority);
|
|
@@ -112,7 +113,7 @@ export default class Dependency implements IDependency {
|
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
get env(): IEnvironment {
|
|
115
|
-
return new Environment(this.#dep.env, this.#options);
|
|
116
|
+
return new Environment(fromEnvironmentId(this.#dep.env), this.#options);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
get packageConditions(): ?Array<string> {
|
|
@@ -32,6 +32,7 @@ import {BundleBehavior} from '../types';
|
|
|
32
32
|
import BundleGroup, {bundleGroupToInternalBundleGroup} from './BundleGroup';
|
|
33
33
|
import type {ProjectPath} from '../projectPath';
|
|
34
34
|
import {identifierRegistry} from '../IdentifierRegistry';
|
|
35
|
+
import {toEnvironmentRef} from '../EnvironmentManager';
|
|
35
36
|
|
|
36
37
|
function createBundleId(data: {|
|
|
37
38
|
entryAssetId: string | null,
|
|
@@ -236,7 +237,7 @@ export default class MutableBundleGraph
|
|
|
236
237
|
: bundleId.slice(-8),
|
|
237
238
|
type: opts.entryAsset ? opts.entryAsset.type : opts.type,
|
|
238
239
|
env: opts.env
|
|
239
|
-
? environmentToInternalEnvironment(opts.env)
|
|
240
|
+
? toEnvironmentRef(environmentToInternalEnvironment(opts.env))
|
|
240
241
|
: nullthrows(entryAsset).env,
|
|
241
242
|
entryAssetIds: entryAsset ? [entryAsset.id] : [],
|
|
242
243
|
mainEntryId: entryAsset?.id,
|
package/src/public/Target.js
CHANGED
|
@@ -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
|
|
|
@@ -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
|
-
|
|
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
|
-
)
|
|
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
|
|
@@ -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
|
|
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
|
-
|
|
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
|
-
)
|
|
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)}:${
|
|
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
|
-
|
|
148
|
+
const conf = await readConfig(
|
|
126
149
|
options.inputFS,
|
|
127
150
|
fromProjectPath(options.projectRoot, filePath),
|
|
128
151
|
);
|
|
129
152
|
|
|
130
|
-
|
|
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
|
-
|
|
136
|
-
typeof
|
|
137
|
-
? hashObject(
|
|
138
|
-
: hashString(JSON.stringify(
|
|
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
|
|