@@ -12,6 +12,8 @@ import type {
12
12
import fs from 'graceful-fs' ;
13
13
import nativeFS from 'fs' ;
14
14
import ncp from 'ncp' ;
15
+ import path from 'path' ;
16
+ import { tmpdir } from 'os' ;
15
17
import { promisify } from 'util' ;
16
18
import { registerSerializableClass } from '@parcel/core' ;
17
19
import { hashFile } from '@parcel/utils' ;
@@ -222,11 +224,43 @@ try {
222
224
//
223
225
}
224
226
227
+ let useOsTmpDir ;
228
+ function shouldUseOsTmpDir ( filePath ) {
229
+ if ( useOsTmpDir != null ) {
230
+ return useOsTmpDir ;
231
+ }
232
+ try {
233
+ const tmpDir = tmpdir ( ) ;
234
+ nativeFS . accessSync (
235
+ tmpDir ,
236
+ nativeFS . constants . R_OK | nativeFS . constants . W_OK ,
237
+ ) ;
238
+ const tmpDirStats = nativeFS . statSync ( tmpDir ) ;
239
+ const filePathStats = nativeFS . statSync ( filePath ) ;
240
+ // Check the tmpdir is on the same partition as the target directory.
241
+ // This is required to ensure renaming is an atomic operation.
242
+ useOsTmpDir = tmpDirStats . dev === filePathStats . dev ;
243
+ } catch ( e ) {
244
+ // We don't have read/write access to the OS tmp directory
245
+ useOsTmpDir = false ;
246
+ }
247
+ return useOsTmpDir ;
248
+ }
249
+
225
250
// Generate a temporary file path used for atomic writing of files.
226
251
function getTempFilePath ( filePath : FilePath ) {
227
252
writeStreamCalls = writeStreamCalls % Number . MAX_SAFE_INTEGER ;
253
+
254
+ let tmpFilePath = filePath ;
255
+
256
+ // If possible, write the tmp file to the OS tmp directory
257
+ // This reduces the amount of FS events the watcher needs to process during the build
258
+ if ( shouldUseOsTmpDir ( filePath ) ) {
259
+ tmpFilePath = path . join ( tmpdir ( ) , path . basename ( filePath ) ) ;
260
+ }
261
+
228
262
return (
229
- filePath +
263
+ tmpFilePath +
230
264
'.' +
231
265
process . pid +
232
266
( threadId != null ? '.' + threadId : '' ) +
0 commit comments