From 1cc60d30cbc5dda59a3e012fcbf0c65c267ab2bd Mon Sep 17 00:00:00 2001 From: thebriando Date: Fri, 2 Sep 2022 11:35:53 -0700 Subject: [PATCH 01/12] Package on main thread when there's only one bundle in request --- packages/core/core/src/PackagerRunner.js | 2 ++ packages/core/core/src/ReporterRunner.js | 10 ++++---- .../core/core/src/requests/PackageRequest.js | 6 +++-- .../core/src/requests/WriteBundlesRequest.js | 24 +++++++++++++++---- packages/core/core/src/worker.js | 7 ++++-- packages/core/types/index.js | 2 ++ 6 files changed, 38 insertions(+), 13 deletions(-) diff --git a/packages/core/core/src/PackagerRunner.js b/packages/core/core/src/PackagerRunner.js index 3c18a16c10b..a82e023c1e5 100644 --- a/packages/core/core/src/PackagerRunner.js +++ b/packages/core/core/src/PackagerRunner.js @@ -325,6 +325,7 @@ export default class PackagerRunner { type: 'buildProgress', phase: 'packaging', bundle, + bundleGraph, }); let packager = await this.config.getPackager(bundle.name); @@ -418,6 +419,7 @@ export default class PackagerRunner { type: 'buildProgress', phase: 'optimizing', bundle, + bundleGraph: internalBundleGraph, }); let optimized = { diff --git a/packages/core/core/src/ReporterRunner.js b/packages/core/core/src/ReporterRunner.js index 9b07912bb7e..535dcddc1dd 100644 --- a/packages/core/core/src/ReporterRunner.js +++ b/packages/core/core/src/ReporterRunner.js @@ -64,10 +64,12 @@ export default class ReporterRunner { let bundle: InternalBundle = event.bundle; // Convert any internal bundles back to their public equivalents as reporting // is public api - let bundleGraph = this.workerFarm.workerApi.getSharedReference( - // $FlowFixMe - bundleGraphRef, - ); + let bundleGraph = + event.bundleGraph ?? + this.workerFarm.workerApi.getSharedReference( + // $FlowFixMe + bundleGraphRef, + ); invariant(bundleGraph instanceof BundleGraph); // $FlowFixMe[incompatible-call] this.report({ diff --git a/packages/core/core/src/requests/PackageRequest.js b/packages/core/core/src/requests/PackageRequest.js index e02c605fd30..33c4a967071 100644 --- a/packages/core/core/src/requests/PackageRequest.js +++ b/packages/core/core/src/requests/PackageRequest.js @@ -18,7 +18,7 @@ import createParcelConfigRequest from './ParcelConfigRequest'; type PackageRequestInput = {| bundleGraph: BundleGraph, bundle: Bundle, - bundleGraphReference: SharedReference, + bundleGraphReference?: SharedReference, optionsRef: SharedReference, |}; @@ -54,10 +54,12 @@ async function run({input, api, farm}: RunInput) { let {cachePath} = nullthrows( await api.runRequest(createParcelConfigRequest()), ); + let {devDepRequests, configRequests, bundleInfo, invalidations} = await runPackage({ bundle, - bundleGraphReference, + bundleGraphReference: + bundleGraphReference == null ? input.bundleGraph : bundleGraphReference, optionsRef, configCachePath: cachePath, previousDevDeps: devDeps, diff --git a/packages/core/core/src/requests/WriteBundlesRequest.js b/packages/core/core/src/requests/WriteBundlesRequest.js index bdfcbcf1360..870fbd3507c 100644 --- a/packages/core/core/src/requests/WriteBundlesRequest.js +++ b/packages/core/core/src/requests/WriteBundlesRequest.js @@ -49,10 +49,6 @@ export default function createWriteBundlesRequest( async function run({input, api, farm, options}: RunInput) { let {bundleGraph, optionsRef} = input; - let {ref, dispose} = await farm.createSharedReference( - bundleGraph, - serialize(bundleGraph), - ); api.invalidateOnOptionChange('shouldContentHash'); @@ -80,9 +76,25 @@ async function run({input, api, farm, options}: RunInput) { return false; } + // Filter out skippable requests. + // if (api.canSkipSubrequest(bundleGraph.getHash(bundle))) { + // // console.log('skipping', bundle.id); + // return false; + // } + return true; }); + let ref; + let dispose; + + // Create shared reference in WorkerFarm if we need to change multiple bundles. + if (bundles.length > 1) { + ({ref, dispose} = await farm.createSharedReference( + bundleGraph, + serialize(bundleGraph), + )); + } try { await Promise.all( bundles.map(async bundle => { @@ -133,7 +145,9 @@ async function run({input, api, farm, options}: RunInput) { api.storeResult(res); return res; } finally { - await dispose(); + if (dispose) { + await dispose(); + } } } diff --git a/packages/core/core/src/worker.js b/packages/core/core/src/worker.js index bb1467076f5..22da7b05041 100644 --- a/packages/core/core/src/worker.js +++ b/packages/core/core/src/worker.js @@ -121,7 +121,7 @@ export async function runPackage( previousInvalidations, }: {| bundle: Bundle, - bundleGraphReference: SharedReference, + bundleGraphReference: SharedReference | BundleGraph, configCachePath: string, optionsRef: SharedReference, previousDevDeps: Map, @@ -129,7 +129,10 @@ export async function runPackage( previousInvalidations: Array, |}, ): Promise { - let bundleGraph = workerApi.getSharedReference(bundleGraphReference); + let bundleGraph = + typeof bundleGraphReference === 'number' + ? workerApi.getSharedReference(bundleGraphReference) + : bundleGraphReference; invariant(bundleGraph instanceof BundleGraph); let options = loadOptions(optionsRef, workerApi); let parcelConfig = await loadConfig(configCachePath, options); diff --git a/packages/core/types/index.js b/packages/core/types/index.js index 2c1ca94685e..a57400f8089 100644 --- a/packages/core/types/index.js +++ b/packages/core/types/index.js @@ -1750,6 +1750,7 @@ export type PackagingProgressEvent = {| +type: 'buildProgress', +phase: 'packaging', +bundle: NamedBundle, + +bundleGraph?: BundleGraph, |}; /** @@ -1760,6 +1761,7 @@ export type OptimizingProgressEvent = {| +type: 'buildProgress', +phase: 'optimizing', +bundle: NamedBundle, + +bundleGraph?: BundleGraph, |}; /** From 43847dda032c280d8795b709d3c4f6be5bc1e917 Mon Sep 17 00:00:00 2001 From: thebriando Date: Fri, 2 Sep 2022 13:16:55 -0700 Subject: [PATCH 02/12] Fix flow errors --- packages/core/types/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/core/types/index.js b/packages/core/types/index.js index 076e72b1c48..f1bf04575e8 100644 --- a/packages/core/types/index.js +++ b/packages/core/types/index.js @@ -5,6 +5,7 @@ import type SourceMap from '@parcel/source-map'; import type {FileSystem} from '@parcel/fs'; import type WorkerFarm from '@parcel/workers'; import type {PackageManager} from '@parcel/package-manager'; +import type InternalBundleGraph from '../core/src/BundleGraph'; import type { Diagnostic, Diagnostifiable, @@ -1754,7 +1755,7 @@ export type PackagingProgressEvent = {| +type: 'buildProgress', +phase: 'packaging', +bundle: NamedBundle, - +bundleGraph?: BundleGraph, + +bundleGraph?: InternalBundleGraph, |}; /** @@ -1765,7 +1766,7 @@ export type OptimizingProgressEvent = {| +type: 'buildProgress', +phase: 'optimizing', +bundle: NamedBundle, - +bundleGraph?: BundleGraph, + +bundleGraph?: InternalBundleGraph, |}; /** From ad39a493fc99fd68dab059fa115d368edad2d973 Mon Sep 17 00:00:00 2001 From: thebriando Date: Fri, 9 Sep 2022 12:01:11 -0700 Subject: [PATCH 03/12] Use report instead of reportWorker when not farming out --- packages/core/core/src/PackagerRunner.js | 8 ++++++-- packages/core/core/src/ReporterRunner.js | 14 +++++++++++++- packages/core/core/src/worker.js | 8 ++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/packages/core/core/src/PackagerRunner.js b/packages/core/core/src/PackagerRunner.js index a82e023c1e5..2b2bd5b89d7 100644 --- a/packages/core/core/src/PackagerRunner.js +++ b/packages/core/core/src/PackagerRunner.js @@ -67,6 +67,7 @@ type Opts = {| report: ReportFn, previousDevDeps: Map, previousInvalidations: Array, + useFarm: boolean, |}; export type PackageRequestResult = {| @@ -109,6 +110,7 @@ export default class PackagerRunner { devDepRequests: Map; invalidations: Map; previousInvalidations: Array; + useFarm: boolean; constructor({ config, @@ -116,6 +118,7 @@ export default class PackagerRunner { report, previousDevDeps, previousInvalidations, + useFarm, }: Opts) { this.config = config; this.options = options; @@ -123,6 +126,7 @@ export default class PackagerRunner { this.previousDevDeps = previousDevDeps; this.devDepRequests = new Map(); this.previousInvalidations = previousInvalidations; + this.useFarm = useFarm; this.invalidations = new Map(); this.pluginOptions = new PluginOptions( optionsProxy(this.options, option => { @@ -325,7 +329,7 @@ export default class PackagerRunner { type: 'buildProgress', phase: 'packaging', bundle, - bundleGraph, + bundleGraph: this.useFarm ? undefined : bundleGraph, }); let packager = await this.config.getPackager(bundle.name); @@ -419,7 +423,7 @@ export default class PackagerRunner { type: 'buildProgress', phase: 'optimizing', bundle, - bundleGraph: internalBundleGraph, + bundleGraph: this.useFarm ? undefined : internalBundleGraph, }); let optimized = { diff --git a/packages/core/core/src/ReporterRunner.js b/packages/core/core/src/ReporterRunner.js index 535dcddc1dd..6b358871343 100644 --- a/packages/core/core/src/ReporterRunner.js +++ b/packages/core/core/src/ReporterRunner.js @@ -133,5 +133,17 @@ export function reportWorker(workerApi: WorkerApi, event: ReporterEvent) { } export function report(event: ReporterEvent) { - bus.emit('reporterEvent', event); + if ( + event.bundleGraph && + event.type === 'buildProgress' && + (event.phase === 'optimizing' || event.phase === 'packaging') + ) { + bus.emit('reporterEvent', { + ...event, + bundle: bundleToInternalBundle(event.bundle), + bundleGraphRef: event.bundleGraph, + }); + } else { + bus.emit('reporterEvent', event); + } } diff --git a/packages/core/core/src/worker.js b/packages/core/core/src/worker.js index 22da7b05041..4664a2e66a9 100644 --- a/packages/core/core/src/worker.js +++ b/packages/core/core/src/worker.js @@ -17,7 +17,7 @@ import Transformation, { type TransformationOpts, type TransformationResult, } from './Transformation'; -import {reportWorker} from './ReporterRunner'; +import {reportWorker, report} from './ReporterRunner'; import PackagerRunner, {type PackageRequestResult} from './PackagerRunner'; import Validation, {type ValidationOpts} from './Validation'; import ParcelConfig from './ParcelConfig'; @@ -140,9 +140,13 @@ export async function runPackage( let runner = new PackagerRunner({ config: parcelConfig, options, - report: reportWorker.bind(null, workerApi), + report: + typeof bundleGraphReference === 'number' + ? reportWorker.bind(null, workerApi) + : report, previousDevDeps, previousInvalidations, + useFarm: typeof bundleGraphReference === 'number' ? true : false, }); return runner.run(bundleGraph, bundle, invalidDevDeps); From 350e01e68b01202ff80afbf609b86ed90cec3fd0 Mon Sep 17 00:00:00 2001 From: thebriando Date: Tue, 20 Sep 2022 10:55:48 +1000 Subject: [PATCH 04/12] Don't serialize if we can skip all bundle subrequests --- .../core/core/src/requests/WriteBundlesRequest.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/core/core/src/requests/WriteBundlesRequest.js b/packages/core/core/src/requests/WriteBundlesRequest.js index 870fbd3507c..891c02f3f13 100644 --- a/packages/core/core/src/requests/WriteBundlesRequest.js +++ b/packages/core/core/src/requests/WriteBundlesRequest.js @@ -76,20 +76,18 @@ async function run({input, api, farm, options}: RunInput) { return false; } - // Filter out skippable requests. - // if (api.canSkipSubrequest(bundleGraph.getHash(bundle))) { - // // console.log('skipping', bundle.id); - // return false; - // } - return true; }); let ref; let dispose; - // Create shared reference in WorkerFarm if we need to change multiple bundles. - if (bundles.length > 1) { + // Create shared reference in WorkerFarm if we need to change multiple bundles and if we + // can't skip the subrequests for all the bundles + if ( + bundles.length > 1 && + bundles.some(b => !api.canSkipSubrequest(bundleGraph.getHash(b))) + ) { ({ref, dispose} = await farm.createSharedReference( bundleGraph, serialize(bundleGraph), From ddf8a34facecef8788542b9b96cabf4bc1741fd0 Mon Sep 17 00:00:00 2001 From: thebriando Date: Wed, 5 Oct 2022 13:08:21 -0700 Subject: [PATCH 05/12] Change condition to not serialize with single bundle case --- packages/core/core/src/requests/WriteBundlesRequest.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/core/src/requests/WriteBundlesRequest.js b/packages/core/core/src/requests/WriteBundlesRequest.js index 891c02f3f13..e9089c89973 100644 --- a/packages/core/core/src/requests/WriteBundlesRequest.js +++ b/packages/core/core/src/requests/WriteBundlesRequest.js @@ -86,7 +86,8 @@ async function run({input, api, farm, options}: RunInput) { // can't skip the subrequests for all the bundles if ( bundles.length > 1 && - bundles.some(b => !api.canSkipSubrequest(bundleGraph.getHash(b))) + bundles.filter(b => !api.canSkipSubrequest(bundleGraph.getHash(b))).length > + 1 ) { ({ref, dispose} = await farm.createSharedReference( bundleGraph, From 32bef5819d3cb29cd286debc6916f536a1dc5281 Mon Sep 17 00:00:00 2001 From: thebriando Date: Mon, 17 Oct 2022 22:28:39 -0700 Subject: [PATCH 06/12] Prevent serialization in PackageRequest --- packages/core/core/src/requests/PackageRequest.js | 5 +++-- .../core/core/src/requests/WriteBundlesRequest.js | 3 +++ packages/core/workers/src/WorkerFarm.js | 13 +++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/core/core/src/requests/PackageRequest.js b/packages/core/core/src/requests/PackageRequest.js index 33c4a967071..3740fb217e4 100644 --- a/packages/core/core/src/requests/PackageRequest.js +++ b/packages/core/core/src/requests/PackageRequest.js @@ -20,6 +20,7 @@ type PackageRequestInput = {| bundle: Bundle, bundleGraphReference?: SharedReference, optionsRef: SharedReference, + shouldSerialize?: boolean, |}; type RunInput = {| @@ -46,8 +47,8 @@ export function createPackageRequest( } async function run({input, api, farm}: RunInput) { - let {bundleGraphReference, optionsRef, bundle} = input; - let runPackage = farm.createHandle('runPackage'); + let {bundleGraphReference, optionsRef, bundle, shouldSerialize} = input; + let runPackage = farm.createHandle('runPackage', shouldSerialize); let start = Date.now(); let {devDeps, invalidDevDeps} = await getDevDepRequests(api); diff --git a/packages/core/core/src/requests/WriteBundlesRequest.js b/packages/core/core/src/requests/WriteBundlesRequest.js index e9089c89973..a299156e0f3 100644 --- a/packages/core/core/src/requests/WriteBundlesRequest.js +++ b/packages/core/core/src/requests/WriteBundlesRequest.js @@ -84,11 +84,13 @@ async function run({input, api, farm, options}: RunInput) { // Create shared reference in WorkerFarm if we need to change multiple bundles and if we // can't skip the subrequests for all the bundles + let shouldSerialize = false; if ( bundles.length > 1 && bundles.filter(b => !api.canSkipSubrequest(bundleGraph.getHash(b))).length > 1 ) { + shouldSerialize = true; ({ref, dispose} = await farm.createSharedReference( bundleGraph, serialize(bundleGraph), @@ -102,6 +104,7 @@ async function run({input, api, farm, options}: RunInput) { bundleGraph, bundleGraphReference: ref, optionsRef, + shouldSerialize, }); let info = await api.runRequest(request); diff --git a/packages/core/workers/src/WorkerFarm.js b/packages/core/workers/src/WorkerFarm.js index 03228f4ea88..6cdb42a8df7 100644 --- a/packages/core/workers/src/WorkerFarm.js +++ b/packages/core/workers/src/WorkerFarm.js @@ -175,7 +175,7 @@ export default class WorkerFarm extends EventEmitter { ); } - createHandle(method: string): HandleFunction { + createHandle(method: string, shouldSerialize?: boolean): HandleFunction { return async (...args) => { // Child process workers are slow to start (~600ms). // While we're waiting, just run on the main thread. @@ -187,9 +187,14 @@ export default class WorkerFarm extends EventEmitter { this.warmupWorker(method, args); } - let processedArgs = restoreDeserializedObject( - prepareForSerialization([...args, false]), - ); + let processedArgs; + if (shouldSerialize) { + processedArgs = restoreDeserializedObject( + prepareForSerialization([...args, false]), + ); + } else { + processedArgs = args; + } if (this.localWorkerInit != null) { await this.localWorkerInit; From d3ec1646667b14ce9bf86bfd22f1e6a3d646253b Mon Sep 17 00:00:00 2001 From: thebriando Date: Mon, 24 Oct 2022 13:09:14 -0700 Subject: [PATCH 07/12] Don't use remote workers when serialization is skipped --- packages/core/workers/src/WorkerFarm.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core/workers/src/WorkerFarm.js b/packages/core/workers/src/WorkerFarm.js index 6cdb42a8df7..057863ae49a 100644 --- a/packages/core/workers/src/WorkerFarm.js +++ b/packages/core/workers/src/WorkerFarm.js @@ -175,12 +175,15 @@ export default class WorkerFarm extends EventEmitter { ); } - createHandle(method: string, shouldSerialize?: boolean): HandleFunction { + createHandle( + method: string, + shouldSerialize: boolean = true, + ): HandleFunction { return async (...args) => { // Child process workers are slow to start (~600ms). // While we're waiting, just run on the main thread. // This significantly speeds up startup time. - if (this.shouldUseRemoteWorkers()) { + if (this.shouldUseRemoteWorkers() && shouldSerialize) { return this.addCall(method, [...args, false]); } else { if (this.options.warmWorkers && this.shouldStartRemoteWorkers()) { From cf5b3ffdaadb3de90104a6d24261e1aad9c496fd Mon Sep 17 00:00:00 2001 From: thebriando Date: Mon, 24 Oct 2022 14:52:44 -0700 Subject: [PATCH 08/12] Fix import --- packages/core/types/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/types/index.js b/packages/core/types/index.js index f1bf04575e8..b7de0060f1d 100644 --- a/packages/core/types/index.js +++ b/packages/core/types/index.js @@ -5,7 +5,7 @@ import type SourceMap from '@parcel/source-map'; import type {FileSystem} from '@parcel/fs'; import type WorkerFarm from '@parcel/workers'; import type {PackageManager} from '@parcel/package-manager'; -import type InternalBundleGraph from '../core/src/BundleGraph'; +import type InternalBundleGraph from '@parcel/core'; import type { Diagnostic, Diagnostifiable, From 51f357534538fb1451c47365bb48a102d1d8f81f Mon Sep 17 00:00:00 2001 From: thebriando Date: Mon, 24 Oct 2022 15:56:18 -0700 Subject: [PATCH 09/12] Revert "Fix import" This reverts commit cf5b3ffdaadb3de90104a6d24261e1aad9c496fd. --- packages/core/types/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/types/index.js b/packages/core/types/index.js index b7de0060f1d..f1bf04575e8 100644 --- a/packages/core/types/index.js +++ b/packages/core/types/index.js @@ -5,7 +5,7 @@ import type SourceMap from '@parcel/source-map'; import type {FileSystem} from '@parcel/fs'; import type WorkerFarm from '@parcel/workers'; import type {PackageManager} from '@parcel/package-manager'; -import type InternalBundleGraph from '@parcel/core'; +import type InternalBundleGraph from '../core/src/BundleGraph'; import type { Diagnostic, Diagnostifiable, From 8bf905ad35f9c6cc594ffdaae13bf1f7f22ae918 Mon Sep 17 00:00:00 2001 From: thebriando Date: Wed, 26 Oct 2022 14:50:12 -0700 Subject: [PATCH 10/12] Send BundleGraph through separate ReporterEvent --- packages/core/core/src/PackagerRunner.js | 28 ++++++++++++++++++------ packages/core/core/src/ReporterRunner.js | 8 +++++-- packages/core/types/index.js | 17 +++++++++----- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/packages/core/core/src/PackagerRunner.js b/packages/core/core/src/PackagerRunner.js index dfaa780eec0..05cc443d848 100644 --- a/packages/core/core/src/PackagerRunner.js +++ b/packages/core/core/src/PackagerRunner.js @@ -390,11 +390,23 @@ export default class PackagerRunner { bundleConfigs: Map, ): Promise { let bundle = NamedBundle.get(internalBundle, bundleGraph, this.options); + let publicBundleGraph = new BundleGraph( + bundleGraph, + NamedBundle.get.bind(NamedBundle), + this.options, + ); + + if (this.useFarm) { + this.report({ + type: 'bundleGraph', + bundleGraph: publicBundleGraph, + }); + } + this.report({ type: 'buildProgress', phase: 'packaging', bundle, - bundleGraph: this.useFarm ? undefined : bundleGraph, }); let packager = await this.config.getPackager(bundle.name); @@ -404,11 +416,7 @@ export default class PackagerRunner { config: configs.get(name)?.result, bundleConfig: bundleConfigs.get(name)?.result, bundle, - bundleGraph: new BundleGraph( - bundleGraph, - NamedBundle.get.bind(NamedBundle), - this.options, - ), + bundleGraph: publicBundleGraph, getSourceMapReference: map => { return this.getSourceMapReference(bundle, map); }, @@ -487,11 +495,17 @@ export default class PackagerRunner { return {type: bundle.type, contents, map}; } + if (this.useFarm) { + this.report({ + type: 'bundleGraph', + bundleGraph, + }); + } + this.report({ type: 'buildProgress', phase: 'optimizing', bundle, - bundleGraph: this.useFarm ? undefined : internalBundleGraph, }); let optimized = { diff --git a/packages/core/core/src/ReporterRunner.js b/packages/core/core/src/ReporterRunner.js index 6b358871343..a80f7d0da03 100644 --- a/packages/core/core/src/ReporterRunner.js +++ b/packages/core/core/src/ReporterRunner.js @@ -21,6 +21,7 @@ import logger, { } from '@parcel/logger'; import PluginOptions from './public/PluginOptions'; import BundleGraph from './BundleGraph'; +import {bundleGraphToInternalBundleGraph} from './public/BundleGraph'; type Opts = {| config: ParcelConfig, @@ -34,6 +35,7 @@ export default class ReporterRunner { options: ParcelOptions; pluginOptions: PluginOptions; reporters: Array>; + bundleGraph: BundleGraph; constructor(opts: Opts) { this.config = opts.config; @@ -53,7 +55,9 @@ export default class ReporterRunner { } eventHandler: ReporterEvent => void = (event): void => { - if ( + if (event.type === 'bundleGraph') { + this.bundleGraph = bundleGraphToInternalBundleGraph(event.bundleGraph); + } else if ( event.type === 'buildProgress' && (event.phase === 'optimizing' || event.phase === 'packaging') && !(event.bundle instanceof NamedBundle) @@ -65,7 +69,7 @@ export default class ReporterRunner { // Convert any internal bundles back to their public equivalents as reporting // is public api let bundleGraph = - event.bundleGraph ?? + this.bundleGraph ?? this.workerFarm.workerApi.getSharedReference( // $FlowFixMe bundleGraphRef, diff --git a/packages/core/types/index.js b/packages/core/types/index.js index 4867144a2bd..09792eae736 100644 --- a/packages/core/types/index.js +++ b/packages/core/types/index.js @@ -5,7 +5,6 @@ import type SourceMap from '@parcel/source-map'; import type {FileSystem} from '@parcel/fs'; import type WorkerFarm from '@parcel/workers'; import type {PackageManager} from '@parcel/package-manager'; -import type InternalBundleGraph from '../core/src/BundleGraph'; import type { Diagnostic, Diagnostifiable, @@ -1710,7 +1709,11 @@ export type TextLogEvent = {| /** * @section reporter */ -export type LogEvent = ProgressLogEvent | DiagnosticLogEvent | TextLogEvent; +export type LogEvent = + | ProgressLogEvent + | DiagnosticLogEvent + | TextLogEvent + | BundleGraphEvent; /** * The build just started. @@ -1765,6 +1768,11 @@ export type BundlingProgressEvent = {| +phase: 'bundling', |}; +export type BundleGraphEvent = {| + +type: 'bundleGraph', + +bundleGraph: BundleGraph, +|}; + /** * A new Bundle is being packaged. * @section reporter @@ -1773,7 +1781,6 @@ export type PackagingProgressEvent = {| +type: 'buildProgress', +phase: 'packaging', +bundle: NamedBundle, - +bundleGraph?: InternalBundleGraph, |}; /** @@ -1784,7 +1791,6 @@ export type OptimizingProgressEvent = {| +type: 'buildProgress', +phase: 'optimizing', +bundle: NamedBundle, - +bundleGraph?: InternalBundleGraph, |}; /** @@ -1843,7 +1849,8 @@ export type ReporterEvent = | BuildFailureEvent | WatchStartEvent | WatchEndEvent - | ValidationEvent; + | ValidationEvent + | BundleGraphEvent; /** * @section reporter From df73a17bd37333cec1421ddfe71a5640a453c00b Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sun, 30 Oct 2022 17:59:07 -0700 Subject: [PATCH 11/12] Only serialize and send shared references to workers that need them --- packages/core/core/src/PackagerRunner.js | 30 ++------ packages/core/core/src/Parcel.js | 2 +- packages/core/core/src/ReporterRunner.js | 30 ++------ .../core/src/requests/BundleGraphRequest.js | 7 +- .../core/core/src/requests/PackageRequest.js | 11 ++- .../core/src/requests/WriteBundlesRequest.js | 32 +++------ packages/core/core/src/types.js | 1 + packages/core/core/src/worker.js | 14 ++-- packages/core/types/index.js | 14 +--- packages/core/workers/src/Worker.js | 3 +- packages/core/workers/src/WorkerFarm.js | 69 +++++++++++++------ 11 files changed, 86 insertions(+), 127 deletions(-) diff --git a/packages/core/core/src/PackagerRunner.js b/packages/core/core/src/PackagerRunner.js index 05cc443d848..e31746f51f2 100644 --- a/packages/core/core/src/PackagerRunner.js +++ b/packages/core/core/src/PackagerRunner.js @@ -68,7 +68,6 @@ type Opts = {| report: ReportFn, previousDevDeps: Map, previousInvalidations: Array, - useFarm: boolean, |}; export type PackageRequestResult = {| @@ -111,7 +110,6 @@ export default class PackagerRunner { devDepRequests: Map; invalidations: Map; previousInvalidations: Array; - useFarm: boolean; constructor({ config, @@ -119,7 +117,6 @@ export default class PackagerRunner { report, previousDevDeps, previousInvalidations, - useFarm, }: Opts) { this.config = config; this.options = options; @@ -127,7 +124,6 @@ export default class PackagerRunner { this.previousDevDeps = previousDevDeps; this.devDepRequests = new Map(); this.previousInvalidations = previousInvalidations; - this.useFarm = useFarm; this.invalidations = new Map(); this.pluginOptions = new PluginOptions( optionsProxy(this.options, option => { @@ -390,19 +386,6 @@ export default class PackagerRunner { bundleConfigs: Map, ): Promise { let bundle = NamedBundle.get(internalBundle, bundleGraph, this.options); - let publicBundleGraph = new BundleGraph( - bundleGraph, - NamedBundle.get.bind(NamedBundle), - this.options, - ); - - if (this.useFarm) { - this.report({ - type: 'bundleGraph', - bundleGraph: publicBundleGraph, - }); - } - this.report({ type: 'buildProgress', phase: 'packaging', @@ -416,7 +399,11 @@ export default class PackagerRunner { config: configs.get(name)?.result, bundleConfig: bundleConfigs.get(name)?.result, bundle, - bundleGraph: publicBundleGraph, + bundleGraph: new BundleGraph( + bundleGraph, + NamedBundle.get.bind(NamedBundle), + this.options, + ), getSourceMapReference: map => { return this.getSourceMapReference(bundle, map); }, @@ -495,13 +482,6 @@ export default class PackagerRunner { return {type: bundle.type, contents, map}; } - if (this.useFarm) { - this.report({ - type: 'bundleGraph', - bundleGraph, - }); - } - this.report({ type: 'buildProgress', phase: 'optimizing', diff --git a/packages/core/core/src/Parcel.js b/packages/core/core/src/Parcel.js index 8688c081716..40e9c448b8b 100644 --- a/packages/core/core/src/Parcel.js +++ b/packages/core/core/src/Parcel.js @@ -110,7 +110,7 @@ export default class Parcel { await resolvedOptions.cache.ensure(); let {dispose: disposeOptions, ref: optionsRef} = - await this.#farm.createSharedReference(resolvedOptions); + await this.#farm.createSharedReference(resolvedOptions, false); this.#optionsRef = optionsRef; this.#disposable = new Disposable(); diff --git a/packages/core/core/src/ReporterRunner.js b/packages/core/core/src/ReporterRunner.js index a80f7d0da03..9b07912bb7e 100644 --- a/packages/core/core/src/ReporterRunner.js +++ b/packages/core/core/src/ReporterRunner.js @@ -21,7 +21,6 @@ import logger, { } from '@parcel/logger'; import PluginOptions from './public/PluginOptions'; import BundleGraph from './BundleGraph'; -import {bundleGraphToInternalBundleGraph} from './public/BundleGraph'; type Opts = {| config: ParcelConfig, @@ -35,7 +34,6 @@ export default class ReporterRunner { options: ParcelOptions; pluginOptions: PluginOptions; reporters: Array>; - bundleGraph: BundleGraph; constructor(opts: Opts) { this.config = opts.config; @@ -55,9 +53,7 @@ export default class ReporterRunner { } eventHandler: ReporterEvent => void = (event): void => { - if (event.type === 'bundleGraph') { - this.bundleGraph = bundleGraphToInternalBundleGraph(event.bundleGraph); - } else if ( + if ( event.type === 'buildProgress' && (event.phase === 'optimizing' || event.phase === 'packaging') && !(event.bundle instanceof NamedBundle) @@ -68,12 +64,10 @@ export default class ReporterRunner { let bundle: InternalBundle = event.bundle; // Convert any internal bundles back to their public equivalents as reporting // is public api - let bundleGraph = - this.bundleGraph ?? - this.workerFarm.workerApi.getSharedReference( - // $FlowFixMe - bundleGraphRef, - ); + let bundleGraph = this.workerFarm.workerApi.getSharedReference( + // $FlowFixMe + bundleGraphRef, + ); invariant(bundleGraph instanceof BundleGraph); // $FlowFixMe[incompatible-call] this.report({ @@ -137,17 +131,5 @@ export function reportWorker(workerApi: WorkerApi, event: ReporterEvent) { } export function report(event: ReporterEvent) { - if ( - event.bundleGraph && - event.type === 'buildProgress' && - (event.phase === 'optimizing' || event.phase === 'packaging') - ) { - bus.emit('reporterEvent', { - ...event, - bundle: bundleToInternalBundle(event.bundle), - bundleGraphRef: event.bundleGraph, - }); - } else { - bus.emit('reporterEvent', event); - } + bus.emit('reporterEvent', event); } diff --git a/packages/core/core/src/requests/BundleGraphRequest.js b/packages/core/core/src/requests/BundleGraphRequest.js index 248628450f5..44e2ac1e33a 100644 --- a/packages/core/core/src/requests/BundleGraphRequest.js +++ b/packages/core/core/src/requests/BundleGraphRequest.js @@ -48,7 +48,7 @@ import { getConfigHash, type PluginWithLoadConfig, } from './ConfigRequest'; -import {cacheSerializedObject, deserializeToCache} from '../serializer'; +import {deserializeToCache} from '../serializer'; import { joinProjectPath, fromProjectPathRelative, @@ -356,11 +356,8 @@ class BundlerRunner { bundleGraphEdgeTypes, ); - // Store the serialized bundle graph in an in memory cache so that we avoid serializing it - // many times to send to each worker, and in build mode, when writing to cache on shutdown. - // Also, pre-compute the hashes for each bundle so they are only computed once and shared between workers. + // Pre-compute the hashes for each bundle so they are only computed once and shared between workers. internalBundleGraph.getBundleGraphHash(); - cacheSerializedObject(internalBundleGraph); // Recompute the cache key to account for new dev dependencies and invalidations. let {cacheKey: updatedCacheKey} = await this.getHashes(graph); diff --git a/packages/core/core/src/requests/PackageRequest.js b/packages/core/core/src/requests/PackageRequest.js index 4d540112c7c..d2d3067d06a 100644 --- a/packages/core/core/src/requests/PackageRequest.js +++ b/packages/core/core/src/requests/PackageRequest.js @@ -18,9 +18,9 @@ import createParcelConfigRequest from './ParcelConfigRequest'; type PackageRequestInput = {| bundleGraph: BundleGraph, bundle: Bundle, - bundleGraphReference?: SharedReference, + bundleGraphReference: SharedReference, optionsRef: SharedReference, - shouldSerialize?: boolean, + useMainThread?: boolean, |}; type RunInput = {| @@ -47,8 +47,8 @@ export function createPackageRequest( } async function run({input, api, farm}: RunInput) { - let {bundleGraphReference, optionsRef, bundle, shouldSerialize} = input; - let runPackage = farm.createHandle('runPackage', shouldSerialize); + let {bundleGraphReference, optionsRef, bundle, useMainThread} = input; + let runPackage = farm.createHandle('runPackage', useMainThread); let start = Date.now(); let {devDeps, invalidDevDeps} = await getDevDepRequests(api); @@ -59,8 +59,7 @@ async function run({input, api, farm}: RunInput) { let {devDepRequests, configRequests, bundleInfo, invalidations} = (await runPackage({ bundle, - bundleGraphReference: - bundleGraphReference == null ? input.bundleGraph : bundleGraphReference, + bundleGraphReference, optionsRef, configCachePath: cachePath, previousDevDeps: devDeps, diff --git a/packages/core/core/src/requests/WriteBundlesRequest.js b/packages/core/core/src/requests/WriteBundlesRequest.js index f3f4bca9f46..f527c0cb41e 100644 --- a/packages/core/core/src/requests/WriteBundlesRequest.js +++ b/packages/core/core/src/requests/WriteBundlesRequest.js @@ -9,7 +9,6 @@ import type BundleGraph from '../BundleGraph'; import type {BundleInfo} from '../PackagerRunner'; import {HASH_REF_PREFIX} from '../constants'; -import {serialize} from '../serializer'; import {joinProjectPath} from '../projectPath'; import nullthrows from 'nullthrows'; import {hashString} from '@parcel/hash'; @@ -49,6 +48,7 @@ export default function createWriteBundlesRequest( async function run({input, api, farm, options}: RunInput) { let {bundleGraph, optionsRef} = input; + let {ref, dispose} = await farm.createSharedReference(bundleGraph); api.invalidateOnOptionChange('shouldContentHash'); @@ -79,23 +79,13 @@ async function run({input, api, farm, options}: RunInput) { return true; }); - let ref; - let dispose; - - // Create shared reference in WorkerFarm if we need to change multiple bundles and if we - // can't skip the subrequests for all the bundles - let shouldSerialize = false; - if ( - bundles.length > 1 && - bundles.filter(b => !api.canSkipSubrequest(bundleGraph.getHash(b))).length > - 1 - ) { - shouldSerialize = true; - ({ref, dispose} = await farm.createSharedReference( - bundleGraph, - serialize(bundleGraph), - )); - } + // Package on the main thread if there is only one bundle to package. + // This avoids the cost of serializing the bundle graph for single file change builds. + let useMainThread = + bundles.length === 1 || + bundles.filter(b => !api.canSkipSubrequest(bundleGraph.getHash(b))) + .length === 1; + try { await Promise.all( bundles.map(async bundle => { @@ -104,7 +94,7 @@ async function run({input, api, farm, options}: RunInput) { bundleGraph, bundleGraphReference: ref, optionsRef, - shouldSerialize, + useMainThread, }); let info = await api.runRequest(request); @@ -148,9 +138,7 @@ async function run({input, api, farm, options}: RunInput) { api.storeResult(res); return res; } finally { - if (dispose) { - await dispose(); - } + await dispose(); } } diff --git a/packages/core/core/src/types.js b/packages/core/core/src/types.js index f355f636691..474ae5ba9cf 100644 --- a/packages/core/core/src/types.js +++ b/packages/core/core/src/types.js @@ -342,6 +342,7 @@ export type AssetRequestInput = {| optionsRef: SharedReference, isURL?: boolean, query?: ?string, + isSingleChangeRebuild?: boolean, |}; export type AssetRequestResult = Array; diff --git a/packages/core/core/src/worker.js b/packages/core/core/src/worker.js index 4664a2e66a9..b093ce2e3b5 100644 --- a/packages/core/core/src/worker.js +++ b/packages/core/core/src/worker.js @@ -25,6 +25,7 @@ import {registerCoreWithSerializer} from './utils'; import {clearBuildCaches} from './buildCache'; import {init as initSourcemaps} from '@parcel/source-map'; import {init as initHash} from '@parcel/hash'; +import WorkerFarm from '@parcel/workers'; import '@parcel/cache'; // register with serializer import '@parcel/package-manager'; @@ -121,7 +122,7 @@ export async function runPackage( previousInvalidations, }: {| bundle: Bundle, - bundleGraphReference: SharedReference | BundleGraph, + bundleGraphReference: SharedReference, configCachePath: string, optionsRef: SharedReference, previousDevDeps: Map, @@ -129,10 +130,7 @@ export async function runPackage( previousInvalidations: Array, |}, ): Promise { - let bundleGraph = - typeof bundleGraphReference === 'number' - ? workerApi.getSharedReference(bundleGraphReference) - : bundleGraphReference; + let bundleGraph = workerApi.getSharedReference(bundleGraphReference); invariant(bundleGraph instanceof BundleGraph); let options = loadOptions(optionsRef, workerApi); let parcelConfig = await loadConfig(configCachePath, options); @@ -140,13 +138,9 @@ export async function runPackage( let runner = new PackagerRunner({ config: parcelConfig, options, - report: - typeof bundleGraphReference === 'number' - ? reportWorker.bind(null, workerApi) - : report, + report: WorkerFarm.isWorker() ? reportWorker.bind(null, workerApi) : report, previousDevDeps, previousInvalidations, - useFarm: typeof bundleGraphReference === 'number' ? true : false, }); return runner.run(bundleGraph, bundle, invalidDevDeps); diff --git a/packages/core/types/index.js b/packages/core/types/index.js index 0185efa8149..b33e362d816 100644 --- a/packages/core/types/index.js +++ b/packages/core/types/index.js @@ -1710,11 +1710,7 @@ export type TextLogEvent = {| /** * @section reporter */ -export type LogEvent = - | ProgressLogEvent - | DiagnosticLogEvent - | TextLogEvent - | BundleGraphEvent; +export type LogEvent = ProgressLogEvent | DiagnosticLogEvent | TextLogEvent; /** * The build just started. @@ -1769,11 +1765,6 @@ export type BundlingProgressEvent = {| +phase: 'bundling', |}; -export type BundleGraphEvent = {| - +type: 'bundleGraph', - +bundleGraph: BundleGraph, -|}; - /** * A new Bundle is being packaged. * @section reporter @@ -1850,8 +1841,7 @@ export type ReporterEvent = | BuildFailureEvent | WatchStartEvent | WatchEndEvent - | ValidationEvent - | BundleGraphEvent; + | ValidationEvent; /** * @section reporter diff --git a/packages/core/workers/src/Worker.js b/packages/core/workers/src/Worker.js index 833251983ad..e3ad9d1c13c 100644 --- a/packages/core/workers/src/Worker.js +++ b/packages/core/workers/src/Worker.js @@ -31,7 +31,7 @@ export default class Worker extends EventEmitter { +options: WorkerOpts; worker: WorkerImpl; id: number = WORKER_ID++; - sharedReferences: $ReadOnlyMap = new Map(); + sentSharedReferences: Set = new Set(); calls: Map = new Map(); exitCode: ?number = null; @@ -135,6 +135,7 @@ export default class Worker extends EventEmitter { } sendSharedReference(ref: SharedReference, value: mixed): Promise { + this.sentSharedReferences.add(ref); return new Promise((resolve, reject) => { this.call({ method: 'createSharedReference', diff --git a/packages/core/workers/src/WorkerFarm.js b/packages/core/workers/src/WorkerFarm.js index 057863ae49a..afeb0717e61 100644 --- a/packages/core/workers/src/WorkerFarm.js +++ b/packages/core/workers/src/WorkerFarm.js @@ -76,6 +76,7 @@ export default class WorkerFarm extends EventEmitter { handles: Map = new Map(); sharedReferences: Map = new Map(); sharedReferencesByValue: Map = new Map(); + serializedSharedReferences: Map = new Map(); profiler: ?Profiler; constructor(farmOptions: $Shape = {}) { @@ -175,15 +176,12 @@ export default class WorkerFarm extends EventEmitter { ); } - createHandle( - method: string, - shouldSerialize: boolean = true, - ): HandleFunction { + createHandle(method: string, useMainThread: boolean = false): HandleFunction { return async (...args) => { // Child process workers are slow to start (~600ms). // While we're waiting, just run on the main thread. // This significantly speeds up startup time. - if (this.shouldUseRemoteWorkers() && shouldSerialize) { + if (this.shouldUseRemoteWorkers() && !useMainThread) { return this.addCall(method, [...args, false]); } else { if (this.options.warmWorkers && this.shouldStartRemoteWorkers()) { @@ -191,7 +189,7 @@ export default class WorkerFarm extends EventEmitter { } let processedArgs; - if (shouldSerialize) { + if (!useMainThread) { processedArgs = restoreDeserializedObject( prepareForSerialization([...args, false]), ); @@ -281,11 +279,24 @@ export default class WorkerFarm extends EventEmitter { } if (worker.calls.size < this.options.maxConcurrentCallsPerWorker) { - worker.call(this.callQueue.shift()); + this.callWorker(worker, this.callQueue.shift()); } } } + async callWorker(worker: Worker, call: WorkerCall): Promise { + for (let ref of this.sharedReferences.keys()) { + if (!worker.sentSharedReferences.has(ref)) { + await worker.sendSharedReference( + ref, + this.getSerializedSharedReference(ref), + ); + } + } + + worker.call(call); + } + async processRequest( data: {| location: FilePath, @@ -408,33 +419,31 @@ export default class WorkerFarm extends EventEmitter { return handle; } - async createSharedReference( + createSharedReference( value: mixed, - // An optional, pre-serialized representation of the value to be used - // in its place. - buffer?: Buffer, - ): Promise<{|ref: SharedReference, dispose(): Promise|}> { + isCacheable: boolean = true, + ): {|ref: SharedReference, dispose(): Promise|} { let ref = referenceId++; this.sharedReferences.set(ref, value); this.sharedReferencesByValue.set(value, ref); - - let toSend = buffer ? buffer.buffer : value; - let promises = []; - for (let worker of this.workers.values()) { - if (worker.ready) { - promises.push(worker.sendSharedReference(ref, toSend)); - } + if (!isCacheable) { + this.serializedSharedReferences.set(ref, null); } - await Promise.all(promises); - return { ref, dispose: () => { this.sharedReferences.delete(ref); this.sharedReferencesByValue.delete(value); + this.serializedSharedReferences.delete(ref); + let promises = []; for (let worker of this.workers.values()) { + if (!worker.sentSharedReferences.has(ref)) { + continue; + } + + worker.sentSharedReferences.delete(ref); promises.push( new Promise((resolve, reject) => { worker.call({ @@ -453,6 +462,24 @@ export default class WorkerFarm extends EventEmitter { }; } + getSerializedSharedReference(ref: SharedReference): ArrayBuffer { + let cached = this.serializedSharedReferences.get(ref); + if (cached) { + return cached; + } + + let value = this.sharedReferences.get(ref); + let buf = serialize(value).buffer; + + // If the reference was created with the isCacheable option set to false, + // serializedSharedReferences will contain `null` as the value. + if (cached !== null) { + this.serializedSharedReferences.set(ref, buf); + } + + return buf; + } + async startProfile() { let promises = []; for (let worker of this.workers.values()) { From 48c8e7972bd589a08af1716744780a0cc5b8f3b3 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sun, 30 Oct 2022 18:01:14 -0700 Subject: [PATCH 12/12] Also transform on the main thread if only one file changed --- packages/core/core/src/RequestTracker.js | 21 +++++++++++++++++++ .../core/src/requests/AssetGraphRequest.js | 7 +++++++ .../core/core/src/requests/AssetRequest.js | 5 ++++- packages/core/core/test/TargetRequest.test.js | 3 +++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index 08e5c73b453..4be5114b359 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -145,6 +145,7 @@ export type RunAPI = {| getRequestResult(contentKey: ContentKey): Async, getPreviousResult(ifMatch?: string): Async, getSubRequests(): Array, + getInvalidSubRequests(): Array, canSkipSubrequest(ContentKey): boolean, runRequest: ( subRequest: Request, @@ -635,6 +636,25 @@ export class RequestGraph extends ContentGraph< }); } + getInvalidSubRequests(requestNodeId: NodeId): Array { + if (!this.hasNode(requestNodeId)) { + return []; + } + + let subRequests = this.getNodeIdsConnectedFrom( + requestNodeId, + requestGraphEdgeTypes.subrequest, + ); + + return subRequests + .filter(id => this.invalidNodeIds.has(id)) + .map(nodeId => { + let node = nullthrows(this.getNode(nodeId)); + invariant(node.type === 'request'); + return node.value; + }); + } + invalidateFileNameNode( node: FileNameNode, filePath: ProjectPath, @@ -1028,6 +1048,7 @@ export default class RequestTracker { this.storeResult(requestId, result, cacheKey); }, getSubRequests: () => this.graph.getSubRequests(requestId), + getInvalidSubRequests: () => this.graph.getInvalidSubRequests(requestId), getPreviousResult: (ifMatch?: string): Async => { let contentKey = nullthrows(this.graph.getNode(requestId)?.id); return this.getRequestResult(contentKey, ifMatch); diff --git a/packages/core/core/src/requests/AssetGraphRequest.js b/packages/core/core/src/requests/AssetGraphRequest.js index 2b0d55073d5..7275a016355 100644 --- a/packages/core/core/src/requests/AssetGraphRequest.js +++ b/packages/core/core/src/requests/AssetGraphRequest.js @@ -121,6 +121,7 @@ export class AssetGraphBuilder { cacheKey: string; shouldBuildLazily: boolean; requestedAssetIds: Set; + isSingleChangeRebuild: boolean; constructor( {input, api, options}: RunInput, @@ -151,6 +152,9 @@ export class AssetGraphBuilder { `${PARCEL_VERSION}${name}${JSON.stringify(entries) ?? ''}${options.mode}`, ); + this.isSingleChangeRebuild = + api.getInvalidSubRequests().filter(req => req.type === 'asset_request') + .length === 1; this.queue = new PromiseQueue(); } @@ -989,6 +993,7 @@ export class AssetGraphBuilder { ...input, name: this.name, optionsRef: this.optionsRef, + isSingleChangeRebuild: this.isSingleChangeRebuild, }); let assets = await this.api.runRequest>( request, @@ -1015,6 +1020,8 @@ export class AssetGraphBuilder { } else { this.assetGraph.safeToIncrementallyBundle = false; } + + this.isSingleChangeRebuild = false; } /** diff --git a/packages/core/core/src/requests/AssetRequest.js b/packages/core/core/src/requests/AssetRequest.js index a02541d092e..520ede77cde 100644 --- a/packages/core/core/src/requests/AssetRequest.js +++ b/packages/core/core/src/requests/AssetRequest.js @@ -133,7 +133,10 @@ async function run({input, api, farm, invalidateReason, options}: RunInput) { invalidations, invalidateOnFileCreate, devDepRequests, - } = (await farm.createHandle('runTransform')({ + } = (await farm.createHandle( + 'runTransform', + input.isSingleChangeRebuild, + )({ configCachePath: cachePath, optionsRef, request, diff --git a/packages/core/core/test/TargetRequest.test.js b/packages/core/core/test/TargetRequest.test.js index b8db4e11e69..646574da410 100644 --- a/packages/core/core/test/TargetRequest.test.js +++ b/packages/core/core/test/TargetRequest.test.js @@ -93,6 +93,9 @@ describe('TargetResolver', () => { getSubRequests() { return []; }, + getInvalidSubRequests() { + return []; + }, }; it('resolves exactly specified targets', async () => {