
簡介這份資源面向希望把本地HTML網(wǎng)頁封裝成Windows桌面程序的開發(fā)者尤其適合剛接觸Electron、需要快速產(chǎn)出可交付exe的初中級前端或全棧人員。內(nèi)容圍繞Electron框架展開覆蓋HTML/CSS/JS資源打包、BrowserWindow全屏顯示、隱藏任務欄、監(jiān)聽Esc鍵退出以及通過electron-packager或electron-builder自定義exe圖標與文件名等關鍵環(huán)節(jié)并涉及版本管理、錯誤處理與跨平臺測試思路。壓縮包共約2000個文件以js、ts、map、json、md、license等源碼與依賴文件為主另有pak、dll、exe等運行時資源整體約95.61MB目錄結構完整便于直接運行與二次修改。目前已有1161人學習下載可作為從網(wǎng)頁到桌面應用落地的參考工程幫助讀者理解主進程與渲染進程通信、打包參數(shù)配置及常見排錯路徑。1. 從網(wǎng)頁到桌面程序為什么我選 Electron 做 HTML 打包手里有一個寫好的 HTML 頁面可能是數(shù)據(jù)看板、可能是觸屏查詢機界面、也可能是內(nèi)部培訓課件現(xiàn)在需要把它變成一個雙擊就能打開的 exe還要全屏、蓋住任務欄、按 Esc 退出、圖標和文件名都得換成自己的。這種需求在展廳大屏、工廠工位機、學校機房這類場景里特別常見——瀏覽器一開地址欄就露出來用戶隨手就能關掉或者跳走體驗完全不可控。Electron 就是干這個的它把 Chromium 和 Node.js 打包進一個可執(zhí)行文件你的 HTML 跑在里面就像一個獨立桌面程序。相比直接讓用戶開瀏覽器訪問Electron 方案能控制窗口尺寸、隱藏菜單欄、攔截鍵盤事件、自定義圖標還能在需要的時候調用本地文件系統(tǒng)。這篇就按「能干什么 → 怎么跑起來 → 怎么改」的順序把整個打包流程拆一遍包括全屏遮任務欄、Esc 退出、圖標和文件名替換這些具體操作。2. 環(huán)境搭建與項目骨架從零到能跑的第一個窗口2.1 安裝 Node.js 與初始化項目Electron 本身就是一個 npm 包所以第一步是把 Node.js 裝好。去 Node.js 官網(wǎng)下載 LTS 版本安裝時勾選「Add to PATH」裝完在命令行里驗證node -v npm -v兩條命令都能輸出版本號就說明環(huán)境沒問題。接下來建一個空文件夾作為項目根目錄比如叫html-to-exe進去之后初始化mkdir html-to-exe cd html-to-exe npm init -ynpm init -y會生成一個默認的package.json里面記錄了項目名、版本、入口文件等信息。這個文件后面要改因為 Electron 的入口不是默認的index.js而是我們指定的主進程文件。2.2 安裝 Electron 并理解它的依賴結構安裝 Electron 用一條命令npm install electron --save-dev這里用--save-dev是因為 Electron 只是開發(fā)期和打包期的工具最終產(chǎn)物是打包好的 exe不需要用戶再裝 Electron。安裝過程會下載一個幾百 MB 的 Chromium 二進制包國內(nèi)網(wǎng)絡環(huán)境下可能會慢常見做法是配置 npm 鏡像源npm config set registry https://registry.npmmirror.com裝完之后node_modules里會出現(xiàn)electron目錄里面包含可執(zhí)行文件。package.json的devDependencies里會多出一行electron: ^版本號。2.3 項目目錄結構與主進程入口一個最小可用的 Electron 項目結構是這樣的html-to-exe/ ├── package.json ├── main.js # 主進程入口 ├── preload.js # 預加載腳本可選 └── src/ └── index.html # 你的網(wǎng)頁main.js是主進程負責創(chuàng)建窗口、控制窗口行為src/index.html就是你要展示的網(wǎng)頁。package.json里要把main字段指向main.js{ name: html-to-exe, version: 1.0.0, main: main.js, scripts: { start: electron . } }改完之后運行npm start如果一切正常會彈出一個默認的 Electron 窗口。這一步先確認環(huán)境通了再往下做全屏和退出邏輯。3. 核心功能實現(xiàn)全屏、遮任務欄、Esc 退出與圖標替換3.1 創(chuàng)建全屏窗口并遮住任務欄Electron 創(chuàng)建窗口用BrowserWindow全屏和遮任務欄的關鍵在構造參數(shù)。下面是一個完整的主進程代碼const { app, BrowserWindow, globalShortcut } require(electron); const path require(path); let mainWindow null; function createWindow() { mainWindow new BrowserWindow({ width: 1920, height: 1080, fullscreen: true, // 全屏 frame: false, // 去掉標題欄和邊框 kiosk: true, // kiosk 模式強制全屏并遮任務欄 alwaysOnTop: true, // 置頂防止被其他窗口蓋住 skipTaskbar: true, // 不在任務欄顯示 icon: path.join(__dirname, build/icon.ico), // 窗口圖標 webPreferences: { preload: path.join(__dirname, preload.js), contextIsolation: true, nodeIntegration: false } }); mainWindow.loadFile(path.join(__dirname, src/index.html)); // 按 Esc 退出 mainWindow.webContents.on(before-input-event, (event, input) { if (input.key Escape input.type keyDown) { app.quit(); } }); } app.whenReady().then(() { createWindow(); app.on(activate, () { if (BrowserWindow.getAllWindows().length 0) createWindow(); }); }); app.on(window-all-closed, () { app.quit(); });逐段說明fullscreen: true讓窗口占滿屏幕但某些系統(tǒng)下任務欄仍可能彈出。kiosk: true是更徹底的全屏模式它會強制窗口覆蓋整個屏幕并阻止用戶退出任務欄被完全遮住。這是展廳、工位機場景最常用的配置。frame: false去掉系統(tǒng)自帶的標題欄和關閉按鈕防止用戶點 X 關掉。alwaysOnTop: true保證窗口不會被其他程序蓋住適合需要長期展示的場景。skipTaskbar: true讓程序不在任務欄顯示圖標進一步減少用戶誤操作的可能。icon指定窗口左上角圖標Windows 下用.ico格式macOS 用.icnsLinux 用.png。before-input-event是攔截鍵盤輸入的關鍵。這里監(jiān)聽Escape鍵的keyDown事件觸發(fā)app.quit()退出程序。注意要判斷input.type keyDown否則按鍵抬起時也會觸發(fā)一次。提示如果kiosk: true導致調試時無法退出可以在開發(fā)階段先注釋掉這行等打包前再打開。3.2 修改 exe 圖標和文件名開發(fā)階段窗口圖標已經(jīng)通過icon參數(shù)設置了但最終 exe 文件的圖標和文件名需要在打包時指定。打包用electron-builder先安裝npm install electron-builder --save-dev然后在package.json里加build配置{ build: { appId: com.example.htmltoexe, productName: MyApp, directories: { output: dist }, win: { target: nsis, icon: build/icon.ico }, nsis: { oneClick: false, allowToChangeInstallationDirectory: true, createDesktopShortcut: true, shortcutName: MyApp } } }參數(shù)說明productName決定最終 exe 的文件名比如設為MyApp產(chǎn)物就是MyApp Setup 1.0.0.exe和安裝后的MyApp.exe。win.icon指定 exe 圖標必須是 256x256 的.ico文件否則打包會報錯。nsis.oneClick設為false會生成帶安裝向導的安裝包用戶可以選擇安裝路徑設為true則是一鍵安裝。shortcutName是桌面快捷方式的名字。圖標文件放在項目根目錄的build文件夾下命名為icon.ico。如果沒有現(xiàn)成的 ico可以用在線工具把 png 轉成 ico注意尺寸要包含 256x256。3.3 打包命令與產(chǎn)物驗證在package.json的scripts里加一條打包命令{ scripts: { start: electron ., build: electron-builder --win } }運行npm run build打包完成后dist目錄下會出現(xiàn)安裝包和免安裝的win-unpacked文件夾。雙擊win-unpacked里的 exe 驗證是否全屏、任務欄是否被遮住、按 Esc 是否退出、圖標和文件名是否正確。如果圖標沒變檢查 ico 文件是否包含 256x256 尺寸如果任務欄沒遮住確認kiosk: true是否生效。4. 避坑與常見問題排查4.1 打包后白屏或頁面加載失敗現(xiàn)象開發(fā)時npm start正常打包后打開 exe 是白屏。原因loadFile的路徑用了相對路徑打包后文件結構變了找不到 HTML。解決統(tǒng)一用path.join(__dirname, src/index.html)這種基于__dirname的絕對路徑。如果 HTML 里引用了 CSS、JS、圖片也要用相對路徑并且確保這些文件被包含在打包產(chǎn)物里。electron-builder默認會打包項目根目錄下除node_modules開發(fā)依賴外的所有文件但最好在build.files里顯式聲明{ build: { files: [ main.js, preload.js, src/**/* ] } }4.2 Esc 退出不生效現(xiàn)象按 Esc 沒反應程序不退出。原因焦點不在webContents上或者事件被頁面里的 JavaScript 攔截了。解決before-input-event是掛在webContents上的只要窗口有焦點就能觸發(fā)。如果頁面里有輸入框或者某些庫監(jiān)聽了鍵盤事件并preventDefault可能會影響。可以在頁面里也加一個監(jiān)聽作為兜底document.addEventListener(keydown, (e) { if (e.key Escape) { window.close(); } });但window.close()在 Electron 里默認只能關閉由腳本打開的窗口所以更穩(wěn)妥的做法是通過 preload 暴露一個退出方法或者直接用主進程的before-input-event。4.3 任務欄遮不住現(xiàn)象fullscreen: true了但鼠標移到屏幕底部任務欄還是彈出來。原因Windows 的任務欄在某些情況下會覆蓋全屏窗口尤其是窗口沒有置頂時。解決加上kiosk: true和alwaysOnTop: true。kiosk模式是專門為這種場景設計的它會阻止任務欄彈出。如果還不行檢查是否有多顯示器窗口可能創(chuàng)建在了副屏上。4.4 圖標不生效現(xiàn)象打包后 exe 圖標還是默認的 Electron 圖標。原因ico 文件尺寸不對或者路徑配置錯誤。解決確認build/icon.ico存在且包含 256x256 尺寸。electron-builder對 ico 文件要求比較嚴格建議用專業(yè)工具生成。另外win.icon的路徑是相對于項目根目錄的不要寫成絕對路徑。4.5 安裝包體積過大現(xiàn)象打包出來的安裝包幾百 MB。原因Electron 本身包含 Chromium 和 Node.js體積天然就大。解決這是 Electron 的固有特性無法根本解決??梢酝ㄟ^electron-builder的asar壓縮、排除不必要的文件來減小一些體積但預期管理要做好——Electron 應用的安裝包通常在 50MB 到 150MB 之間。5. 二次開發(fā)與改造思路從能跑到好用5.1 把網(wǎng)頁內(nèi)容做成可配置如果這個 exe 要給多個場景用每次改 HTML 都要重新打包就很麻煩。常見做法是把 HTML 內(nèi)容外置程序啟動時讀取同目錄下的config.json或者直接加載外部 HTML 文件const fs require(fs); const configPath path.join(path.dirname(app.getPath(exe)), config.json); let targetUrl src/index.html; if (fs.existsSync(configPath)) { const config JSON.parse(fs.readFileSync(configPath, utf-8)); targetUrl config.url || targetUrl; } mainWindow.loadFile(targetUrl);這樣運維人員只需要改config.json里的地址不用重新打包。如果加載的是遠程 URL把loadFile換成loadURL即可。5.2 增加退出密碼或組合鍵Esc 直接退出在生產(chǎn)環(huán)境可能太隨意可以改成組合鍵比如CtrlShiftQmainWindow.webContents.on(before-input-event, (event, input) { if (input.control input.shift input.key.toLowerCase() q) { app.quit(); } });或者彈一個密碼框驗證通過才退出。這樣既能防止誤觸又保留了維護通道。5.3 禁用右鍵菜單和開發(fā)者工具展廳場景不希望用戶右鍵或者按 F12 打開開發(fā)者工具可以在主進程里禁用mainWindow.webContents.on(context-menu, (e) { e.preventDefault(); }); globalShortcut.register(CommandOrControlShiftI, () { return false; });context-menu事件攔截右鍵菜單globalShortcut攔截開發(fā)者工具快捷鍵。注意globalShortcut要在app.whenReady()之后注冊。5.4 自動更新與版本管理如果程序部署在多臺機器上手動更新很痛苦。electron-builder配合electron-updater可以實現(xiàn)自動更新?;舅悸肥窃趐ackage.json里配置publish地址主進程里監(jiān)聽更新事件const { autoUpdater } require(electron-updater); app.whenReady().then(() { autoUpdater.checkForUpdatesAndNotify(); });自動更新需要有一個文件服務器或者對象存儲來放安裝包和latest.yml文件。對于內(nèi)部使用的場景也可以簡單點——程序啟動時請求一個版本接口發(fā)現(xiàn)新版本就提示用戶下載。5.5 性能與內(nèi)存優(yōu)化Electron 應用的內(nèi)存占用一直是槽點。如果頁面本身不復雜可以在webPreferences里關掉一些不必要的功能webPreferences: { preload: path.join(__dirname, preload.js), contextIsolation: true, nodeIntegration: false, enableRemoteModule: false, spellcheck: false, backgroundThrottling: false }backgroundThrottling: false在需要后臺持續(xù)運行的場景下有用但會增加 CPU 占用。另外如果頁面只是靜態(tài)展示可以考慮用BrowserView或者WebContentsView替代BrowserWindow減少一層窗口管理的開銷。從那以后我每次打包前都會強制走一遍檢查清單ico 尺寸對不對、kiosk開沒開、Esc 邏輯測沒測、config.json路徑對不對。這幾步花不了五分鐘但能省掉現(xiàn)場部署時的一堆麻煩。希望幫到你。本文還有配套的精品資源點擊獲取