Фактическая боевая сводка Electron - уменьшить размер пакета

Electron

Я использую электрон уже некоторое время. Как самый мощный инструмент упаковки для межтерминальных приложений, я глубоко впечатлен его простотой и удобством использования. Раньше это была простая конфигурация из коробки. Недавно проект больше потребностей, и я выкопал больше API, в основном в том числе:

  1. Как отличить систему от упаковки стороннего ПО и запуска его в подпроцессе?
  2. Как оптимизировать размер упаковки электрона?

Давайте сначала перейдем в каталог проекта, чтобы облегчить описание позже

.
├── app                                             // 生产package.json
│   ├── package.json
│   └── yarn.lock
├── build                                           // 第三方资源
│   ├── macResources
│   └── winResources
├── dist                                            // 打包的应用的储存处
├── electron-builder.yml                            // 配置文件
├── icon.icns                                       // Mac的 icon
├── icon.ico                                        // Win 的 icon
├── main.js                                         // 主程序
├── package.json                                    // 开发 package.json
├── to-build                                        // 前端资源页面
│   ├── index.bundle.js
│   ├── index.html
├── webpack.config.js                               // 打包 main.js 的 webpack 配置
└── yarn.lock

Разбейте первую задачу:

  1. Система дифференциации В Electron есть несколько макропеременных, которые можно использовать непосредственно в файле, см.File Macros, Все что мне нужно это${os}, если они вас не удовлетворяют, вы можете использоватьenv.ENV_NAMEОпределите его самостоятельно. Необходимо использоватьcross-envГарантированно кроссплатформенный
cross-env CUSTOMER_ENV=anything electron-builder
  1. Как упаковать стороннее программное обеспечение Следует отметить, что электрон по умолчанию обнаружит все файлы, кроме папки сборки, если она соответствует заданным параметрам.file-pattern, он будет упакован. Требуется упаковать различное стороннее программное обеспечение (например, драйверы) в соответствии с различными системами. Я использую следующий метод:
  2. Сотрудничать${os}значение для имени папки,macResources/winResources, вы можете легко использовать переменную макроса "${os}Resources", чтобы найти соответствующую папку
  3. Поместите оба в папку сборки (так ничего не будет упаковано)
  4. Есть несколько способов упаковки
    1. определениеfile
    2. определениеextraResources
    3. определениеextraFiles(Единственное отличие от первого в том, что первый не копируется вcontentсередина,видеть) В итоге я использовал конфигурациюfile, потому чтоfileбудет сmainВ каталоге такого же уровня проще понять поиск пути командной строки после меня (extraResourcesБудет вResourceЭтот каталог требует../на предыдущий уровень)

Обратите внимание, что определеноfileПоле также означает, что значение по умолчанию недействительно, и вам нужно вручную включить их все.И это должна быть папка или включать подстановочные знаки (используйте имя файла напрямую, чтобы попытаться включить недействительное)

Также обратите внимание, что если это исполняемый файл, его нельзя использовать.asarМетод сжатия, необходимо установить:asar: false.Использование 2,3 не имеет этого ограничения (ведь оно в родительской папке, там реальный путь, не сожмется), после сравнения не используетсяasar, объем приложения не сильно отличается, и безопасности нет, его можно легко распаковать,Ссылаться на, Конечно, вы также можете использоватьasarUnpackполе для настройки конфигурации.Может относиться к

Следующим шагом является то, как заставить стороннее программное обеспечение выполняться вместе с приложением.main.jsиспользуется вchild-processмодульныйspawn, Просто перейдите по соответствующему пути. Это не относится к области электрона, это относится к nodejsAPI .

let childSpawn;
const checkMacOS = () => os.platform() === 'darwin';
if (checkMacOS()) {
  childSpawn = spawn(path.join(__dirname, 'macResources/xxx'));
} else {
  spawn(path.join(__dirname, './winResources/xxx'));
}

использоватьspawnЭто связано с тем, что стороннее программное обеспечение необходимо завершить одновременно с закрытием программного обеспечения.winможет быть прекращено автоматически,macНеобходимо указатьpid

  mainWindow.on('closed', function() {
    if (checkMacOS()) {
      process.kill(childSpawn.pid);
    }
    mainWindow = null
  })

На самом деле объем этого пакета намного меньше, чем если бы я упаковывал его без различия платформы (две платформы будут упакованы без различия платформы). упакованный контентnode_moduleНа него тоже приходится десятки мегабайт, и толку от него никакогоelectronа такжеelectron-builder... Нет, я должен найти способ удалить его.

Его определенно невозможно удалить напрямую, потому чтоmain.jsмногое другоеrequireЧто. Итак, первый шаг — использоватьwebpackДля упаковки и подключения зависимостей следует отметить, чтоtargetУстановить какelectron-main

Как включить после упаковкиmain.jsЕсть два варианта

  1. использовать предыдущийfilesполе, будетwebpackПослеmain.jsВключено. Здесь можно использовать подстановочные знаки и другие методы, поэтому я не буду вдаваться в подробности.
  2. использоватьдвойной пакет.json, это немного интересно, нужно развиватьpackage.json, один производственныйpackage.jsonИ похоже, что структура проекта стала чище, так что попробуйте. Конкретная операция – это
  3. создать новыйappпапка, по умолчанию будет корневым каталогом пакета, поэтому в файле конфигурацииfilesИспользуемый относительный путь необходимо соответствующим образом изменить.
  4. существуетappсоздать новыйpackage.json, просто включитеname, version, descriptionи другую простую информацию, а если есть не-js-зависимости, такие как вызовC++Библиотека, она нужна здесьdependenciesДобавлено. Я им не пользовался, так что пока не обращайте на него внимания.

Ниже приведеныwebpackКонфигурация, поскольку сам электрон является ядром хрома, не требует совместимости, поэтому не вводитсяbabel

const path = require('path');
module.exports = {
  target: 'electron-main',
  entry: path.resolve(__dirname, 'main.js'),
  output: {
    path: path.resolve(__dirname, 'app'),
    filename: '[name].js'
  },
  mode: 'production',
  node: {
    // 使用绝对路径
    __dirname: false,
  }
};

Ниже приведено электронноеymlконфигурация для справки

directories:
  output: ./dist
appId: com.electron.xxx
asar: false
copyright: xxx
productName: xxx
mac:
  target:
    - dmg
  icon: ./icon.icns
dmg:
  contents:
    - x: 130
      'y': 50
      type: dir
      name: Driver
      path: build/macResources/Driver
    - x: 130
      'y': 210
    - x: 400
      'y': 210
      type: link
      path: /Applications
nsis:
  allowToChangeInstallationDirectory: true
  oneClick: false
  menuCategory: true
  include: build/installer.nsh
  allowElevation: true
  perMachine: true
win:
  target: nsis
files:
    - from: ../build/${os}Resources/
      to: ${os}Resources/
    - from: ./
      to: ./
    - from: ../to-build
      to: web
compression: normal
electronVersion: 6.0.9

Поговорим о результатах, ведь сторонний софт загружается по требованию, что сокращается вдвоеresourceРазмер, т.к. удаленnode_modules, использоватьwebpackПосле uglify стало на десятки мегабайт меньше.Поскольку у меня сторонний софт относительно большой, то общее сокращение составляет более 400 М. Плюс конфигурацияcompression: normal, После сжатия объем установочного пакета контролируется в пределах 150M, что соответствует требованиям продукта.