electron/docs/tutorial/application-packaging.md
2015-04-16 11:31:12 +08:00

4.6 KiB

Application packaging

To protect your app's resources and source code from the users, you can choose to package your app into an asar archive with little changes to your source code.

Generating asar archive

An asar archive is a simple tar-like format that concatenates files into a single file, Electron can read arbitrary files from it without unpacking the whole file.

Following is the steps to package your app into an asar archive:

1. Install the asar utility

$ npm install -g asar

2. Package with asar pack

$ asar pack your-app app.asar

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:

$ 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:

var fs = require('fs');
fs.readFileSync('/path/to/example.asar/file.txt');

List all files under the root of the archive:

var fs = require('fs');
fs.readdirSync('/path/to/example.asar');

Use a module from the archive:

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

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

var BrowserWindow = require('browser-window');
var win = new BrowserWindow({width: 800, height: 600});
win.loadUrl('file:///path/to/example.asar/static/index.html');

Web API

In a web page, files in 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:

<script>
var $ = require('./jquery.min.js');
$.get('file:///path/to/example.asar/file.txt', function(data) {
  console.log(data);
});
</script>

Treating asar archive as normal file

For some cases like verifying the asar archive's checksum, we need to read the content of asar archive as file. For this purpose you can use the built-in original-fs module which provides original fs APIs without asar support:

var originalFs = require('original-fs');
originalFs.readFileSync('/path/to/example.asar');

Limitations on 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 to cwd option of some APIs will also cause errors.

Extra unpacking on some APIs

Most fs APIs can read file or get 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
  • 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.

Adding unpacked files in asar archive

As stated above, some Node APIs will unpack the file to filesystem when calling, apart from the performance issues, it could also lead to false alerts of virus scanners.

To work around this, you can unpack some files creating archives by using the --unpack option, an example of excluding shared libraries of native modules is:

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

After running the command, apart from the app.asar, there is also an app.asar.unpacked folder generated which contains the unpacked files, you should copy it together with app.asar when shipping it to users.