一、Electron打包体积为什么这么大?

每次用Electron打完包,看着动辄上百MB的安装包,我的内心都是崩溃的。这玩意儿怎么就这么大呢?让我们先看看默认打包时都塞了些什么东西:

  1. 完整的Chromium浏览器内核(约50-60MB)
  2. Node.js运行时(约20-30MB)
  3. 你的应用代码和依赖
  4. 各种资源文件(图片、字体等)
// 典型electron-builder配置示例(技术栈:Electron + electron-builder)
{
  "build": {
    "appId": "com.example.myapp",
    "files": [
      "dist/**/*",
      "node_modules/**/*"  // 默认包含所有node_modules
    ],
    "asar": true,          // 默认启用asar打包
    "win": {
      "target": "nsis"     // 默认使用NSIS安装包
    }
  }
}

二、基础优化方案

2.1 清理无用依赖

首先打开你的package.json,看看dependencies里是不是躺着很多实际上没用的包?我经常发现项目里有这些"僵尸依赖":

# 使用depcheck找出无用依赖(技术栈:Node.js)
npx depcheck

# 输出示例:
Unused dependencies
* lodash (声明了但从未使用)
* moment (声明了但从未使用)

2.2 使用electron-builder的排除配置

electron-builder允许我们精确控制打包内容:

// 优化后的electron-builder配置
{
  "build": {
    "files": [
      "!**/node_modules/aws-sdk",       // 排除AWS SDK
      "!**/node_modules/electron/*.ts",  // 排除TypeScript源码
      "!**/*.map"                       // 排除sourcemap
    ],
    "asarUnpack": [
      "**/*.node"                       // 解压原生模块
    ]
  }
}

2.3 选择性引入Node原生模块

有些Node原生模块特别占地方,比如sqlite3:

// 错误示例:直接require整个sqlite3
const sqlite3 = require('sqlite3')

// 正确做法:动态加载
const { app } = require('electron')
const path = require('path')

let sqlite3
app.whenReady().then(() => {
  sqlite3 = require(path.join(__dirname, 'sqlite3.node'))
})

三、进阶优化技巧

3.1 使用electron-packager替代方案

electron-builder虽然方便,但electron-packager在某些场景下更灵活:

# 使用electron-packager的过滤选项(技术栈:Node.js)
npx electron-packager . --ignore="node_modules/(aws-sdk|electron-prebuild)"

3.2 压缩资源文件

图片和字体是体积大户,试试这些工具:

// 使用sharp压缩图片(技术栈:Node.js)
const sharp = require('sharp')

sharp('input.png')
  .resize(800)
  .webp({ quality: 80 })
  .toFile('output.webp')

3.3 代码分割

Electron支持动态导入:

// 静态导入(全部打包)
import utils from './utils'

// 动态导入(按需加载)
const utils = await import('./utils')

四、终极优化方案

4.1 使用electron-vite

vite的按需编译特性非常适合Electron:

// vite.config.js(技术栈:Electron + Vite)
export default {
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return 'vendor'
          }
        }
      }
    }
  }
}

4.2 启用UPX压缩

对可执行文件进行二次压缩:

# 在electron-builder中配置UPX(技术栈:Linux)
{
  "build": {
    "win": {
      "target": {
        "arch": ["x64"],
        "compression": "maximum"
      }
    },
    "afterPack": "./scripts/upx.js"
  }
}

4.3 使用WebAssembly替代部分JS代码

性能关键部分可以用Rust编写:

// lib.rs(技术栈:Rust + WASM)
#[wasm_bindgen]
pub fn heavy_compute(input: i32) -> i32 {
    input * 2
}

然后在Electron中调用:

import init, { heavy_compute } from './pkg/wasm_module'

await init()
heavy_compute(42)

五、实际案例对比

优化前:

  • 安装包大小:210MB
  • 启动时间:3.2秒
  • 内存占用:320MB

优化后:

  • 安装包大小:68MB(减少67%)
  • 启动时间:1.8秒(提升43%)
  • 内存占用:210MB(减少34%)

六、注意事项

  1. 测试!测试!再测试!每次优化后都要完整测试所有功能
  2. 原生模块需要匹配Electron的ABI版本
  3. 某些安全工具会误报UPX压缩的文件
  4. 生产环境建议保留sourcemap以便调试

七、总结

Electron应用体积优化是个系统工程,需要:

  1. 从依赖管理入手
  2. 合理配置打包工具
  3. 优化资源文件
  4. 考虑使用更现代的构建工具
  5. 在关键路径使用性能更好的技术

记住:没有银弹,要根据你的应用特点选择适合的优化组合。