Формат ASAR: упаковка приложений Electron без усилий
Основы формата ASAR для упаковки Electron приложений
ASAR (Atom Shell Archive) – это архивный формат, используемый в Electron для объединения файлов приложения в один файл. Он ускоряет загрузку, уменьшает количество операций ввода-вывода и частично защищает исходный код. Ниже рассмотрены основные способы работы с ASAR.
Как упаковать приложение в ASAR с помощью пакета asar
Наиболее прямой способ – использование официального пакета @electron/asar. Он предоставляет CLI и Node API.
Установка
npm install -g @electron/asarJs asar (формат asar в electron (упаковка приложений))
Создание архива
asar pack ./my-app ./my-app.asar
Команда pack упаковывает содержимое папки my-app в файл my-app.asar. По умолчанию создаётся упорядоченный архив, доступный для чтения через специальный протокол asar://.
Проверка содержимого
asar list my-app.asar
Команда выводит иерархию файлов внутри архива.
Извлечение файлов
asar extract my-app.asar ./output
Распаковывает архив в указанную директорию.
Типичные ошибки и их решение
- Ошибка доступа к файлу – возникает, если пути содержат недопустимые символы или превышена длина. Решение: переименовать файлы, использовать более короткие имена.
- Проблемы с кодировкой – при упаковке файлов с не-UTF8 именами. Решение: использовать файлы только с UTF-8 именами.
- Архив большого размера – упаковка может занять много времени. Решение: исключить ненужные файлы (node_modules, исходники) с помощью опции
--exclude-hidden.
Использование @electron/asar подходит для ручной упаковки и интеграции в скрипты сборки. Это основное решение, на котором базируются все остальные.
Как настроить electron-builder для автоматической упаковки в ASAR
Популярный сборщик electron-builder включает встроенную поддержку ASAR. Достаточно указать опции в package.json или конфигурационном файле.
{
"build": {
"asar": true,
"asarUnpack": [
"node_modules/needed-native-module/**"
]
}
}
Флаг asar: true включает упаковку всех файлов в asar. Свойство asarUnpack перечисляет файлы, которые должны остаться вне архива (например, нативные модули).
Типичные ошибки и их решение
- Нативные модули не загружаются – если модули требуют доступ к файловой системе (Node.js addon), их надо исключить через
asarUnpack. Если забыть, приложение упадёт с ошибкойMODULE_NOT_FOUND. - Конфликт с автообновлением – при обновлении через
electron-updaterasar заменяется целиком, что может привести к сбоям. Решение: исключить конфигурационные файлы из asar.
Этот вариант предпочтителен для продакшен-сборок, так как автоматизирует процесс и обрабатывает исключения.
Как программно создать ASAR из Node.js скрипта
API пакета asar позволяет создавать архив из кода, что полезно для кастомных процессов сборки.
const { createPackage } = require('@electron/asar');
async function pack() {
await createPackage('./app', './app.asar');
console.log('Архив создан');
}
pack();
Для более тонкого контроля используется createPackageFromFiles, где можно указать список нужных файлов:
const { createPackageFromFiles } = require('@electron/asar');
const path = require('path');
const src = '/path/to/app';
const files = ['index.js', 'renderer.js', 'assets/'];
createPackageFromFiles(src, 'app.asar', files.map(f => path.join(src, f)));
Типичные ошибки и их решение
- Ошибка при работе с символическими ссылками – API не обрабатывает их по умолчанию. Решение: предварительно разрешать ссылки или исключать их.
- Превышение лимита памяти – при очень больших проектах. Решение: упаковывать по частям или использовать потоки.
Подходит для сложных сценариев, где нужно динамически формировать состав архива.
Как работать с ASAR через командную строку
Утилита asar предоставляет полноценный CLI для быстрого выполнения операций без Node.js кода.
# Упаковка
asar pack ./dist ./release/app.asar
# Извлечение
asar extract ./release/app.asar ./temp
# Список содержимого
asar list ./release/app.asar
Типичные ошибки и их решение
- Команда не найдена – пакет не установлен глобально. Решение: установить через
npm i -g @electron/asar. - Неверный формат архива – если asar-файл повреждён или создан другой утилитой. Решение: создать архив заново через asar pack.
CLI удобен для разовых операций и быстрой проверки.
Как настроить ASAR при упаковке через electron-packager
electron-packager также поддерживает asar через флаги.
npx electron-packager . MyApp --asar --asar-unpack=node_modules/some-module
Флаг --asar включает архивацию, --asar-unpack позволяет исключить подстроки пути. Можно указать несколько масок через запятую.
Типичные ошибки и их решение
- Пропущенные файлы – если маска не соответствует реальной структуре. Решение: детально проверить пути в консоли после сборки.
Подходит для простых проектов, где нет сложной конфигурации сборки.
Расширенные примеры работы с ASAR
Полный цикл: упаковка, просмотр, распаковка
Установим asar, создадим архив, проинспектируем его и восстановим файлы.
# Установка
npm install -g @electron/asar
# Создание тестового проекта
mkdir test-app
cd test-app
echo 'console.log("Hello")' > index.js
echo '{"main":"index.js"}' > package.json
mkdir assets
touch assets/icon.png
cd ..
# Упаковка
asar pack test-app test-app.asar
# Список
asar list test-app.asar
test-app/ test-app/index.js test-app/package.json test-app/assets/ test-app/assets/icon.png
# Распаковка
asar extract test-app.asar ./extracted
tree extracted
extracted/
├── index.js
├── package.json
└── assets/
└── icon.png
Архив полностью восстанавливается. Размер asar-файла обычно меньше исходной папки за счёт выравнивания данных.
Интеграция asar в npm скрипты
Добавим команды упаковки в package.json для автоматизации.
{
"scripts": {
"build": "webpack && node build.js",
"pack:asar": "asar pack ./dist ./release/app.asar",
"postbuild": "npm run pack:asar"
}
}
После выполнения npm run build автоматически запустится упаковка в asar. Такой подход используется для CI/CD.
Настройка electron-builder с asarUnpack для нативных модулей
Нативный модуль node-canvas требует доступа к файлам вне архива. Пример конфигурации:
{
"build": {
"appId": "com.example.app",
"asar": true,
"asarUnpack": [
"node_modules/canvas/build/**",
"node_modules/canvas/*.node"
],
"files": [
"!node_modules/**/*",
"!node_modules/canvas/build/**/*"
]
}
}
Файлы в asarUnpack остаются вне архива, но копируются в папку приложения. Это гарантирует, что нативные бинарники будут доступны в файловой системе.
Просмотр структуры asar с помощью asar list
Команда asar list принимает дополнительные флаги, например, --pretty для форматированного вывода в JSON.
asar list app.asar --pretty
{
"files": [
{"path": "index.js", "size": 25, "offset": 0},
{"path": "package.json", "size": 18, "offset": 512},
{"path": "assets/icon.png", "size": 1024, "offset": 1536}
]
}
Позволяет увидеть смещения и размеры каждого файла. Это помогает отлаживать проблемы с доступом.
Замена файла внутри asar архива
Так как asar неизменяем, для замены файла требуется распаковать архив, удалить старый файл, добавить новый и переупаковать. Пример скрипта:
const { extract, createPackage } = require('@electron/asar');
const fs = require('fs-extra');
const path = require('path');
async function replaceFile(asarPath, targetPath, newContent) {
const tempDir = './temp_asar';
await extract(asarPath, tempDir);
const fullTarget = path.join(tempDir, targetPath);
await fs.outputFile(fullTarget, newContent);
await createPackage(tempDir, asarPath.replace('.asar', '_v2.asar'));
await fs.remove(tempDir);
console.log('Архив обновлён');
}
Этот метод полезен для патчей без полной пересборки приложения.
Чтение файла из asar через Node.js
Electron монтирует asar как виртуальную файловую систему. Обычное чтение работает прозрачно, но если нужно обращаться к архиву вне контекста Electron, используется протокол asar://.
const fs = require('fs');
const pathInAsar = 'asar://' + path.resolve('./app.asar') + '/index.js';
const stream = fs.createReadStream(pathInAsar);
stream.on('data', chunk => console.log(chunk.toString()));
Обратите внимание: протокол asar:// доступен только внутри окружения Electron. Для обычного Node.js необходимо использовать API asar: fs.readFileSync(require.resolve('./app.asar/index.js')) после вызова asar.registerAsarFs (если такой модуль подключён).