|
@@ -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.
|