Aller au contenu principal

Archives ASAR

After creating an application distribution, the app's source code are usually bundled into an ASAR archive, which is a simple extensive archive format designed for Electron apps. By bundling the app we can mitigate issues around long path names on Windows, speed up require and conceal your source code from cursory inspection.

The bundled app runs in a virtual file system and most APIs would just work normally, but for some cases you might want to work on ASAR archives explicitly due to a few caveats.

Using ASAR Archives

In Electron there are two sets of APIs: Node APIs provided by Node.js and Web APIs provided by Chromium. Both APIs support reading files from ASAR archives.

Node API

With special patches in Electron, Node APIs like fs.readFile and require treat ASAR archives as virtual directories, and the files in it as normal files in the filesystem.

Par exemple, supposons que nous ayons une archive exemple.asar dans /chemin/vers :

$ asar list /chemin/vers/exemple.asar
/app.js
/file.txt
/dir/module.js
/static/index.html
/static/main.css
/static/jquery.min.js

Read a file in the ASAR archive:

const fs = require('fs')
fs.readFileSync('/chemin/vers/exemple.asar/fichier.txt')

Lister tous les fichiers à la racine de l’archive :

const fs = require('fs')
fs.readdirSync('/chemin/vers/exemple.asar')

Utiliser un module de l’archive :

require('./path/to/example.asar/dir/module.js')

You can also display a web page in an ASAR archive with BrowserWindow:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

win.loadURL('file:///path/to/example.asar/static/index.html')

Web API

In a web page, files in an archive can be requested with the file: protocol. Like the Node API, ASAR archives are treated as directories.

Par exemple, pour obtenir un fichier avec $.get:

<script>
let $ = require('./jquery.min.js')
$.get('file:///chemin/vers/exemple.asar/fichier.txt', (data) => {
console.log(data)
})
</script>

Treating an ASAR archive as a Normal File

For some cases like verifying the ASAR archive's checksum, we need to read the content of an ASAR archive as a file. Pour cela, vous pouvez utiliser le module original-fs intégré qui fournit l'API fs sans le support de asar :

const originalFs = require('original-fs')
originalFs.readFileSync('/chemin/vers/exemple.asar')

Vous pouvez également définir process.noAsar à true pour désactiver le support de asar dans le module fs :

const fs = require('fs')
process.noAsar = true
fs.readFileSync('/chemin/vers/exemple.asar')

Limites de Node API

Even though we tried hard to make ASAR archives in the Node API work like directories as much as possible, there are still limitations due to the low-level nature of the Node API.

Les archives sont en lecture seule

The archives can not be modified so all Node APIs that can modify files will not work with ASAR archives.

Le dossier de travail ne peux pas être définie comme dossier dans une archive

Though ASAR archives are treated as directories, there are no actual directories in the filesystem, so you can never set the working directory to directories in ASAR archives. Les passer en tant qu'option de cwd de certaines APIs occasionnera aussi des erreurs.

Dépaquetage supplémentaire sur certaines APIs

Most fs APIs can read a file or get a file's information from ASAR archives without unpacking, but for some APIs that rely on passing the real file path to underlying system calls, Electron will extract the needed file into a temporary file and pass the path of the temporary file to the APIs to make them work. Cela ajoute un traitement supplémentaire pour ces APIs.

Les APIs qui requièrent un dépaquetage supplémentaire sont :

  • child_process.execFile
  • child_process.execFileSync
  • fs.open
  • fs.openSync
  • process.dlopen - utilisé par require sur des modules natifs

Fausses informations Stat de fs.stat

Les objets Stats retournés par fs.stat et ses amis sur les fichiers dans les archives asar sont générés par déduction, parce que ces fichiers n'existent pas dans le système de fichiers. Donc vous ne devriez pas faire confiance aux objets Stats sauf pour obtenir la taille du fichier et vérifier le type de fichier.

Executing Binaries Inside ASAR archive

There are Node APIs that can execute binaries like child_process.exec, child_process.spawn and child_process.execFile, but only execFile is supported to execute binaries inside ASAR archive.

C'est parce que exec et spawn acceptent command au lieu de file en entrée, et les command sont exécutées sous shell. Il n'y a pas de moyen fiable de déterminer si une commande utilise un fichier dans une archive asar, et même si nous le faisons, nous ne pouvons pas être sûrs de pouvoir remplacer les chemins d'accès dans la commande sans effets secondaires.

Adding Unpacked Files to ASAR archives

As stated above, some Node APIs will unpack the file to the filesystem when called. Apart from the performance issues, various anti-virus scanners might be triggered by this behavior.

As a workaround, you can leave various files unpacked using the --unpack option. In the following example, shared libraries of native Node.js modules will not be packed:

$ asar pack app app.asar --unpack *.node

Après avoir exécuter la commande, vous remarquerez qu'un dossier nommé app.asar.unpacked a été créé avec le fichier app.asar. Il contient les fichiers non-empaquetés et devrait être distribué avec l'archive app.asar.