electron/docs-translations/zh-TW/tutorial/application-packaging.md

5.7 KiB
Raw Blame History

應用程式打包

為了減少圍繞著 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 中有兩組 APINode.js 提供的 Node APIs 和 Chromium 提供的 Web APIs兩組 API 都支援從 asar 壓縮檔中讀取檔案。

Node API

因為 Electron 中有一些特別的補釘,像是 fs.readFilerequire 這樣的 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');

你也可以利用 BrowserWindowasar 壓縮檔中呈現一個網頁:

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 APIasar 壓縮檔都被視為目錄。

例如,要透過 $.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.noAsartrue 來關掉在 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 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 commands 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.