@@ -9,11 +9,7 @@ import { getBuildOutputFolder } from "./getBuildOutputFolder";
99import { getPackageSourceHash } from "./getPackageSourceHash" ;
1010import { getBuildMeta } from "./getBuildMeta" ;
1111import { getPackageCacheFolderPath } from "./getPackageCacheFolderPath" ;
12- import {
13- distBuildHashMatches ,
14- writeDistBuildHash ,
15- isExperimentalBuildCacheEnabled
16- } from "./distBuildHash" ;
12+ import { distMatchesCache , recordCacheHash } from "./distContentHash" ;
1713
1814const { green } = chalk ;
1915
@@ -28,9 +24,6 @@ export async function getBatches(options: GetBatchesOptions = {}) {
2824
2925 const packagesNoCache : Package [ ] = [ ] ;
3026 const packagesUseCache : Package [ ] = [ ] ;
31- // Source hash of each cache-hit package, reused below to skip the cache→dist
32- // copy when the existing dist was already built from that same hash.
33- const cacheHitHashes = new Map < string , string > ( ) ;
3427
3528 let workspacesPackages = (
3629 getPackages ( {
@@ -70,7 +63,6 @@ export async function getBatches(options: GetBatchesOptions = {}) {
7063
7164 if ( packageMeta . sourceHash === sourceHash ) {
7265 packagesUseCache . push ( workspacePackage ) ;
73- cacheHitHashes . set ( workspacePackage . name , sourceHash ) ;
7466 } else {
7567 packagesNoCache . push ( workspacePackage ) ;
7668 }
@@ -123,31 +115,30 @@ export async function getBatches(options: GetBatchesOptions = {}) {
123115 }
124116 }
125117
126- const experimentalCache = isExperimentalBuildCacheEnabled ( ) ;
118+ // Skip the cache→dist copy for packages whose dist already matches the
119+ // cache byte-for-byte (content hash). Reads actual bytes in parallel, so
120+ // it can't go stale from out-of-band dist writes (`webiny watch`, manual
121+ // edits) — those change the hash and force a copy.
122+ const fresh = await Promise . all ( packagesUseCache . map ( pkg => distMatchesCache ( pkg ) ) ) ;
127123
128- let copied = 0 ;
124+ const restored : Package [ ] = [ ] ;
129125 for ( let i = 0 ; i < packagesUseCache . length ; i ++ ) {
130126 const workspacePackage = packagesUseCache [ i ] ;
131- const sourceHash = cacheHitHashes . get ( workspacePackage . name ) ! ;
132127
133- // EXPERIMENTAL (opt-in): skip the copy when dist was already
134- // built/restored from this exact source hash — the bytes on disk are
135- // already identical. Off by default; the marker can go stale if
136- // something writes dist out of band (e.g. `webiny watch`).
137- if ( experimentalCache && distBuildHashMatches ( workspacePackage , sourceHash ) ) {
128+ if ( fresh [ i ] ) {
138129 continue ;
139130 }
140131
141132 const cacheFolderPath = path . join ( CACHE_FOLDER_PATH , workspacePackage . packageJson . name ) ;
142133 fs . copySync ( cacheFolderPath , getBuildOutputFolder ( workspacePackage ) ) ;
143- if ( experimentalCache ) {
144- writeDistBuildHash ( workspacePackage , sourceHash ) ;
145- }
146- copied ++ ;
134+ restored . push ( workspacePackage ) ;
147135 }
148136
149- if ( experimentalCache && copied > 0 ) {
150- console . log ( `Restored ${ green ( copied ) } package(s) from cache into dist.` ) ;
137+ if ( restored . length ) {
138+ // dist now equals the cache — record the hash so the next build can
139+ // verify freshness by hashing dist alone.
140+ await Promise . all ( restored . map ( pkg => recordCacheHash ( pkg ) ) ) ;
141+ console . log ( `Restored ${ green ( restored . length ) } package(s) from cache into dist.` ) ;
151142 }
152143 } else {
153144 if ( useCache ) {
0 commit comments