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 //${host}:${port}`);
});

編譯完成後,會生成server.exe文件,雙擊該文件,瀏覽器訪問//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地址://github.com/vercel/pkg-fetch/releases

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

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

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

 

第四篇 – 加個瀏覽器的殼

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

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

地址://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)等桌面應用相關的知識。