直接跳到内容

Electron Node

Electron Node 是 Electron 框架的核心特性之一,它将 Node.js 运行时与 Chromium 渲染引擎深度集成,为桌面应用程序提供了完整的全栈 JavaScript 开发能力。这种独特的架构允许开发者在渲染进程和主进程中同时使用 Node.js API,打破了传统 Web 应用在浏览器环境中的限制。

Node 集成架构

Electron 的 Node 集成采用分层架构设计,将 Node.js 运行时与 Chromium 渲染进程巧妙结合:

Electron 应用运行时环境
     |
     +-- 主进程 (Main Process)
     |     |
     |     +-- 完整的 Node.js 运行时
     |     |     |
     |     |     +-- 文件系统访问
     |     |     +-- 网络操作
     |     |     +-- 原生模块支持
     |     |
     |     +-- Chromium 窗口管理
     |
     +-- 渲染进程 (Renderer Processes)
           |
           +-- Chromium 渲染引擎
           |     |
           |     +-- HTML/CSS/JavaScript 渲染
           |     +-- Web API 支持
           |
           +-- Node.js 运行时 (可选集成)
                 |
                 +-- 通过预加载脚本安全访问
                 +-- 上下文隔离保护

主进程中的 Node.js

完整的 Node.js 环境

Electron 主进程运行在完整的 Node.js 环境中,可以直接使用所有 Node.js 内置模块和第三方包:

javascript
// main.js
import { app, BrowserWindow } from 'electron';
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
import os from 'os';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

class FileSystemManager {
  constructor() {
    this.userDataPath = app.getPath('userData');
    this.tempPath = os.tmpdir();
  }

  // 读取应用数据文件
  async readAppData(filename) {
    const filePath = path.join(this.userDataPath, filename);
    try {
      const data = await fs.readFile(filePath, 'utf-8');
      return JSON.parse(data);
    } catch (error) {
      if (error.code === 'ENOENT') {
        return null; // 文件不存在
      }
      throw error;
    }
  }

  // 写入应用数据
  async writeAppData(filename, data) {
    const filePath = path.join(this.userDataPath, filename);
    const dir = path.dirname(filePath);
    
    // 确保目录存在
    await fs.mkdir(dir, { recursive: true });
    
    // 写入文件
    await fs.writeFile(filePath, JSON.stringify(data, null, 2));
  }

  // 监控文件变化
  watchFile(filePath, callback) {
    const fs = require('fs'); // 使用 CommonJS 模块进行文件监控
    return fs.watch(filePath, { persistent: false }, callback);
  }
}

class NetworkManager {
  constructor() {
    this.net = require('net'); // TCP 网络
    this.dgram = require('dgram'); // UDP 网络
    this.http = require('http'); // HTTP 服务器
    this.https = require('https'); // HTTPS 服务器
  }

  // 创建 HTTP 服务器
  createHttpServer(port, requestHandler) {
    const server = this.http.createServer(requestHandler);
    
    server.listen(port, () => {
      console.log(`HTTP 服务器运行在端口 ${port}`);
    });
    
    return server;
  }

  // 创建 TCP 服务器
  createTcpServer(port, connectionHandler) {
    const server = this.net.createServer(connectionHandler);
    
    server.listen(port, () => {
      console.log(`TCP 服务器运行在端口 ${port}`);
    });
    
    return server;
  }

  // 检查网络连接
  async checkConnectivity(host, port) {
    return new Promise((resolve) => {
      const socket = this.net.createConnection(port, host);
      
      socket.setTimeout(5000);
      
      socket.on('connect', () => {
        socket.destroy();
        resolve(true);
      });
      
      socket.on('timeout', () => {
        socket.destroy();
        resolve(false);
      });
      
      socket.on('error', () => {
        resolve(false);
      });
    });
  }
}

进程管理与系统集成

主进程可以利用 Node.js 的进程管理能力实现复杂的系统集成:

javascript
// main.js
import { app, ipcMain } from 'electron';
import { spawn, exec } from 'child_process';
import { EventEmitter } from 'events';

class SystemIntegration extends EventEmitter {
  constructor() {
    super();
    this.childProcesses = new Map();
    this.setupProcessManagement();
  }

  setupProcessManagement() {
    // 处理外部进程执行请求
    ipcMain.handle('process:execute', async (event, command, args = []) => {
      return this.executeCommand(command, args);
    });

    // 处理长时间运行的进程
    ipcMain.handle('process:spawn', async (event, command, args = [], options = {}) => {
      return this.spawnProcess(command, args, options);
    });

    // 终止进程
    ipcMain.handle('process:kill', async (event, pid) => {
      return this.killProcess(pid);
    });
  }

  // 执行命令并返回结果
  async executeCommand(command, args = []) {
    return new Promise((resolve, reject) => {
      exec(`${command} ${args.join(' ')}`, (error, stdout, stderr) => {
        if (error) {
          reject({ success: false, error: error.message });
        } else {
          resolve({ 
            success: true, 
            stdout: stdout.toString(), 
            stderr: stderr.toString() 
          });
        }
      });
    });
  }

  // 生成子进程
  spawnProcess(command, args = [], options = {}) {
    const child = spawn(command, args, {
      stdio: ['pipe', 'pipe', 'pipe'],
      ...options
    });

    const processId = Date.now().toString();
    
    this.childProcesses.set(processId, {
      process: child,
      command,
      args,
      startTime: new Date()
    });

    // 收集输出
    let stdout = '';
    let stderr = '';

    child.stdout.on('data', (data) => {
      stdout += data.toString();
      this.emit('process:output', { pid: processId, type: 'stdout', data: data.toString() });
    });

    child.stderr.on('data', (data) => {
      stderr += data.toString();
      this.emit('process:output', { pid: processId, type: 'stderr', data: data.toString() });
    });

    child.on('close', (code) => {
      this.childProcesses.delete(processId);
      this.emit('process:exit', { pid: processId, code, stdout, stderr });
    });

    child.on('error', (error) => {
      this.childProcesses.delete(processId);
      this.emit('process:error', { pid: processId, error: error.message });
    });

    return { pid: processId, process: child };
  }

  // 终止进程
  killProcess(pid) {
    const processInfo = this.childProcesses.get(pid);
    if (processInfo) {
      processInfo.process.kill();
      this.childProcesses.delete(pid);
      return { success: true };
    }
    return { success: false, error: '进程不存在' };
  }

  // 获取系统信息
  getSystemInfo() {
    const os = require('os');
    
    return {
      platform: process.platform,
      arch: process.arch,
      nodeVersion: process.version,
      electronVersion: process.versions.electron,
      chromeVersion: process.versions.chrome,
      memory: process.memoryUsage(),
      system: {
        totalMemory: os.totalmem(),
        freeMemory: os.freemem(),
        cpus: os.cpus().length,
        uptime: os.uptime()
      }
    };
  }
}

渲染进程中的 Node 集成

安全的 Node.js 访问

通过预加载脚本和上下文隔离,安全地在渲染进程中暴露 Node.js 功能:

javascript
// preload.js
import { contextBridge, ipcRenderer } from 'electron';
import { crypto } from 'crypto';

// 安全地暴露 Node.js API 子集
contextBridge.exposeInMainWorld('nodeAPI', {
  // 加密功能
  crypto: {
    createHash: (algorithm, data) => {
      const hash = crypto.createHash(algorithm);
      hash.update(data);
      return hash.digest('hex');
    },
    
    randomBytes: (size) => {
      return crypto.randomBytes(size).toString('hex');
    }
  },

  // 工具函数
  utils: {
    getPlatform: () => process.platform,
    getVersions: () => ({
      node: process.versions.node,
      electron: process.versions.electron
    })
  },

  // 文件系统操作(通过 IPC)
  fs: {
    readFile: (filePath) => ipcRenderer.invoke('fs:readFile', filePath),
    writeFile: (filePath, content) => ipcRenderer.invoke('fs:writeFile', filePath, content),
    readDir: (dirPath) => ipcRenderer.invoke('fs:readDir', dirPath)
  },

  // 进程管理
  process: {
    execute: (command, args) => ipcRenderer.invoke('process:execute', command, args),
    getSystemInfo: () => ipcRenderer.invoke('process:getSystemInfo')
  }
});

在渲染进程中使用 Node.js 功能

javascript
// renderer.js
class NodeIntegrationExample {
  constructor() {
    this.setupEventListeners();
    this.loadSystemInfo();
  }

  async setupEventListeners() {
    // 文件操作示例
    document.getElementById('readFileBtn').addEventListener('click', () => {
      this.readFileExample();
    });

    // 加密操作示例
    document.getElementById('hashBtn').addEventListener('click', () => {
      this.hashExample();
    });

    // 系统命令示例
    document.getElementById('systemCmdBtn').addEventListener('click', () => {
      this.systemCommandExample();
    });
  }

  async readFileExample() {
    try {
      const content = await window.nodeAPI.fs.readFile('/path/to/file.txt');
      document.getElementById('fileContent').textContent = content;
    } catch (error) {
      console.error('读取文件失败:', error);
    }
  }

  async hashExample() {
    const data = document.getElementById('hashInput').value;
    const hash = window.nodeAPI.crypto.createHash('sha256', data);
    document.getElementById('hashResult').textContent = hash;
  }

  async systemCommandExample() {
    try {
      const result = await window.nodeAPI.process.execute('ls', ['-la']);
      if (result.success) {
        document.getElementById('cmdOutput').textContent = result.stdout;
      } else {
        document.getElementById('cmdOutput').textContent = '命令执行失败';
      }
    } catch (error) {
      console.error('执行命令失败:', error);
    }
  }

  async loadSystemInfo() {
    const info = await window.nodeAPI.process.getSystemInfo();
    this.displaySystemInfo(info);
  }

  displaySystemInfo(info) {
    const infoDiv = document.getElementById('systemInfo');
    infoDiv.innerHTML = `
      <h3>系统信息</h3>
      <p>平台: ${info.platform}</p>
      <p>架构: ${info.arch}</p>
      <p>Node.js 版本: ${info.nodeVersion}</p>
      <p>内存使用: ${Math.round(info.memory.heapUsed / 1024 / 1024)}MB</p>
    `;
  }
}

// 初始化应用
new NodeIntegrationExample();

原生模块集成

使用 Node.js 原生模块

Electron 支持使用 Node.js 原生模块,但需要注意与 Electron 版本的兼容性:

javascript
// main.js
import { app } from 'electron';

class NativeModuleManager {
  constructor() {
    this.nativeModules = new Map();
    this.loadNativeModules();
  }

  loadNativeModules() {
    try {
      // 尝试加载 SQLite3
      const sqlite3 = require('sqlite3');
      this.nativeModules.set('sqlite3', sqlite3);
      console.log('SQLite3 模块加载成功');
    } catch (error) {
      console.warn('SQLite3 模块加载失败:', error.message);
    }

    try {
      // 尝试加载图像处理模块
      const sharp = require('sharp');
      this.nativeModules.set('sharp', sharp);
      console.log('Sharp 模块加载成功');
    } catch (error) {
      console.warn('Sharp 模块加载失败:', error.message);
    }
  }

  // 数据库操作
  setupDatabase() {
    const sqlite3 = this.nativeModules.get('sqlite3');
    if (!sqlite3) {
      throw new Error('SQLite3 模块不可用');
    }

    const dbPath = `${app.getPath('userData')}/app.db`;
    const db = new sqlite3.Database(dbPath);

    return {
      db,
      // 封装常用数据库操作
      run: (sql, params = []) => {
        return new Promise((resolve, reject) => {
          db.run(sql, params, function(error) {
            if (error) {
              reject(error);
            } else {
              resolve({ id: this.lastID, changes: this.changes });
            }
          });
        });
      },

      get: (sql, params = []) => {
        return new Promise((resolve, reject) => {
          db.get(sql, params, (error, row) => {
            if (error) {
              reject(error);
            } else {
              resolve(row);
            }
          });
        });
      },

      all: (sql, params = []) => {
        return new Promise((resolve, reject) => {
          db.all(sql, params, (error, rows) => {
            if (error) {
              reject(error);
            } else {
              resolve(rows);
            }
          });
        });
      }
    };
  }

  // 图像处理
  async processImage(inputPath, outputPath, operations = {}) {
    const sharp = this.nativeModules.get('sharp');
    if (!sharp) {
      throw new Error('Sharp 模块不可用');
    }

    let image = sharp(inputPath);

    // 应用操作
    if (operations.resize) {
      image = image.resize(operations.resize.width, operations.resize.height);
    }

    if (operations.rotate) {
      image = image.rotate(operations.rotate);
    }

    if (operations.format) {
      image = image.toFormat(operations.format);
    }

    // 保存图像
    await image.toFile(outputPath);
    return { success: true, outputPath };
  }
}

原生模块构建与兼容性

确保原生模块与 Electron 版本兼容:

javascript
// build-tools.js
import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';

class NativeModuleBuilder {
  constructor() {
    this.electronVersion = process.versions.electron;
  }

  // 检查模块兼容性
  checkModuleCompatibility(moduleName) {
    try {
      // 使用 electron-rebuild 检查兼容性
      const result = execSync(`npx electron-rebuild --module-dir node_modules/${moduleName} --electron-version ${this.electronVersion} --dry-run`, {
        encoding: 'utf-8'
      });
      return { compatible: true, message: result };
    } catch (error) {
      return { compatible: false, error: error.message };
    }
  }

  // 重建原生模块
  rebuildModule(moduleName) {
    try {
      console.log(`正在为 Electron ${this.electronVersion} 重建 ${moduleName}...`);
      
      execSync(`npx electron-rebuild --module-dir node_modules/${moduleName} --electron-version ${this.electronVersion}`, {
        stdio: 'inherit'
      });
      
      return { success: true };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }

  // 自动处理所有原生模块
  async rebuildAllModules() {
    const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
    const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
    
    const nativeModules = await this.detectNativeModules();
    
    for (const moduleName of nativeModules) {
      console.log(`处理模块: ${moduleName}`);
      
      const compatibility = this.checkModuleCompatibility(moduleName);
      if (!compatibility.compatible) {
        console.log(`重建模块 ${moduleName}...`);
        const result = this.rebuildModule(moduleName);
        
        if (!result.success) {
          console.error(`重建 ${moduleName} 失败:`, result.error);
        }
      } else {
        console.log(`模块 ${moduleName} 兼容`);
      }
    }
  }

  // 检测项目中的原生模块
  async detectNativeModules() {
    const nodeModulesPath = 'node_modules';
    const nativeModules = [];
    
    try {
      const modules = fs.readdirSync(nodeModulesPath);
      
      for (const module of modules) {
        if (module.startsWith('.')) continue;
        
        const modulePath = path.join(nodeModulesPath, module);
        const bindingGypPath = path.join(modulePath, 'binding.gyp');
        
        if (fs.existsSync(bindingGypPath)) {
          nativeModules.push(module);
        }
      }
    } catch (error) {
      console.error('检测原生模块时出错:', error);
    }
    
    return nativeModules;
  }
}

性能优化与资源管理

Node.js 进程优化

javascript
// performance-manager.js
import { performance, PerformanceObserver } from 'perf_hooks';
import v8 from 'v8';

class NodePerformanceManager {
  constructor() {
    this.metrics = new Map();
    this.setupPerformanceMonitoring();
  }

  setupPerformanceMonitoring() {
    // 监控垃圾回收
    const observer = new PerformanceObserver((list) => {
      const entries = list.getEntries();
      entries.forEach((entry) => {
        console.log(`GC 事件: ${entry.name}`, entry.duration);
        this.recordMetric('gc', entry);
      });
    });

    observer.observe({ entryTypes: ['gc'] });

    // 定期收集性能指标
    setInterval(() => {
      this.collectPerformanceMetrics();
    }, 5000);
  }

  collectPerformanceMetrics() {
    const metrics = {
      timestamp: Date.now(),
      memory: process.memoryUsage(),
      cpu: process.cpuUsage(),
      heap: v8.getHeapStatistics(),
      activeHandles: process._getActiveHandles().length,
      activeRequests: process._getActiveRequests().length
    };

    this.metrics.set(metrics.timestamp, metrics);
    
    // 保持最近100个指标
    if (this.metrics.size > 100) {
      const firstKey = this.metrics.keys().next().value;
      this.metrics.delete(firstKey);
    }

    return metrics;
  }

  // 内存泄漏检测
  detectMemoryLeaks() {
    const metrics = Array.from(this.metrics.values());
    if (metrics.length < 10) return null;

    const recent = metrics.slice(-5);
    const older = metrics.slice(-10, -5);

    const recentAvg = this.averageMemory(recent);
    const olderAvg = this.averageMemory(older);

    const growth = (recentAvg - olderAvg) / olderAvg;
    
    if (growth > 0.1) { // 内存增长超过10%
      return {
        leakDetected: true,
        growthRate: growth,
        suggestion: '检查未释放的引用或定时器'
      };
    }

    return { leakDetected: false };
  }

  averageMemory(metrics) {
    const total = metrics.reduce((sum, m) => sum + m.memory.heapUsed, 0);
    return total / metrics.length;
  }

  // 强制垃圾回收(仅开发环境)
  forceGarbageCollection() {
    if (global.gc) {
      global.gc();
      return { success: true, message: '垃圾回收已执行' };
    } else {
      return { 
        success: false, 
        message: '请使用 --expose-gc 标志启动应用以启用强制垃圾回收' 
      };
    }
  }

  // 获取性能报告
  getPerformanceReport() {
    const metrics = Array.from(this.metrics.values());
    const latest = metrics[metrics.length - 1];
    
    return {
      summary: {
        uptime: process.uptime(),
        platform: process.platform,
        nodeVersion: process.version
      },
      current: latest,
      trends: this.calculateTrends(metrics),
      leaks: this.detectMemoryLeaks()
    };
  }

  calculateTrends(metrics) {
    if (metrics.length < 2) return {};
    
    const first = metrics[0];
    const last = metrics[metrics.length - 1];
    
    const memoryGrowth = (last.memory.heapUsed - first.memory.heapUsed) / first.memory.heapUsed;
    
    return {
      memoryGrowth,
      trend: memoryGrowth > 0.05 ? 'increasing' : memoryGrowth < -0.05 ? 'decreasing' : 'stable'
    };
  }
}

Electron 的 Node.js 集成提供了强大的能力,让开发者能够构建功能丰富的桌面应用程序。通过合理利用主进程的完整 Node.js 环境、安全地在渲染进程中暴露必要的 Node.js 功能、正确管理原生模块,以及实施性能监控和优化,可以创建出既具备 Web 应用灵活性又拥有原生应用能力的跨平台桌面应用。

Electron Node已经加载完毕