electron-forge透過Squirrel.Windows打包導致的asar檔案過大的解決方案

星小梦發表於2024-08-17

環境

我的Eectron環境如下:

"@electron-forge/cli": "^7.1.0",
"@electron-forge/maker-deb": "^7.1.0",
"@electron-forge/maker-rpm": "^7.1.0",
"@electron-forge/maker-squirrel": "^7.1.0",
"@electron-forge/maker-zip": "^7.1.0",
"@electron-forge/plugin-auto-unpack-natives": "^7.1.0",
"@electron-forge/plugin-vite": "^7.1.0",
"@electron/packager": "^18.3.3",
"@electron/rebuild": "^3.3.0",
"@vitejs/plugin-vue": "3.1.0",
"electron": "^27.1.0",

問題如下

  1. 如果你打包後的asar檔案包含了專案的整個原始碼?方法如下
    你可以使用asar extract app.asar <輸入目錄>命令提取出asar檔案包含的內容,從而分析asar是否包含了不需要包含的檔案。
    如果包含了專案不需要打包進asar的檔案,我們需要設定forge.config.js檔案的內容,需要配置ignore屬性的內容資訊,關於ignore屬性的使用說明在這裡可以看到: https://electron.github.io/packager/main/interfaces/Options.html#ignore
    我的forge.config.js如下配置內容,僅供參考:
module.exports = {
  packagerConfig: {
    asar: true,
    ignore:['/.idea', /^\/logs$/, /^\/deps$/, /^\/extensions$/, /^\/src$/ ,/^\/.device-config$/, /^\/.gitignore$/, /^\/package-lock.json$/, /^[/\\]vite\.\w+\.config\.js$/],
    ...其他配置
  },
  ...其他配置
}

上邊的ignore解析方式是如果當前目錄被忽略了,當前目錄的子內容就也會被忽略到。
起始路徑是以forge.config.js檔案所在的目錄開始,要忽略的檔案和目錄以相對的目錄進行定義就行。

  1. 設定不需要打包進asar的檔案和目錄的方式?方法如下
    這裡我們就需要使用packagerConfig.extraResource屬性了,這個屬性會將配置的目錄或檔案路徑,不打包進asar檔案中,但是將其放在/resources目錄下。/resources目錄是在你打包構建成exe後可見,
    但是在未構建的情況下,也能獲取到/resources目錄的位置,這個位置就會是node_modules/electron目錄下的/resources目錄。
    我們可以透過process.resourcesPath屬性來獲取。
    這邊建議的方式是使用process.cwd()來自行構建生產和開發時的環境配置,以防指定的資源路徑不一樣導致的訪問不到的問題。
    這是我的pathutils的程式碼,僅供參考:
export function getAppPath() {
    if(process.env.NODE_ENV === "development"){
        const targetPath = path.join(process.cwd(), 'out', 'app');
        if(!fs.existsSync(targetPath)){
            fs.mkdirSync(targetPath, { recursive: true })
        }
        return path.join(process.cwd(), 'out', 'temp-root')
    }else if(process.env.NODE_ENV === "production"){
        return process.cwd();
    }else{
        console.error("未知的Node環境", process.env.NODE_ENV)
        return null;
    }
}


export function getAppResourcePath(devPaths, prodPaths){
    return path.join(getAppPath(),
        process.env.NODE_ENV === "development" ? devPaths : "",
        process.env.NODE_ENV === "production" ? prodPaths : "",
    )
}
  1. process.env.NODE_ENV在構建打包成exe檔案後,透過exe執行時獲取到的process.env.NODE_ENV環境變數的值是undefined問題
    這裡我們需要藉助app.isPackaged屬性進行自己賦值環境變數的值。
    我們可以在main.js的執行內容的最上方新增以下程式碼即可。
if (app.isPackaged) {
    process.env.NODE_ENV = 'production'
}

屬性的說明:
app.isPackaged 只讀 返回一個boolean值,如果應用已經打包,返回true ,否則返回false 。 對於大多數應用程式,此屬性可用於區分開發和生產環境。

electron packager打包後process.env.NODE_ENV為undefined,可在這篇issue獲取到有關資訊

  1. 這裡說明下electron-packager,關於ignore和asar檔案的配置引數的使用說明
    ignore可以理解為是否要包含進asar檔案的屬性,如果這個屬性指定的內容匹配上了,
    那麼將不會出現在asar的檔案中。
    asar.unpackasar.unpackDir是對於將要打包進asar中的檔案內容,進行不同的行為操作,一個是針對檔案的,一個是針對目錄的。
    asar.unpack:所有與提供的 glob 表示式相匹配的檔案都會被解壓到 app.asar.unpacked 目錄下,並且這些檔案不會被打包進 ASAR 檔案中。
    asar.unpackdir: 與該屬性值匹配的所有目錄及其內容都將被解壓到 app.asar.unpacked 目錄下。這意味著這些目錄不會被包含在 ASAR 檔案內。

動態生成的檔案或者需要頻繁寫入的日誌檔案通常會使用 unpack 或 unpackDir 來確保它們不被包含在 ASAR 存檔中。

有關asar支援的命令列命令

其他參考資料

Electron 應用程式打包體積過大常用的最佳化方法
electron ASAR Archives
github package volume size to large
The packaged file volume is too large and contains nodes_ modules electron-forge package (--template=vite)
Undocumented breaking change for Vite plugin in v7.3.0

vite plugin v7.3.0版本以上的版本,進行了一次大的變更,配置xxx.main.config.js等檔案的方式進行了改變。
electron-forge對於vite-plugins的使用說明在當前時間並未進行更新。

feat: adds default fuses to templates

關於模板的初始預設配置的commit說明

vite template can not generate asar
packagerConfig in ForgeConfig ignores afterComplete hook functions

關於在packagerConfig中的配置afterComplete後,遇到構建程序掛起的問題。是因為執行完成後,別忘呼叫callback回撥方法。

我當時以為是錯誤的回撥方法,原來是執行完成的執行方法,不執行callback就會一直掛起構建的程序。

最後一個是關於我當時提交的issue,有關asar打包檔案大的問題

相關文章