|
1 | 1 | # Application packaging |
| 2 | + |
| 3 | +To protect your app's resources and source code from the users, you can choose |
| 4 | +to package your app into [asar][asar] archive with little changes to your source |
| 5 | +code. |
| 6 | + |
| 7 | +## Generating `asar` archive |
| 8 | + |
| 9 | +The [asar][asar] archive is a simple tar-like format that concatenates files |
| 10 | +into a single file, atom-shell can read arbitrary file in it without unpacking |
| 11 | +the whole file. |
| 12 | + |
| 13 | +Following is the steps to package your app into `asar` archive: |
| 14 | + |
| 15 | +### 1. Install asar utility |
| 16 | + |
| 17 | +```bash |
| 18 | +$ npm install -g asar |
| 19 | +``` |
| 20 | + |
| 21 | +### 2. Package with `asar pack` |
| 22 | + |
| 23 | +```bash |
| 24 | +$ asar pack your-app app.asar |
| 25 | +``` |
| 26 | + |
| 27 | +## Using `asar` archives |
| 28 | + |
| 29 | +In atom-shell there are two sets of APIs: Node APIs provided by Node.js, and Web |
| 30 | +APIs provided by Chromium. Both APIs support reading file from `asar` archives. |
| 31 | + |
| 32 | +### Node API |
| 33 | + |
| 34 | +With special patches in atom-shell, Node APIs like `fs.readFile` and `require` |
| 35 | +treat `asar` archives as virtual directories, and the files in it as normal |
| 36 | +files in filesystem. |
| 37 | + |
| 38 | +For example, suppose we have an `example.asar` archive under `/path/to`: |
| 39 | + |
| 40 | +```bash |
| 41 | +$ asar list /path/to/example.asar |
| 42 | +/app.js |
| 43 | +/file.txt |
| 44 | +/dir/module.js |
| 45 | +/static/index.html |
| 46 | +/static/main.css |
| 47 | +/static/jquery.min.js |
| 48 | +``` |
| 49 | + |
| 50 | +Read a file in `asar` archive: |
| 51 | + |
| 52 | +```javascript |
| 53 | +var fs = require('fs'); |
| 54 | +fs.readFileSync('/path/to/example.asar/file.txt'); |
| 55 | +``` |
| 56 | + |
| 57 | +List all files under the root of archive: |
| 58 | + |
| 59 | +```javascript |
| 60 | +var fs = require('fs'); |
| 61 | +fs.readdirSync('/path/to/example.asar'); |
| 62 | +``` |
| 63 | + |
| 64 | +Use a module from the archive: |
| 65 | + |
| 66 | +```javascript |
| 67 | +require('/path/to/example.asar/dir/module.js'); |
| 68 | +``` |
| 69 | + |
| 70 | +### Web API |
| 71 | + |
| 72 | +In web page files in archive can be requests by using the `asar:` protocol, |
| 73 | +like node API, `asar` archives are treated as directories. |
| 74 | + |
| 75 | +For example, to get a file with `$.get`: |
| 76 | + |
| 77 | +```html |
| 78 | +<script> |
| 79 | +var $ = require('./jquery.min.js'); |
| 80 | +$.get('asar:/path/to/example.asar/file.txt', function(data) { |
| 81 | + console.log(data); |
| 82 | +}); |
| 83 | +</script> |
| 84 | +``` |
| 85 | + |
| 86 | +The `asar:` protocol can also be used to request normal files in filesystem, |
| 87 | +just like the `file:` protocol. But unlike `file:` protocol, there is no slashes |
| 88 | +(`//`) after `asar:`. |
| 89 | + |
| 90 | +You can also display a web page in `asar` archive with `BrowserWindow`: |
| 91 | + |
| 92 | +```javascript |
| 93 | +var BrowserWindow = require('browser-window'); |
| 94 | +var win = new BrowserWindow({width: 800, height: 600}); |
| 95 | +win.loadUrl('asar:/path/to/example.asar/static/index.html'); |
| 96 | +``` |
| 97 | + |
| 98 | +## Limitations on Node API |
| 99 | + |
| 100 | +Even though we tried hard to make `asar` archives in Node API work like |
| 101 | +directories as much as possible, there are still limitations due to the |
| 102 | +low-level nature of Node API. |
| 103 | + |
| 104 | +### Archives are read only |
| 105 | + |
| 106 | +The archives can not be modifies so all Node APIs that can modify files will not |
| 107 | +work with `asar` archives. |
| 108 | + |
| 109 | +### Working directory can not be set to directories in archive |
| 110 | + |
| 111 | +Though `asar` archives are treated as directories, there are no actual |
| 112 | +directories in the filesystem, so you can never set working directory to |
| 113 | +directories in `asar` archives, passing them to `cwd` option of some APIs will |
| 114 | +also cause errors. |
| 115 | + |
| 116 | +### Extra unpacking on some APIs |
| 117 | + |
| 118 | +Most `fs` APIs can read file or get file's information from `asar` archives |
| 119 | +without unpacking, but for some APIs that rely on passing the real file path to |
| 120 | +underlying system calls, atom-shell will extract the needed file into a |
| 121 | +temporary file and pass the path of the temporary file to the APIs to make them |
| 122 | +work. This adds a little overhead for those APIs. |
| 123 | + |
| 124 | +APIs that requires extra unpacking are: |
| 125 | + |
| 126 | +* `child_process.execFile` |
| 127 | +* `child_process.fork` |
| 128 | +* `fs.open` |
| 129 | +* `fs.openSync` |
| 130 | +* `process.dlopen` - Used by `require` on native modules |
| 131 | + |
| 132 | +### Fake stat information of `fs.stat` |
| 133 | + |
| 134 | +The `Stats` object returned by `fs.stat` and its friends on files in `asar` |
| 135 | +archives are generated by guessing, because those files do not exist on |
| 136 | +filesystem. So you should not trust the `Stats` object except for getting file |
| 137 | +size and checking file type. |
| 138 | + |
| 139 | +[asar]: https://github.com/atom/asar |
0 commit comments