-
Notifications
You must be signed in to change notification settings - Fork 15k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add back docs about asar archives (#35667)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
- Loading branch information
Showing
2 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
--- | ||
title: ASAR Archives | ||
description: What is ASAR archive and how does it affect the application. | ||
slug: asar-archives | ||
hide_title: false | ||
--- | ||
|
||
After creating an [application distribution](application-distribution.md), the | ||
app's source code are usually bundled into an [ASAR | ||
archive](https://github.com/electron/asar), 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. | ||
|
||
For example, suppose we have an `example.asar` archive under `/path/to`: | ||
|
||
```sh | ||
$ asar list /path/to/example.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: | ||
|
||
```javascript | ||
const fs = require('fs') | ||
fs.readFileSync('/path/to/example.asar/file.txt') | ||
``` | ||
|
||
List all files under the root of the archive: | ||
|
||
```javascript | ||
const fs = require('fs') | ||
fs.readdirSync('/path/to/example.asar') | ||
``` | ||
|
||
Use a module from the archive: | ||
|
||
```javascript | ||
require('./path/to/example.asar/dir/module.js') | ||
``` | ||
|
||
You can also display a web page in an ASAR archive with `BrowserWindow`: | ||
|
||
```javascript | ||
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. | ||
|
||
For example, to get a file with `$.get`: | ||
|
||
```html | ||
<script> | ||
let $ = require('./jquery.min.js') | ||
$.get('file:///path/to/example.asar/file.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. For this purpose you can use the built-in | ||
`original-fs` module which provides original `fs` APIs without `asar` support: | ||
|
||
```javascript | ||
const originalFs = require('original-fs') | ||
originalFs.readFileSync('/path/to/example.asar') | ||
``` | ||
|
||
You can also set `process.noAsar` to `true` to disable the support for `asar` in | ||
the `fs` module: | ||
|
||
```javascript | ||
const fs = require('fs') | ||
process.noAsar = true | ||
fs.readFileSync('/path/to/example.asar') | ||
``` | ||
|
||
## Limitations of the 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. | ||
|
||
### Archives Are Read-only | ||
|
||
The archives can not be modified so all Node APIs that can modify files will not | ||
work with ASAR archives. | ||
|
||
### Working Directory Can Not Be Set to Directories in 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. Passing them as the `cwd` option of some APIs | ||
will also cause errors. | ||
|
||
### Extra Unpacking on Some 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. This adds a little overhead for those APIs. | ||
|
||
APIs that requires extra unpacking are: | ||
|
||
* `child_process.execFile` | ||
* `child_process.execFileSync` | ||
* `fs.open` | ||
* `fs.openSync` | ||
* `process.dlopen` - Used by `require` on native modules | ||
|
||
### Fake Stat Information of `fs.stat` | ||
|
||
The `Stats` object returned by `fs.stat` and its friends on files in `asar` | ||
archives is generated by guessing, because those files do not exist on the | ||
filesystem. So you should not trust the `Stats` object except for getting file | ||
size and checking file type. | ||
|
||
### 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. | ||
|
||
This is because `exec` and `spawn` accept `command` instead of `file` as input, | ||
and `command`s are executed under shell. There is no reliable way to determine | ||
whether a command uses a file in asar archive, and even if we do, we can not be | ||
sure whether we can replace the path in command without side effects. | ||
|
||
## 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: | ||
|
||
```sh | ||
$ asar pack app app.asar --unpack *.node | ||
``` | ||
|
||
After running the command, you will notice that a folder named `app.asar.unpacked` | ||
was created together with the `app.asar` file. It contains the unpacked files | ||
and should be shipped together with the `app.asar` archive. |