Skip to content

v5

Core Changes

  1. Full TypeScript Rewrite: All APIs now have complete type definitions.
  2. Dual Module Format Output: Both CJS and ESM formats are supported.
  3. Node.js Version Upgrade: Minimum requirement is Node.js >= 20.19.0.
  4. Pino Logging System: More powerful logging capabilities.
  5. Bundle Registry Mechanism: Faster startup.
  6. Async Controller Loading: Supports ESM dynamic imports, avoiding sync/async concurrency race conditions.
  7. Main Process Bundling: Main process code can be bundled like frontend bundles.
  8. Build Registry Plugin: Replicates runtime property name mapping logic.
  9. Comprehensive Build Configuration Enhancement: Added numerous fine-grained control options.
  10. Post-Build Independent Transpilation: Independently transpiles files that cannot be bundled.
  11. Encryption System Upgrade: More secure.
  12. Atomic Resource Move: Prevents data loss.
  13. ee-bin Full Upgrade: Added complete TypeScript type system.
  14. EventBus Event Isolation: Lifecycle event optimization.
  15. ESM-Compatible Config Loading: Auto-unwraps __esModule format, supports function/class exports.
  16. Controller Concurrency Safety: Explicitly guarantees no state pollution between concurrent requests.
  17. Cross Inter-Process Improvements: Optimized.

I. Core Architecture Changes

1. Full TypeScript Rewrite

In v4, ee-core and ee-bin were written entirely in JavaScript (.js). Type definitions were only auto-generated via tsconfig.json with emitDeclarationOnly + allowJs to produce .d.ts files — the source code itself had no type constraints.

v5 performs a full TypeScript rewrite of both core packages. All source files are .ts, with extremely strict compilation settings.

Impact:

  • All APIs have complete type definitions; IDE intelligent hints are significantly improved
  • Compile-time catches implicit any, unchecked index access, optional property misuse, and other common errors
  • ESM source code import must include .js extension (NodeNext specification)

2. Dual Module Format Output (CJS + ESM)

v4 only outputs CommonJS (require('ee-core')). v5 outputs both CJS and ESM formats:

dist/cjs/   → CommonJS (module: CommonJS)
dist/esm/   → ESM      (module: NodeNext)

The exports field in package.json provides conditional exports for each subpath:

json
{
  "./app": {
    "import": "./dist/esm/app/index.js",
    "require": "./dist/cjs/app/index.js"
  }
}

Impact:

  • Developers can directly import { ElectronEgg } from 'ee-core' in ESM projects
  • CJS projects continue to use const { ElectronEgg } = require('ee-core')
  • The exports mapping of ee-core is auto-generated by scripts/gen-exports.js. After adding new subpath modules, run npm run gen-exports to update — no manual editing needed

3. Node.js Version Requirement Upgrade

v5 requires Node.js >= 20.19.0.


II. ee-core Feature Updates

4. Logging System: Pino Replaces egg-logger

v4 uses egg-logger (EggLoggers). Log files append -YYYYMMDD suffixes by day, with lazy initialization via Object.defineProperty.

v5 fully switches to the Pino logging system:

Featurev4 (egg-logger)v5 (Pino)
Logging libraryegg-loggerpino + pino-roll + pino-pretty
Rotation policyAppend suffix by daypino-roll: rotate by day/hour
Dev outputCustom formatpino-pretty: configurable color, depth, timestamp
TimezoneFixed UTCIANA timezone support (e.g. Asia/Shanghai)
Log redactionNonePino redaction (field masking)
Custom levelsFixedConfigurable custom levels
Call styleStandard method callProxy wrapper: supports {obj, msg}, printf ('count: %d', 42), concatenation ('msg:', val) styles
Safe modeNoneSafe mode prevents serialization crashes

Impact:

  • Log configuration migrates from config.logger egg-logger format to pino format
  • coreLogger, logger, errorLogger three instances remain, but the underlying implementation is completely different
  • Developers need to update custom log configuration

5. Bundle Mode: Registry Mechanism

This is v5's most critical architectural addition. v4 loads controllers and configs at runtime via globby filesystem scanning, and bundled apps also depend on filesystem paths.

Impact:

  • After bundling, all controllers and configs are registered to global variables, no filesystem scanning needed, faster startup
  • Lazy getters avoid initialization order issues — controllers do not execute at the registration phase
  • Dev mode (unbundled) automatically falls back to filesystem scanning, consistent with v4 behavior
  • process.env.EE_BUNDLED = "true" identifies bundle mode

6. Async Controller Loading

v4's ControllerLoader only supports synchronous require() loading. v5 adds an async loading path:

  • Application.runAsync()loadControllerAsync()FileLoader.parseAsync()import() dynamic loading
  • Loading process has a loading flag to prevent sync/async concurrency race conditions

Impact:

  • ESM projects can use runAsync() to ensure async modules load correctly
  • In async loading mode, controller files can be in ESM format

7. IPC Dual Model

v5 explicitly defines the IPC Dual Model:

ModelRenderer CallMain Process RegistrationCharacteristics
send/onwebContents.send / ipcRenderer.sendipcMain.onSync, event.returnValue + event.reply
invoke/handleipcRenderer.invokeipcMain.handleAsync, Promise return value, recommended

Error propagation adds {__EE_ERROR__: true, message} structured marker.

8. HTTP Service: Koa Middleware Chain Standardization

v5 explicitly orders the middleware chain:

errorHandler → preMiddleware → CORS → koa-body → dispatch → postMiddleware

A new koaConfig configuration section is added; developers can independently configure preMiddleware and postMiddleware arrays.

9. Child Process Config Passing: argv Replaces Filesystem

v5 passes eeConfig via process.argv[2] (JSON stringified and injected by JobProcess). Inside the child process, setConfig() parses and caches it — no filesystem read needed.

Impact:

  • child_process.fork() scenarios in bundled apps are more reliable
  • Child processes no longer depend on config file paths

10. Port Allocation: Dual-Level Lock Mechanism

v5 introduces an old + young dual-level lock set (15-second rotation) to prevent concurrent processes from grabbing the same port.

It also checks all local network interfaces to avoid assigning already-occupied ports.

11. systemSleep: True Sync Blocking

v5 adds the systemSleep(ms) utility function, using Atomics.wait + SharedArrayBuffer for true synchronous blocking (no CPU occupation), with a busy-wait fallback.

12. Zero lodash Dependency

v5 completely removes the following npm dependencies, replacing them with lightweight in-house implementations:

v4 Dependencyv5 ReplacementLocation
lodash.mergeextend.ts (in-house deep merge)ee-core, ee-bin shared
chalkANSI escape code lightweight implementationee-bin lib/helpers.ts
is-type-ofis.function() / is.class()ee-bin lib/helpers.ts
fs-extracopyDirSync() in-house implementationee-bin lib/helpers.ts
debugcreateDebug() environment-drivenee-bin lib/helpers.ts
egg-loggerpino systemee-core log/
adm-zipcompressingee-bin incrUpdater

Impact:

  • Package size and security risks significantly reduced

III. ee-bin Feature Updates

13. Build Registry Plugin (Core Addition)

v4's ee-bin has no esbuild plugin mechanism. Controllers and config files are directly bundled into main.js (or copied verbatim in copy mode).

v5 adds bundle_registry_plugin.ts, a key component of v5's bundling architecture:

  • Virtual module app:controller-registry: scans the controller directory and generates a registry
  • Virtual module app:config-registry: scans the config directory and generates a registry
  • Virtual module app:bundle-entry: entry point that loads registries + main.js in sequence

The computeProperties() function replicates ee-core's defaultCamelize(caseStyle: 'lower') logic, ensuring build-time and runtime property name mapping consistency.

14. Comprehensive Build Configuration Enhancement

v5's build.electron (BundleConfig type) adds numerous fine-grained control options:

Config Itemv4v5Description
externalNoneUser-defined external packages
sourcemapfalse (fixed)false → auto logicdev→inline, prod→off; can explicitly set inline/external
minifyNoneProduction minification
dropNoneRemove console/debugger
keepNamesNonePreserve function/class names during minification
legalCommentsNoneinline/eof/none
defineNoneCompile-time constant injection
copyNoneExtra file/directory copying
formatNonecjs/esm; default cjs
Framework externalsNo explicit listee-core, ee-bin, electron, better-sqlite3, proxy-agent, pino-roll, pino-pretty

Impact:

  • Production builds can finely control sourcemap, minification, constant injection, etc.
  • sourcemap: false is no longer "always off", but "auto-decide by environment"
  • format: 'esm' mode requires all business code (controllers, services, configs) to be ESM-compatible

15. Post-Build Processing: Independent File Transpilation

v5's bundle mode, after bundling, performs independent esbuild transpilation on files that cannot be bundled (preload/bridge.js, jobs/ directory, user copy config items):

  • Script files (.js/.ts) are compiled with bundle: false into Node-loadable CJS .js, preserving runtime require() calls
  • Non-script files are copied verbatim
  • All transpilation uses _resolveBaseBuildOptions() shared settings, ensuring format consistency with the main bundle

Impact:

  • preload/bridge.js and jobs/ files work correctly in bundled environments
  • No need to manually handle child_process.fork() path issues

16. Encryption System Upgrade


Featurev4v5
entryFilesNoneEntry files (e.g. main.js) compiled to .jsc then overwritten .js as bytenode loader shell
bytecodeOptionsFixed electron: trueConfigurable bytenode compile parameters
Safety checkNoneVerifies .jsc exists after compilation before deleting .js; throws error and preserves source file if not
silent modeNoneHides javascript-obfuscator Pro ad output
cleanFilesNoneSpecifies encryption artifacts to clean
encryptDirNoneCustom encryption output directory

17. Resource Move: Atomic Operation

v5's move.ts switches to atomic operation:

Backup target → .bak → Copy source to target → Delete backup

On copy failure, restores .bak to prevent data loss.

18. Other ee-bin Changes

Itemv4v5
esbuild0.21.50.28
commander11.0.014
Compression libadm-zipcompressing
Test frameworkNoneVitest (coverage 90%/85%)
pargv.jsminimist-style parserRetained but refactored to TS
TypeScript typesNoneComplete BinConfig type system
Config loading.js/.cjs/.ts/.json/.json5Same + ESM default export unwrapping + function/class config factories

IV. General Changes

19. EventBus Improvements

v5's EventBus separates lifecycle events and custom events into two independent internal Maps:

  • Lifecycle events (register/emitLifecycle): duplicate registration overwrites with warning, async errors re-thrown
  • Custom events (on/emit): async errors caught and logged, no flow interruption

v4's EventBus uses the same mechanism for both event types, with no overwrite warnings.

20. ESM-Compatible Config Loading

v5's loadFile() / loadFileAsync() adds ESM compatibility:

  • Auto-unwraps {__esModule: true, default: fn} format
  • Auto-calls config files exporting functions (passing appInfo)
  • Directly uses config files exporting classes (no call)
  • Async version uses import() for loading

21. Controller Concurrency Safety

v5 explicitly states: each middleware call creates a new controller instance, ensuring no state pollution between concurrent requests. The type system also reinforces this constraint in ControllerLoader.

22. Cross Inter-Process Management Improvements

v5's Cross class adds at run():

  • Dynamic port allocation (dual-level lock mechanism)
  • Duplicate service names auto-append pid suffix to avoid conflicts

V. Migration Notes

Must Adjust

  1. Node.js version: Ensure >= 20.19.0
  2. Log configuration: Migrate from egg-logger format to pino format (pino-roll rotation, pino-pretty output, etc.)
  3. ESM import extension: import in ee-core source code must include .js (NodeNext specification)
  1. Build configuration: Use the new minify, drop, define, sourcemap auto logic etc. to improve production bundle quality
  2. Encryption configuration: New entryFiles, bytecodeOptions, silent etc. options allow finer encryption control
  3. Async controllers: ESM projects should use runAsync() + loadControllerAsync()

No Adjustment Needed

  • Dev mode controller/config loading falls back to filesystem scanning, consistent with v4 behavior
  • ElectronEgg entry class, Application singleton, startup flow sequence unchanged
  • Three-channel communication (Socket.IO, HTTP, IPC) architecture unchanged
  • Child process (ChildJob, ChildPoolJob) API unchanged
  • SqliteStorage API unchanged