Skip to content

Commit 7e3505b

Browse files
Akryumnklayman
authored andcommitted
feat(serve): use chokidar to be able to watch folders (#247)
* feat: use chokidar to be able to watch folders * fix: prevent multiple restart at the same time * test: fix commands spec * fix(serve): main process not rebuilt if changed during build
1 parent 0a27e22 commit 7e3505b

File tree

4 files changed

+73
-21
lines changed

4 files changed

+73
-21
lines changed

__tests__/commands.spec.js

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const execa = require('execa')
99
const portfinder = require('portfinder')
1010
const Application = require('spectron').Application
1111
const { chainWebpack, getExternals } = require('../lib/webpackConfig')
12+
const chokidar = require('chokidar')
1213
// #endregion
1314

1415
// #region Mocks
@@ -26,6 +27,7 @@ jest.mock('electron-builder/out/cli/install-app-deps.js', () => ({
2627
installAppDeps: mockInstallAppDeps
2728
}))
2829
jest.mock('../lib/webpackConfig.js')
30+
jest.mock('chokidar')
2931
const mockPipe = jest.fn()
3032
const childEvents = {}
3133
const mockExeca = {
@@ -66,6 +68,11 @@ console.log = jest.fn()
6668
beforeEach(() => {
6769
jest.clearAllMocks()
6870
})
71+
chokidar.watch.mockImplementation((file) => {
72+
return {
73+
on: (type, cb) => {}
74+
}
75+
})
6976
// #endregion
7077

7178
// #region runCommand
@@ -449,9 +456,13 @@ describe('electron:serve', () => {
449456

450457
test('Custom launch arguments is used if provided', async () => {
451458
let watchCb
452-
fs.watchFile.mockImplementation((file, cb) => {
453-
// Set callback to be called later
454-
watchCb = cb
459+
chokidar.watch.mockImplementation((file) => {
460+
return {
461+
on: (type, cb) => {
462+
// Set callback to be called later
463+
watchCb = cb
464+
}
465+
}
455466
})
456467
await runCommand('electron:serve', {
457468
pluginOptions: {
@@ -514,9 +525,13 @@ describe('electron:serve', () => {
514525
// So we can make sure it wasn't called
515526
jest.spyOn(process, 'exit')
516527
let watchCb
517-
fs.watchFile.mockImplementation((file, cb) => {
518-
// Set callback to be called later
519-
watchCb = cb
528+
chokidar.watch.mockImplementation((file) => {
529+
return {
530+
on: (type, cb) => {
531+
// Set callback to be called later
532+
watchCb = cb
533+
}
534+
}
520535
})
521536
await runCommand('electron:serve', {
522537
pluginOptions: {
@@ -528,7 +543,7 @@ describe('electron:serve', () => {
528543
})
529544

530545
// Proper file is watched
531-
expect(fs.watchFile.mock.calls[0][0]).toBe('projectPath/customBackground')
546+
expect(chokidar.watch.mock.calls[0][0]).toBe('projectPath/customBackground')
532547
// Child has not yet been killed or unwatched
533548
expect(mockExeca.send).not.toBeCalled()
534549
expect(mockExeca.kill).not.toBeCalled()
@@ -560,9 +575,13 @@ describe('electron:serve', () => {
560575
// So we can make sure it wasn't called
561576
jest.spyOn(process, 'exit')
562577
let watchCb = {}
563-
fs.watchFile.mockImplementation((file, cb) => {
564-
// Set callback to be called later
565-
watchCb[file] = cb
578+
chokidar.watch.mockImplementation((file) => {
579+
return {
580+
on: (type, cb) => {
581+
// Set callback to be called later
582+
watchCb[file] = cb
583+
}
584+
}
566585
})
567586
await runCommand('electron:serve', {
568587
pluginOptions: {
@@ -576,8 +595,8 @@ describe('electron:serve', () => {
576595
})
577596

578597
// Proper file is watched
579-
expect(fs.watchFile.mock.calls[0][0]).toBe('projectPath/customBackground')
580-
expect(fs.watchFile.mock.calls[1][0]).toBe('projectPath/listFile')
598+
expect(chokidar.watch.mock.calls[0][0]).toBe('projectPath/customBackground')
599+
expect(chokidar.watch.mock.calls[1][0]).toBe('projectPath/listFile')
581600
// Child has not yet been killed or unwatched
582601
expect(mockExeca.send).not.toBeCalled()
583602
expect(mockExeca.kill).not.toBeCalled()

index.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ module.exports = (api, options) => {
298298
}
299299
}
300300

301+
// Prevent multiple restarts at the same time
302+
let queuedBuilds = 0
301303
// Electron process
302304
let child
303305
// Auto restart flag
@@ -328,8 +330,11 @@ module.exports = (api, options) => {
328330
// Initial start of Electron
329331
startElectron()
330332
// Restart on main process file change
333+
const chokidar = require('chokidar')
331334
mainProcessWatch.forEach(file => {
332-
fs.watchFile(api.resolve(file), () => {
335+
chokidar.watch(api.resolve(file)).on('all', () => {
336+
queuedBuilds++
337+
333338
if (args.debug) {
334339
// Rebuild main process
335340
startElectron()
@@ -342,8 +347,10 @@ module.exports = (api, options) => {
342347

343348
// Set auto restart flag
344349
childRestartOnExit = 1
345-
346-
killElectron()
350+
if (child) {
351+
// Start Electron if it hasn't been already launched
352+
startElectron()
353+
}
347354
})
348355
})
349356

@@ -375,6 +382,12 @@ module.exports = (api, options) => {
375382
}
376383

377384
function launchElectron () {
385+
// Kill existing instances
386+
killElectron()
387+
// Don't launch if a new background file is being bundled
388+
queuedBuilds--
389+
if (queuedBuilds > 0) return
390+
378391
if (args.debug) {
379392
// Do not launch electron and provide instructions on launching through debugger
380393
info(
@@ -404,9 +417,6 @@ module.exports = (api, options) => {
404417
info('Launching Electron...')
405418
}
406419

407-
// Disable Electron process auto restart
408-
childRestartOnExit = 0
409-
410420
let stdioConfig = [null, null, null]
411421

412422
// Use an IPC on Windows for graceful exit
@@ -448,15 +458,18 @@ module.exports = (api, options) => {
448458
}
449459

450460
child.on('exit', () => {
451-
child = null
461+
if (child.killed) {
462+
child = null
463+
}
452464

453465
if (childExitTimeout) {
454466
clearTimeout(childExitTimeout)
455467
childExitTimeout = null
456468
}
457469

458470
if (childRestartOnExit > 0) {
459-
startElectron()
471+
// Disable Electron process auto restart
472+
childRestartOnExit = 0
460473
} else {
461474
process.exit(0)
462475
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"license": "MIT",
2929
"private": false,
3030
"dependencies": {
31+
"chokidar": "^2.1.5",
3132
"electron-builder": "^20.29.0",
3233
"execa": "^1.0.0",
3334
"friendly-errors-webpack-plugin": "^1.7.0",

yarn.lock

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4096,6 +4096,25 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4, chokidar@^2.
40964096
optionalDependencies:
40974097
fsevents "^1.2.7"
40984098

4099+
chokidar@^2.1.5:
4100+
version "2.1.5"
4101+
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.5.tgz#0ae8434d962281a5f56c72869e79cb6d9d86ad4d"
4102+
integrity sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==
4103+
dependencies:
4104+
anymatch "^2.0.0"
4105+
async-each "^1.0.1"
4106+
braces "^2.3.2"
4107+
glob-parent "^3.1.0"
4108+
inherits "^2.0.3"
4109+
is-binary-path "^1.0.0"
4110+
is-glob "^4.0.0"
4111+
normalize-path "^3.0.0"
4112+
path-is-absolute "^1.0.0"
4113+
readdirp "^2.2.1"
4114+
upath "^1.1.1"
4115+
optionalDependencies:
4116+
fsevents "^1.2.7"
4117+
40994118
chownr@^1.0.1, chownr@^1.1.1:
41004119
version "1.1.1"
41014120
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
@@ -14255,7 +14274,7 @@ unzip-response@^2.0.1:
1425514274
resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
1425614275
integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=
1425714276

14258-
upath@^1.1.0:
14277+
upath@^1.1.0, upath@^1.1.1:
1425914278
version "1.1.2"
1426014279
resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068"
1426114280
integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==

0 commit comments

Comments
 (0)