1. 程式人生 > 實用技巧 >nodejs打包成桌面程式(exe)的進階之路

nodejs打包成桌面程式(exe)的進階之路

nodejs打包成桌面程式(exe)的進階之路

node js bat 前端 計劃任務

前言:最近的研究,請大佬們細品

第一篇 - 任務計劃程式篇

說真的研究到將nodejs打包成可執行的exe檔案是個意外的方向。

剛開始我的需求就是想要在電腦開機時自啟動nodejs的專案;因為自己目前是搞前端開發的,而nodejs現在對於前端來說還是很火的,我們也會經常接觸到它,比如webpack、Vue、React等都要用到nodejs進行編譯,轉換成瀏覽器可識別的檔案,在這裡nodejs扮演的是一個工具人的角色,給它們提供一個編譯的環境。

那麼nodejs可以做一個網站的服務麼,這是肯定的,它有著如express等框架提供一個快速服務開發,讓它像php、java一樣提供一個API,但是到這裡又遇到了一個問題,我自己用nodejs開發了一個自己的工作系統,在自己的電腦跑,如果是linux的話,可以用pm2等守護程序工具,但是在window用這個工具,親測過它佔用的記憶體會越來越大,然後有說用nssm將nodejs註冊成服務,親測可以,但是呢我工作中要用到mockjs進行資料模擬,我將這一個也整合到了我的工作系統中,那麼這時候,如果我修改了一下模擬系統的程式碼,就要手動重啟這個服務了???,那麼這個註冊成服務對於我所需要的場景就有點廢了。

既然上面提到的被否定了,那麼我又想了其他方法。之前我也仔細研究過window系統,從封裝到重灌,哈哈哈,所以我想到了一個和系統服務差不多的——任務計劃程式,設定一個任務計劃程式,讓它在電腦登入的時候啟動服務那麼可行嗎。

那麼現在我就採用任務計劃程式這一條方案,這個呢需要自己寫一個bat檔案,呼叫nodemon啟動專案。

nodemon與node啟動對比,nodemon會監聽專案的程式碼修改,如果有修改則自動重啟

@echo off
echo.
echo 光之旅star
echo.

color 0a

set AutoPath=%~dp0
%AutoPath:~0,2%
pushd %AutoPath%

cd /d %AutoPath%

cd ../server

nodemon bin/www

pause

上面就是我啟動服務所用的server.bat檔案

  • color 0a :設定cmd視窗顏色

  • set AutoPath=%~dp0 :將當前檔案所在的目錄賦值給一個變數

  • cd ../server :找到專案的根目錄

  • nodemon bin/www :用nodemon啟動服務(專案用的是Express 應用程式生成器建立的:express-generator )

然後將這個bat檔案新增到任務計劃程式中

這樣儲存後,重新啟動電腦登入,就會自動呼叫這個bat檔案啟動服務

本來到這裡就完了,完美的實現了我的需求,但是呢。。。。。。

這樣就會出現一個cmd視窗,如果關閉了cmd視窗,服務就會停止,嗯,這是正常的情況,我們常常要用到nodejs的時候也是有這個視窗的,但是呢。。。。。。

這個視窗一直在工作列佔著一個位置,強迫症讓我想要關掉它,這可以實現麼,所以就來到了我們的第二篇研究中,請看第二篇。。。。。。

第二篇 - cmd打包成exe篇

如何在啟動服務的時候不顯示cmd視窗呢,之前我有用VBScript寫過一些指令碼程式,這個呢可以不顯示cmd視窗在後臺執行,那我這次是要用這個麼,當然不是,為什麼呢

VBScript寫的指令碼程式相信有些人有用過,就是字尾為.vbs的可執行檔案,但是有些病毒正是利用這個特點寫了一些病毒指令碼,比如在U盤插進電腦的時候就觸發執行,導致電腦中毒的情況,最經典的就是 U盤檔案變成快捷方式 的病毒,想要了解的可以看我另外一個博文,這裡就不贅述,執行這個字尾的程式是window自帶的wscript.exe檔案,所以我把它刪除了。

那麼我要用什麼呢,在這裡我需要藉助一個工具(cmd to exe converter),這個工具可以將bat檔案打包成exe,並且可以設定該打包的檔案隱身執行,那麼這樣就達到了我所需要的在後臺執行的需求,下面看操作

將之前的bat檔案用cmd to exe converter 開啟,如圖進行相關設定,然後點選選單欄的轉換即可打包出exe檔案

然後將exe檔案參照第一篇在 任務計劃程式 中使用

bat檔案如果是ANSI格式的,引入到cmd to exe converter 中,中文可能亂碼,因為cmd to exe converter 預設是UTF8編碼

cmd視窗預設不解析UTF8編碼的中文,可以在bat檔案中新增程式碼讓cmd視窗解析UTF8編碼

chcp 65001

上面我們生成了exe檔案,並且點選exe檔案會在後臺啟動服務,但是我們多點選幾下exe檔案,在工作管理員中我們可以看到會同時啟動好多這個檔案,並不是只允許當前點選的這個檔案,那麼這並不是我們需要的,這個怎麼解決呢

看上面的程式碼,我們可以再建立一個bat檔案,我將它命名為start.bat。

裡面先關掉之前的程序,再去呼叫,這樣就保證了每次都只存在一個例項

taskkill /f /t /im cgServer.exe
start cgServer.exe

在這一篇中,我們所講的是將cmd打包成exe檔案,解決了我希望啟動的程式在後臺執行的情況,但並沒有將我的專案也打包成exe,這和標題有些不符合,那麼接下來要怎麼做呢,請看下一篇

第三篇 - nodejs打包成exe

我在思考,cmd可以打包成exe,那麼用nodejs做的專案可以打包成exe嗎,打包成exe後就可以將專案發給別人看,且不需要安裝node環境

首先想到的是 Electron ,它是目前使用 JavaScript,HTML 和 CSS 構建跨平臺的桌面應用程式最常用的解決方案,但是要用它的話,就要遵循它的規範,說不定還要重構我的程式,且學習起來還是需要一些成本在裡面的,基於這些情況,我把它拋棄了。

那麼還有什麼解決方案呢,這時候一個pkg的node包映入了我的眼簾,它的作用就是 打包node為可執行檔案(.exe)的工具 ,接下來我們直接用

npm install -g pkg
pkg server.js
pkg -t win server.js
  • npm install -g pkg :全域性安裝pkg

  • pkg server.js : 將 api.js 編譯成 api.exe 可執行檔案

  • pkg -t win server.js : 上面的命令會同時編譯出 linux 、windows 、mac 版的 exe,加 -t win 就可以只編譯 windows 下的

//server.js
//用express做的簡單服務

const express = require("express");

const app = express();

const path = require("path");

app.use(express.static(path.join(__dirname, "dist"))); //注意這裡使用path.join(__dirname, 'dist')而不是'dist',雖然在命令列中執行起來效果是一樣的,不過pkg打包會無法識別到dist目錄

var server = app.listen(8081, function () {
var host = server.address().address;

var port = server.address().port;

console.log(`AIbuy agents server start successfully on http://${host}:${port}`);
});

編譯完成後,會生成server.exe檔案,雙擊該檔案,瀏覽器訪問http://localhost:8081即可

注意在編譯的過程中(pkg -t win server.js)可能會出現報錯的情況,如下

> pkg@4.3.0
> Fetching base Node.js binaries to PKG_CACHE_PATH
fetched-v12.18.1-win-x64 [ ] 0%
> Error! connect ETIMEDOUT 13.229.188.59:443
> Asset not found by direct link:
{"tag":"v2.6","name":"uploaded-v2.6-node-v12.18.1-win-x64"}

這是因為編譯的時候要從github下載uploaded-v2.6-node-v12.18.1-win-x64包,由於下載不了導致的,

這時我們可以先去github下載到這個包,放到當前使用者下,如C:\Users\cheng\.pkg-cache\v2.6

,讓包的名字改為 fetched-v12.18.1-win-x64 ,再次執行編譯即可。

要下載什麼版本的包看自己的報錯需要什麼版本。

github地址:https://github.com/vercel/pkg-fetch/releases

正常下載網速很慢,推薦使用 IDM 進行下載

注:pkg除了根據檔名打包,還可以根據package.json檔案打包,要注意的是專案中引用檔案的方式,pkg只會打包使用 require 或者 通過 __filename__dirname 的檔案

這一篇我們講了將nodejs打包成exe,但是不知道你們有沒有注意到,我們上面的操作都只是為了啟動nodejs的服務,但是要訪問的話,還是需要在瀏覽器中訪問,那麼如果程式碼中用了es6的語法,是不是還要帶個谷歌瀏覽器讓其他要訪問你頁面的人安裝呢,這是一個值得思考的問題,我們繼續看下一篇

第四篇 - 加個瀏覽器的殼

上面我們提到站點訪問的問題,可能會說的比較極端,但是確實也是我當時在考慮的問題,那麼這個要怎麼解決呢。

這次就不賣關子了,直接使用npm的easy-window包

地址:https://gitee.com/zha2/easy-window

可以直接下載,或者使用git克隆下來

裡面有一些案例感興趣的可以看看

我們所需要的是裡面的 easy-window.exe 檔案,將該檔案拷貝到第二篇或者第三篇檔案所在的目錄中,比如我們用第二篇的目錄為例,建立一個bat檔案,內容如下

start easy-window.exe -url http://localhost:3000/ -title "管理系統" -maxbox true -topmost true
  • -url :要用的url地址

  • -title :標題

  • -maxbox :允許視窗最大化

  • -topmost :將視窗置頂

執行後就可以彈出一個的視窗,我們上面輸入的地址內容就在這個窗口裡面執行,這就像是給我們的專案加了一個殼,讓我們專案在我們給定的殼裡執行,這個殼是一個精簡版的瀏覽器

需要注意的是easy-window裡面執行傳統的網頁沒問題,但是執行單頁應用就會出問題。

easy-window各種引數

結尾

到此我的 nodejs打包成桌面程式(exe)的進階之路 就算是一個摸索的結點,上面提到的都不用怎麼去學新的技術,而是將多種工具組合靈活使用。

如果需要繼續進階,可以考慮學習Electron、PyQt(用python寫Qt)等桌面應用相關的知識。