5.7 KiB
應用程式打包
為了減少圍繞著 Windows 上長路徑名稱問題的 issues ,稍微地加速 require
和隱藏你的原始碼避免不小心被看到,你可以選擇把你的應用程式打包成一個 asar 壓縮檔,只需要改變一點點你的原始碼就好。
產生 asar
壓縮檔
一個 asar 壓縮檔是一個簡單的類 tar 格式的檔案,它會把幾個檔案串接成一個檔案, Electron 可以不需要解壓縮整個檔案就從中讀取任意檔案。
把你的應用程式打包成 asar
壓縮檔的步驟:
1. 安裝 asar 工具包
$ npm install -g asar
2. 用 asar pack
打包
$ asar pack your-app app.asar
使用 asar
壓縮檔
在 Electron 中有兩組 API:Node.js 提供的 Node APIs 和 Chromium 提供的 Web
APIs,兩組 API 都支援從 asar
壓縮檔中讀取檔案。
Node API
因為 Electron 中有一些特別的補釘,像是 fs.readFile
和 require
這樣的 Node API 會將 asar
壓縮檔視為許多虛擬目錄,將裡頭的檔案視為在檔案系統上的一般檔案。
例如,假設我們有一個 example.asar
壓縮檔在 /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
讀取一個在 asar
壓縮檔中的檔案:
const fs = require('fs');
fs.readFileSync('/path/to/example.asar/file.txt');
列出所有在壓縮檔根目錄下的檔案:
const fs = require('fs');
fs.readdirSync('/path/to/example.asar');
使用一個壓縮檔中的模組:
require('/path/to/example.asar/dir/module.js');
你也可以利用 BrowserWindow
在 asar
壓縮檔中呈現一個網頁:
const BrowserWindow = require('electron').BrowserWindow;
var win = new BrowserWindow({width: 800, height: 600});
win.loadURL('file:///path/to/example.asar/static/index.html');
Web API
在一個網頁中,壓縮檔中的檔案都可以透過 file:
這個協定被存取,如同 Node API,asar
壓縮檔都被視為目錄。
例如,要透過 $.get
取得一個檔案:
<script>
var $ = require('./jquery.min.js');
$.get('file:///path/to/example.asar/file.txt', function(data) {
console.log(data);
});
</script>
把一個 asar
壓縮檔視為一般檔案
在一些像是驗證 asar
壓縮檔檢查碼(checksum)的例子中,我們需要以檔案的方式讀取 asar
壓縮檔中的內容,為了達到這個目的,你可以使用內建的
original-fs
模組,它提供了沒有 asar
支援的原生 fs
API:
var originalFs = require('original-fs');
originalFs.readFileSync('/path/to/example.asar');
你也可以設定 process.noAsar
為 true
來關掉在 fs
模組中的 asar
支援:
process.noAsar = true;
fs.readFileSync('/path/to/example.asar');
Node API 上的限制
儘管我們盡可能的努力嘗試著使 Node API 中的 asar
壓縮檔像目錄一樣運作,還是有一些基於 Node API 低階本質的限制存在。
壓縮檔都是唯讀的
所有壓縮檔都無法被修改,因此所有可以修改檔案的 Node API 都無法與 asar
壓縮檔一起運作。
使用中的目錄無法被設為壓縮檔中的目錄
儘管 asar
壓縮檔被視為目錄,卻並沒有真正的目錄在檔案系統中,所以你永遠無法將使用中的目錄設定成 asar
壓縮檔中的目錄,把他們以 cwd
選項的方式傳遞,對某些 API 也會造成錯誤。
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 byrequire
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 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.