Если Electron-приложение стабильно работает на Windows, но падает на macOS, причина обычно находится не в самом интерфейсе. Чаще ломается платформенный слой: пути к файлам, запуск внешних программ, нативный модуль, архитектура сборки, доступ к ресурсам или подпись приложения.

Начинать исправление нужно с точного этапа сбоя. Приложение может падать до создания окна, после загрузки renderer, при обращении к конкретной функции или только у пользователя после скачивания из интернета. Для каждого сценария нужен свой набор данных.

Сначала определите, где именно происходит сбой

Не объединяйте все случаи в формулировку «на Mac не работает». Зафиксируйте минимальный сценарий и момент, после которого процесс завершается.

  • Падает ли main process до появления окна или renderer после загрузки страницы.
  • Работает ли запуск через режим разработки и воспроизводится ли ошибка в упакованном .app.
  • Падает ли приложение сразу или после открытия файла, печати, обновления, экспорта либо другой функции.
  • Возникает ли ошибка на Intel Mac, Apple Silicon или на обеих архитектурах.
  • Запускается ли локальная сборка, но блокируется версия, скачанная через браузер.

Если проблема появляется только после упаковки, сначала проверяйте состав app bundle, asar, пути и подпись. Если падает и development-сборка, полезнее начать с платформенной ветки кода, зависимостей и системных разрешений.

Основные причины различий между Windows и macOS

Жестко заданные пути и запись внутрь приложения

Пути с обратными слешами, буквами дисков и каталогами вроде Program Files не переносятся на macOS. После упаковки ресурсы Electron также располагаются иначе, а содержимое app bundle и app.asar нельзя использовать как обычное рабочее хранилище.

  • Для сборки путей используйте системные функции path.join и path.resolve.
  • Путь к упакованным ресурсам определяйте через process.resourcesPath и конфигурацию packager.
  • Настройки, кеш и пользовательские файлы записывайте в app.getPath("userData") или другой подходящий системный каталог.
  • Не рассчитывайте, что текущая рабочая директория совпадает с каталогом приложения.

Windows-команды и различия окружения

Вызов cmd.exe, PowerShell, .exe-файла или команды с Windows-синтаксисом завершится ошибкой на macOS. Кроме того, GUI-приложение на Mac может получать другой PATH, чем Terminal, поэтому установленная утилита не всегда доступна по короткому имени.

  • Разделяйте платформенные реализации через process.platform, не размазывая условные проверки по всему проекту.
  • При запуске процесса передавайте программу и аргументы отдельно, а не собирайте одну shell-строку.
  • Используйте абсолютный путь к поставляемой утилите и проверяйте ее архитектуру.
  • Явно обрабатывайте exit code, stderr, timeout и отсутствие бинарного файла.

Нативные Node.js-модули собраны не для той платформы

Модули с файлами .node зависят от платформы, архитектуры и ABI Electron. Каталог node_modules, установленный на Windows, нельзя просто положить в macOS-сборку. Для Electron такие зависимости нужно пересобирать под используемую версию runtime и целевую архитектуру.

  • Проверьте sqlite, serialport, sharp, keytar и другие пакеты с нативным кодом.
  • Сопоставьте версии Electron, Node ABI, process.arch и архитектуру каждого бинарника.
  • Пересоберите зависимости штатным инструментом, например @electron/rebuild, на macOS runner.
  • Для universal-сборки убедитесь, что нативные компоненты действительно содержат обе архитектуры.

Подпись, Hardened Runtime и нотариализация

Локальный неподписанный .app может запускаться у разработчика, но скачанный дистрибутив проверяется Gatekeeper. Подписывать нужно не только внешний bundle, но и вложенные helpers, frameworks и нативные исполняемые файлы. Для распространения вне Mac App Store используется Developer ID и нотариализация актуальным процессом Apple.

  • Проверьте целостность code signature и подписи всех вложенных компонентов.
  • Изучите notary log, а не только финальный статус загрузки.
  • Включайте только необходимые entitlements и соответствующие purpose strings.
  • Не отключайте библиотечную валидацию или другие защиты без подтвержденной необходимости.

Разрешения macOS и защищенные каталоги

Доступ к камере, микрофону, контактам, автоматизации и некоторым пользовательским каталогам регулируется macOS. Если в Info.plist отсутствует описание назначения или приложение неверно обрабатывает отказ, функция может завершать процесс либо оставаться без данных.

Пошаговая диагностика на macOS

  1. Соберите проблемный артефакт тем же способом, которым формируется релиз, и запускайте именно его, а не electron . из исходников.
  2. Сохраните версию macOS, модель процессора, process.platform, process.arch, версии Electron и приложения.
  3. Разделите логи main process, preload и renderer. Добавьте обработчики uncaughtException и unhandledRejection с безопасной записью стека.
  4. Проверьте системный crash report и Console рядом с моментом завершения процесса.
  5. Сравните список файлов внутри .app и app.asar с Windows-артефактом: конфигурацию, preload, assets, бинарники и нативные модули.
  6. Запустите проблемную функцию отдельно и зафиксируйте входные данные, путь к ресурсу, команду, exit code и stderr без секретов.
  7. Проверьте code signature, Gatekeeper assessment и журнал нотариализации для релизного файла.
  8. Повторите запуск из чистой учетной записи после скачивания дистрибутива, чтобы воспроизвести quarantine и отсутствующие пользовательские настройки.

Как исправить кроссплатформенный код

Исправление лучше строить через небольшой платформенный адаптер. Общая бизнес-логика остается единой, а пути, системные команды, разрешения и нативные интеграции получают отдельные проверяемые реализации.

  1. Замените ручную конкатенацию путей на системные API и уберите зависимость от current working directory.
  2. Перенесите изменяемые файлы из каталога приложения в userData, cache, temp или выбранный пользователем каталог.
  3. Замените Windows-only команды на кроссплатформенную библиотеку либо отдельную macOS-реализацию.
  4. Пересоберите нативные зависимости под darwin и нужные x64, arm64 или universal targets.
  5. Исправьте упаковку extraResources и asarUnpack только для файлов, которым действительно нужен доступ вне asar.
  6. Настройте подпись вложенных binaries, Hardened Runtime, минимальные entitlements и нотариализацию.
  7. Добавьте понятную обработку отсутствующего разрешения и повторный запрос только в корректном пользовательском сценарии.
  8. Собирайте macOS-релиз на macOS CI runner и проверяйте готовый артефакт до публикации.

Как проверить результат

  • Упакованное приложение запускается двойным кликом без Terminal и переменных среды разработчика.
  • Одинаково проходят Intel и Apple Silicon сценарии, заявленные в поддержке продукта.
  • Первый запуск скачанного дистрибутива проходит проверку Gatekeeper и не требует ручного снятия quarantine.
  • Функции чтения, записи, экспорта, печати и запуска внешних процессов работают с путями, содержащими пробелы и кириллицу.
  • Отказ в системном разрешении показывает понятное состояние и не завершает процесс.
  • Повторный запуск, обновление и сохранение настроек не возвращают прежнюю ошибку.
  • В новых логах нет необработанных исключений, ошибок загрузки .node и нарушений code signature.

Типичные ошибки при исправлении

  • Проверять только development-режим и считать его эквивалентом релизной сборки.
  • Копировать node_modules с Windows вместо установки и rebuild под macOS.
  • Снимать quarantine командой xattr у себя и считать проблему пользователей решенной.
  • Добавлять широкие entitlements или отключать Hardened Runtime, не найдя конкретную причину.
  • Логировать только renderer, когда приложение завершается в main process или нативном модуле.
  • Исправлять один абсолютный путь другим абсолютным путем конкретного Mac.
  • Тестировать только на машине разработчика с установленными Xcode, Homebrew и нужными CLI-утилитами.

Как предотвратить повторение

  • Собирайте Windows и macOS артефакты на нативных CI runners из одного зафиксированного lockfile.
  • Добавьте smoke-тест готового .app: запуск, создание окна, чтение ресурсов и запись пользовательских данных.
  • Проверяйте x64 и arm64 при каждом изменении нативных зависимостей.
  • Храните платформенные функции в отдельных модулях с явным контрактом и тестами.
  • Автоматизируйте проверку подписи и результат нотариализации перед публикацией.
  • Собирайте обезличенные crash reports с версией приложения, macOS и архитектурой.

Когда нужна помощь

Если Electron-приложение работает на Windows, но падает на macOS, я проверю готовый артефакт, main и renderer logs, пути, нативные зависимости, архитектуру, подпись и разрешения. После диагностики исправлю конкретную причину, настрою воспроизводимую macOS-сборку и проверю релизный сценарий без ослабления системной защиты.