Если 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
- Соберите проблемный артефакт тем же способом, которым формируется релиз, и запускайте именно его, а не electron . из исходников.
- Сохраните версию macOS, модель процессора, process.platform, process.arch, версии Electron и приложения.
- Разделите логи main process, preload и renderer. Добавьте обработчики uncaughtException и unhandledRejection с безопасной записью стека.
- Проверьте системный crash report и Console рядом с моментом завершения процесса.
- Сравните список файлов внутри .app и app.asar с Windows-артефактом: конфигурацию, preload, assets, бинарники и нативные модули.
- Запустите проблемную функцию отдельно и зафиксируйте входные данные, путь к ресурсу, команду, exit code и stderr без секретов.
- Проверьте code signature, Gatekeeper assessment и журнал нотариализации для релизного файла.
- Повторите запуск из чистой учетной записи после скачивания дистрибутива, чтобы воспроизвести quarantine и отсутствующие пользовательские настройки.
Как исправить кроссплатформенный код
Исправление лучше строить через небольшой платформенный адаптер. Общая бизнес-логика остается единой, а пути, системные команды, разрешения и нативные интеграции получают отдельные проверяемые реализации.
- Замените ручную конкатенацию путей на системные API и уберите зависимость от current working directory.
- Перенесите изменяемые файлы из каталога приложения в userData, cache, temp или выбранный пользователем каталог.
- Замените Windows-only команды на кроссплатформенную библиотеку либо отдельную macOS-реализацию.
- Пересоберите нативные зависимости под darwin и нужные x64, arm64 или universal targets.
- Исправьте упаковку extraResources и asarUnpack только для файлов, которым действительно нужен доступ вне asar.
- Настройте подпись вложенных binaries, Hardened Runtime, минимальные entitlements и нотариализацию.
- Добавьте понятную обработку отсутствующего разрешения и повторный запрос только в корректном пользовательском сценарии.
- Собирайте 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-сборку и проверю релизный сценарий без ослабления системной защиты.