Skip to content

Migrate to Electron 42 and modernize tooling#1

Merged
jgcoded merged 2 commits into
mainfrom
electron-42-migration
May 15, 2026
Merged

Migrate to Electron 42 and modernize tooling#1
jgcoded merged 2 commits into
mainfrom
electron-42-migration

Conversation

@jgcoded
Copy link
Copy Markdown
Owner

@jgcoded jgcoded commented May 15, 2026

  • Electron 23 -> 42; electron-builder 23 -> 26; electron-updater 5 -> 6; electron-debug 3 -> 4; @electron/notarize 1 -> 3; @electron/rebuild 3 -> 4
  • Webpack stack: webpack-dev-server 4 -> 5; css-loader 6 -> 7; sass-loader 13 -> 16; @svgr/webpack 6 -> 8; css-minimizer 4 -> 7
  • TypeScript 4.9 -> 5.7; prettier 2 -> 3; rimraf 4 -> 5

Add src/main/bootstrap.cjs so ts-node fires in dev. Electron 28+ loads package.json::main via dynamic import(), which bypasses ts-node's CJS require hook. The .cjs bootstrap registers ts-node and tsconfig-paths, then requires main.ts.

Replace AppWindow's 0x0-size init guard with an explicit initialSetupDone flag. Chromium 148 clamps BrowserWindow({width:0, height:0}) to a non-zero minimum, so the old "size === 0" check never fired and the window stayed clamped after startup.

Switch electron-debug to ESM-default import (v4 is pure ESM) and open DevTools in a detached window.

Bundle VideoService.exe into packaged builds via extraResources so it lands under process.resourcesPath.

Set package.json "type": "commonjs" to disable Node 22's ESM auto-detection of typeless files. Migrate notarize.js to @electron/notarize v3 API (drop appBundleId, require teamId), rimraf scripts to v5 named rimrafSync export, and Sass map-get to the module-scoped map.get.

Add CLAUDE.md and a jest setup that stubs window.electron so the existing App.test.tsx mounts cleanly inside jsdom.

- Electron 23 -> 42; electron-builder 23 -> 26; electron-updater 5 -> 6;
  electron-debug 3 -> 4; @electron/notarize 1 -> 3; @electron/rebuild 3 -> 4
- Webpack stack: webpack-dev-server 4 -> 5; css-loader 6 -> 7;
  sass-loader 13 -> 16; @svgr/webpack 6 -> 8; css-minimizer 4 -> 7
- TypeScript 4.9 -> 5.7; prettier 2 -> 3; rimraf 4 -> 5

Add src/main/bootstrap.cjs so ts-node fires in dev. Electron 28+ loads
package.json::main via dynamic import(), which bypasses ts-node's CJS
require hook. The .cjs bootstrap registers ts-node and tsconfig-paths,
then requires main.ts.

Replace AppWindow's 0x0-size init guard with an explicit
initialSetupDone flag. Chromium 148 clamps BrowserWindow({width:0,
height:0}) to a non-zero minimum, so the old "size === 0" check never
fired and the window stayed clamped after startup.

Switch electron-debug to ESM-default import (v4 is pure ESM) and open
DevTools in a detached window.

Bundle VideoService.exe into packaged builds via extraResources so it
lands under process.resourcesPath.

Set package.json "type": "commonjs" to disable Node 22's ESM
auto-detection of typeless files. Migrate notarize.js to @electron/notarize
v3 API (drop appBundleId, require teamId), rimraf scripts to v5 named
rimrafSync export, and Sass map-get to the module-scoped map.get.

Add CLAUDE.md and a jest setup that stubs window.electron so the
existing App.test.tsx mounts cleanly inside jsdom.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR is a broad tooling and dependency modernization. It bumps Electron from 23 to 42 and updates the surrounding webpack/test/lint/prettier stack, then applies the minimum source/config changes needed to keep the app booting, packaging, and testing under the new versions. It also adds a jsdom Jest setup so the existing renderer smoke test mounts, and bundles VideoService.exe into packaged builds.

Changes:

  • Major version bumps across Electron, electron-builder/updater/debug/rebuild/notarize, the webpack/css/sass/svgr stack, TypeScript 5.7, prettier 3, and rimraf 5, with corresponding API migrations (named rimrafSync, @electron/notarize v3 teamId, Sass map.get, ESM-default electron-debug).
  • New src/main/bootstrap.cjs plus "type": "commonjs" and main pointing at the bootstrap so ts-node hooks fire under Electron 28+'s dynamic-import main loader; start:main no longer pre-registers ts-node on the CLI.
  • AppWindow.updateSize switched from a 0x0-size guard (broken by Chromium 148 clamping) to an explicit initialSetupDone static flag; large prettier reformat (trailing commas, quotes, brace style) across renderer/main TS, plus rewrite of VideoPreviewPanel.tsx; new CLAUDE.md, .erb/scripts/jest.setup.ts stubbing window.electron, and extraResources entry for VideoService.exe.

Reviewed changes

Copilot reviewed 21 out of 23 changed files in this pull request and generated no comments.

Show a summary per file
File Description
package.json Dependency bumps; switch main to bootstrap.cjs, add "type": "commonjs", register jest setup file, add VideoService.exe to extraResources, replace devEngines with engines.
src/main/bootstrap.cjs New CJS entrypoint that registers ts-node + tsconfig-paths then loads main.ts.
src/main/main.ts Use ESM-default electron-debug import with { devToolsMode: 'detach' }; prettier reformat.
src/main/RecordingChildProcess.ts Prettier reformat; add no-console eslint disable for the debug log.
src/main/preload.ts Prettier trailing-comma reformat.
src/renderer/ipc/AppWindow.ts Replace 0×0-size init guard with initialSetupDone flag; reformat.
src/renderer/ipc/RecordingService.ts, HotKeyService.ts Prettier trailing-comma reformat.
src/renderer/components/app/App.tsx Prettier reformat (trailing commas only).
src/renderer/components/settingspanel/SettingsPanel.tsx Prettier reformat.
src/renderer/components/videopreviewpanel/VideoPreviewPanel.tsx Reformat + small refactor (destructuring, functional setState, type="button", jsx-a11y media disable comment); import ordering.
src/renderer/components/_Common.scss Switch from deprecated map-get to sass:map's map.get; remove stray double semicolon.
src/common/IpcApi.ts, TelemetryService.ts Prettier trailing-comma reformat.
src/tests/App.test.tsx Fix import path to the actual renderer/components/app/App.
.erb/scripts/jest.setup.ts New Jest setup stubbing window.electron IPC surface and navigator.mediaDevices for jsdom.
.erb/scripts/notarize.js Migrate to @electron/notarize v3: drop appBundleId, require APPLE_TEAM_ID.
.erb/scripts/clean.js, delete-source-maps.js Migrate to rimraf v5 named rimrafSync (with { glob: true } where globs are used).
.eslintignore Ignore the entire .erb/ directory and .eslintrc.js; drops prior opt-in linting of .erb.
CLAUDE.md New contributor guide for Claude Code with project context, commands, and architecture notes.
release/app/package-lock.json Rename lockfile root from electron-react-boilerplate to desktop-recorder.
Files not reviewed (1)
  • release/app/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- .erb/scripts/notarize.js: defer @electron/notarize load to dynamic
  import inside the darwin-only branch. v3 is pure ESM and the top-level
  require() failed at module load on every platform, even though the
  hook is gated to macOS.
- tsconfig.json: add skipLibCheck. react-inlinesvg v4's index.d.ts uses
  both `export =` and named exports which tsc rejects; standard fix is
  to skip type-checking third-party declaration files.
- .github/workflows/{test,publish}.yml: bump Node 16 -> 22 (engines now
  requires >=20) and actions/{checkout,setup-node}@V3 -> v4. Add
  APPLE_TEAM_ID to publish env (@electron/notarize v3 requires it).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jgcoded jgcoded merged commit 2818c3b into main May 15, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants