如何用Web前端技術(shù)就能開發(fā)出桌面應(yīng)用程序?
Web前端技術(shù)開發(fā)桌面應(yīng)用的方式
CEF:用 Chromium&Webkit 來呈現(xiàn) web 頁面毛甲,是客戶端里面嵌瀏覽器,瀏覽器里面跑網(wǎng)頁锉试。
heX:基于CEF,內(nèi)部整合了開源項目 Chromium 及 node.js览濒。
nw:基于Chromium 和 node.js呆盖,利用 web 方式開發(fā)跨平臺桌面應(yīng)用的平臺技術(shù)。
electron:底層也是基于Chromium 和 node.js贷笛。
等等应又。。乏苦。
案例實操~electron
electron 是 github 開發(fā)的株扛,用來開發(fā)桌面應(yīng)用的一款前端框架
開發(fā)環(huán)境
安裝 node.js
為了避免網(wǎng)絡(luò)問題對 Node 工作時的影響,我們安裝國內(nèi)的 node 鏡像 cnpm汇荐。
npm install -g cnpm --registry=https://registry.npm.taobao.org
安裝 electron
npm install --save-dev electron
或者全局安裝
npm install -g electron
開發(fā)工具
其實 vscode 就是 electron 開發(fā)的
開發(fā)一個簡易的 electron
Electron 應(yīng)用使用 JavaScript 開發(fā)洞就,其工作原理和方法與 Node.js 開發(fā)相同。 electron
模塊包含了 Electron 提供的所有 API 和功能拢驾,引入方法和普通 Node.js 模塊一樣:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="javascript" contenteditable="false" cid="n37" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">const electron = require('electron')</pre>
electron
模塊所提供的功能都是通過命名空間暴露出來的奖磁。 比如說: electron.app
負責(zé)管理 Electron 應(yīng)用程序的生命周期改基, electron.BrowserWindow
類負責(zé)創(chuàng)建窗口繁疤。下面是一個簡單的main.js
文件咖为,它將在應(yīng)用程序準備就緒后打開一個窗口:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="javascript" contenteditable="false" cid="n40" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">const { app, BrowserWindow } = require('electron')
?
function createWindow () {
// 創(chuàng)建瀏覽器窗口
let win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
?
// 加載index.html文件
win.loadFile('index.html')
}
?
app.whenReady().then(createWindow)</pre>
創(chuàng)建你想展示的 index.html
:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" contenteditable="false" cid="n42" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html></pre>
啟動
我們在package.json
中已經(jīng)寫好了啟動命令,所以這里直接用 node 啟動命令npm start
就可以了稠腊,如果沒有配躁染,也可以用electron .
命令啟動。
主進程和渲染進程
我們可以理解package.json
中定義的入口文件就是主進程架忌,那一般一個程序只有一個主進程吞彤,而我們可以利用一個主進程,打開多個子窗口叹放。
由于 Electron 使用了 Chromium 來展示 web 頁面饰恕,所以 Chromium 的多進程架構(gòu)也被使用到。每個 Electron 中的 web 頁面運行在它自己的渲染進程中井仰,也就是我們說的渲染進程埋嵌。
也就是說主進程控制渲染進程,一個主進程可以控制多個渲染進程俱恶。
您應(yīng)當(dāng)在 main.js
中創(chuàng)建窗口雹嗦,并處理程序中可能遇到的所有系統(tǒng)事件。下面我們將完善上述例子合是,添加以下功能:打開開發(fā)者工具了罪、處理窗口關(guān)閉事件、在 macOS 用戶點擊 dock 上圖標時重建窗口聪全,添加后泊藕,main. js 就像下面這樣:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="javascript" contenteditable="false" cid="n54" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">const { app, BrowserWindow } = require('electron')
?
function createWindow () {
// 創(chuàng)建瀏覽器窗口
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
?
// 并且為你的應(yīng)用加載index.html
win.loadFile('index.html')
?
// 打開開發(fā)者工具
win.webContents.openDevTools()
}
?
app.whenReady().then(createWindow)
?
// 當(dāng)所有窗口都關(guān)閉時觸發(fā)此事件.
app.on('window-all-closed', () => {
// 在 macOS 上,除非用戶用 Cmd + Q 確定地退出荔烧,
// 否則絕大部分應(yīng)用及其菜單欄會保持激活吱七。
if (process.platform !== 'darwin') {
app.quit()
}
})
?
app.on('activate', () => {
// 在macOS上,當(dāng)單擊dock圖標并且沒有其他窗口打開時鹤竭,
// 通常在應(yīng)用程序中重新創(chuàng)建一個窗口踊餐。
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
?
// In this file you can include the rest of your app's specific main process
// code. 也可以拆分成幾個文件,然后用 require 導(dǎo)入臀稚。
?</pre>
git 上面的 demo 示例
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="shell" contenteditable="false" cid="n57" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 克隆這倉庫
git clone https://github.com/electron/electron-quick-start
進入倉庫
cd electron-quick-start
安裝依賴庫
npm install
運行應(yīng)用
npm start</pre>
electron-forge 構(gòu)建項目
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="shell" contenteditable="false" cid="n60" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># 全局安裝electron-forge
npm install electron-forge -g
?
用electron-forge初始化一個項目
electron-forge init demo02
?
進入到項目目錄
cd demo02
?
啟動項目
npm start</pre>
擴展~開發(fā)桌面百度
主進程代碼
我們創(chuàng)建了主進程對象 win 后吝岭,讓它直接加載百度的地址。
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" contenteditable="false" cid="n65" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">const { app, BrowserWindow } = require('electron')
?
function createWindow () {
// 創(chuàng)建瀏覽器窗口
let win = new BrowserWindow({
width: 800,
height: 800,
webPreferences: {
nodeIntegration: true
}
})
?
// 加載index.html文件
// win.loadFile('index.html')
win.loadURL("http://www.baidu.com")
}
?
app.whenReady().then(createWindow)</pre>
打包發(fā)布
我們希望使用electron-packager
對應(yīng)用進行打包發(fā)布吧寺,electron-packager
的安裝方式如下:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="shell" contenteditable="false" cid="n68" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(255, 255, 255); position: relative !important; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">#下載electron-packager打包插件
npm install electron-packager -g
開始打包
electron-packager ./ demo01 --win --out ./ --arch=x64 --app-version=0.0.1 --electron-version=8.2.5</pre>
我們還可以進一步打包成可執(zhí)行文件