Windows 下支持自動更新的 Electron 應(yīng)用腳手架

前言

之前寫過一篇關(guān)于 Windows 下通過 Electron 自帶的 autoUpdater 實現(xiàn)應(yīng)用自動更新的文章诬滩,很多小伙伴私信問我要具體實現(xiàn)代碼,不過因為之前一直很忙(還有懶...)。

這兩周正好周末比較空,除了在 github 上搭建了一個腳手架,還順便把實現(xiàn)優(yōu)化了一波球凰,下面將會帶著大家從零開始詳細(xì)介紹實現(xiàn)過程狮腿,對小白也很友好的教程哦腿宰。

從零開始

進(jìn)入你的工作目錄,比如 d/workspace

# 目錄 d/workspace
mkdir electron-demo # 新建文件夾 electron-demo
cd electron-demo # 進(jìn)入文件夾 electron-demo
npm init # 初始化 npm缘厢,一路回車即可
npm i electron --save-dev # 安裝 electron 依賴
touch main.js # 新建文件 main.js
touch index.html # 新建文件 index.html

現(xiàn)在你的文件結(jié)構(gòu)如下:

|- electron-demo
  |- main.js # 空文件
  |- index.html # 空文件
  |- package.json
  |- package-lock.json # npm 自動生成的文件
  |- node_modules

確保 package.json 的name吃度,version,description這三個字段都不為空贴硫,main 字段的取值為 main.js 椿每。

{
  "name": "electron-demo",
  "version": "0.0.1",
  "description": "electron-demo",
  "main": "main.js"
}

主進(jìn)程和渲染進(jìn)程

Electron 應(yīng)用分為主進(jìn)程和渲染進(jìn)程。渲染進(jìn)程是直接與用戶產(chǎn)生交互的進(jìn)程英遭,也就是我們看到的一個個窗口頁面间护,而主進(jìn)程主要負(fù)責(zé)控制應(yīng)用的生命周期,負(fù)責(zé)各個渲染進(jìn)程的通信等挖诸。

我們的主進(jìn)程代碼寫在 main.js 中汁尺,所以首先在你心愛的代碼編輯中打開 main.js,輸入如下代碼:

const path = require('path');
const url = require('url');
const {
    app,
    BrowserWindow
} = require('electron');

app.on('ready', () => {
    let win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            devTools: true
        }
    });

    win.loadURL(
        url.format({
            pathname: path.join(__dirname, 'index.html'),
            protocol: 'file:',
            slashes: true
        })
    );
});

app.on('window-all-closed', () => app.quit());

再打開 index.html多律,輸入如下代碼:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
</head>

<body>
    <h1>Hello World!</h1>
</body>

</html>

之后執(zhí)行

# 目錄 d/workspace/electron-demo
node_modules/.bin/electron .

不出意外的話你會看到一個彈出框痴突,像這樣:


image.png

我們也可以把 node_modules/.bin/electron . 保存成 npm 腳本搂蜓,方便以后調(diào)用。打開 package.json辽装,添加如下內(nèi)容:

  "scripts": {
    "start": "electron ."
  }

以后只需要調(diào)用 npm start 即可帮碰。

到這里,我們已經(jīng)有了一個最簡單的 Electron 應(yīng)用拾积,如果你對繼續(xù)開發(fā)應(yīng)用本身更感興趣的話殉挽,請移步 Electron 官方文檔,因為接下來我們會專注在怎么讓這個應(yīng)用實現(xiàn)自動更新殷勘。

自動更新

安裝依賴

自動更新功能的實現(xiàn)依賴 electron-builder 和 electron-updater此再,所以我們需要先安裝這兩個依賴。

# 目錄 d/workspace/electron-demo
npm i electron-builder --save-dev # 必須安裝為開發(fā)依賴玲销,否則打包會出錯
npm i electron-updater --save # 必須安裝為運(yùn)行依賴输拇,否則運(yùn)行會出錯

配置 package.json

為了配合打包 package.json 需要新增字段 build:

 "build": {
    "appId": "com.xxx.app",
    "publish": [
      {
        "provider": "generic",
        "url": "http://127.0.0.1:8080"
      }
    ]
  },

同樣為了執(zhí)行方便,我們需要添加一個 npm 腳本贤斜,打開 package.json策吠,添加如下內(nèi)容:

  "scripts": {
    "start": "electron .",
    "build": "electron-builder -w"
  }

以后只需要調(diào)用 npm run build 即可。

主進(jìn)程和渲染進(jìn)程

打開main.js瘩绒,編輯后內(nèi)容如下:

const path = require('path');
const url = require('url');
const {
    app,
    BrowserWindow,
    ipcMain 
} = require('electron');
const { autoUpdater } = require('electron-updater');
const feedUrl = `http://127.0.0.1:8080/${process.platform}`;

let webContents;

let createWindow = () => {
    let win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            devTools: true
        }
    });

    webContents = win.webContents;

    win.loadURL(
        url.format({
            pathname: path.join(__dirname, 'src/index.html'),
            protocol: 'file:',
            slashes: true
        })
    );

    webContents.openDevTools();
};

let sendUpdateMessage = (message, data) => {
    webContents.send('message', { message, data });
};

let checkForUpdates = () => {
    autoUpdater.setFeedURL(feedUrl);

    autoUpdater.on('error', function (message) {
        sendUpdateMessage('error', message)
    });
    autoUpdater.on('checking-for-update', function (message) {
        sendUpdateMessage('checking-for-update', message)
    });
    autoUpdater.on('update-available', function (message) {
        sendUpdateMessage('update-available', message)
    });
    autoUpdater.on('update-not-available', function (message) {
        sendUpdateMessage('update-not-available', message)
    });

    // 更新下載進(jìn)度事件
    autoUpdater.on('download-progress', function (progressObj) {
        sendUpdateMessage('downloadProgress', progressObj)
    })
    autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
        ipcMain.on('updateNow', (e, arg) => {
            //some code here to handle event
            autoUpdater.quitAndInstall();
        })
        sendUpdateMessage('isUpdateNow');
    });

    //執(zhí)行自動更新檢查
    autoUpdater.checkForUpdates();
};

app.on('ready', () => {
    createWindow();

    setTimeout(checkForUpdates, 1000);
});

app.on('window-all-closed', () => app.quit());

index.html:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
</head>

<body>
    <h1>Hello World!</h1>
    <script>
        const { ipcRenderer } = require('electron');

        ipcRenderer.on('message', (event, { message, data }) => {
            console.log(message, data);
            switch (message) {
                case 'isUpdateNow':
                    if (confirm('現(xiàn)在更新猴抹?')) {
                        ipcRenderer.send('updateNow');
                    }
                    break;
                default:
                    document.querySelector('h1').innerHTML = message;
                    break;
            }
        });
    </script>
</body>

</html>

打包

npm run build

第一次運(yùn)行會比較慢,運(yùn)行結(jié)束后會在當(dāng)前目錄下新增一個 dist 文件夾锁荔,dist 的目錄結(jié)構(gòu)如下:

|- dist
  |- win-unpacked
  |- electron-autoupdate-scaffold Setup.exe
  |- electron-autoupdate-scaffold Setup.exe.blockmap
  |- electron-builder-effective-config.yaml
  |- latest.yml

win-unpacked 下是可執(zhí)行文件蟀给,但是先別著急運(yùn)行,我們還缺一個后臺阳堕。

自動更新后臺

聰明的你一定注意到跋理,前面代碼中我們有一個:

const feedUrl = `http://127.0.0.1:8080/${process.platform}`;

所以我們現(xiàn)在要做的就是一個可以接受這個請求的服務(wù)。

回到你的工作目錄(d/workspace

# 目錄 d/workspace
mkdir electron-server
cd electron-server
npm init
npm i koa --save
npm i koa-static --save
touch server.js

打開 server.js恬总,輸入如下內(nèi)容:

// server.js
let Koa = require('koa');
let app = new Koa();
let path = require('path');

app.use(require('koa-static')(path.resolve(__dirname + '/packages')));

let server = app.listen(8080, () => {
    let { address, port } = server.address();

    console.log("應(yīng)用實例前普,訪問地址為 http://%s:%s", address, port);
});

將之前打包出來的 dist 目錄下的 4 個文件(除了 win-unpacked)拷貝到這邊的 packages/win32 下(新建目錄 packages/win32),之后

# 目錄 d/workspace/electron-server
npm start

到此為止壹堰,我們的自動更新服務(wù)就搭建完成了拭卿,現(xiàn)在來一波測試吧。

測試

  1. 進(jìn)入 electron-demo/dist/win-unpacked 找到可執(zhí)行文件贱纠,雙擊運(yùn)行峻厚,看到打開窗口的控制臺中依次輸出:

    checking-for-update
    update-not-available
    
  2. 進(jìn)入 electron-demo,打開 package.json谆焊,把版本號改為0.0.2惠桃,重新打包后拷貝打包文件到自動更新后臺目錄(d/workspace/electron-server/packages/win32)。

  3. 進(jìn)入 electron-demo,打開 package.json刽射,把版本號改為0.0.1军拟,重新打包后再次進(jìn)入 dist/win-unpacked 目錄,運(yùn)行 exe誓禁,看到打開窗口的控制臺中依次輸出:

    checking-for-update
    update-available
    

    并且出現(xiàn)彈窗提示「現(xiàn)在更新懈息?」。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末摹恰,一起剝皮案震驚了整個濱河市辫继,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俗慈,老刑警劉巖姑宽,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異闺阱,居然都是意外死亡炮车,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門酣溃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘦穆,“玉大人,你說我怎么就攤上這事赊豌】富颍” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵碘饼,是天一觀的道長熙兔。 經(jīng)常有香客問我,道長艾恼,這世上最難降的妖魔是什么住涉? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮蒂萎,結(jié)果婚禮上秆吵,老公的妹妹穿的比我還像新娘淮椰。我一直安慰自己五慈,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布主穗。 她就那樣靜靜地躺著泻拦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪忽媒。 梳的紋絲不亂的頭發(fā)上争拐,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音晦雨,去河邊找鬼架曹。 笑死隘冲,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绑雄。 我是一名探鬼主播展辞,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼万牺!你這毒婦竟也來了罗珍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤脚粟,失蹤者是張志新(化名)和其女友劉穎覆旱,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體核无,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扣唱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了团南。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片画舌。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖已慢,靈堂內(nèi)的尸體忽然破棺而出曲聂,到底是詐尸還是另有隱情,我是刑警寧澤佑惠,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布朋腋,位于F島的核電站,受9級特大地震影響膜楷,放射性物質(zhì)發(fā)生泄漏旭咽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一赌厅、第九天 我趴在偏房一處隱蔽的房頂上張望穷绵。 院中可真熱鬧,春花似錦特愿、人聲如沸仲墨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽目养。三九已至,卻和暖如春毒嫡,著一層夾襖步出監(jiān)牢的瞬間癌蚁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留努释,地道東北人碘梢。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像伐蒂,于是被迫代替她去往敵國和親痘系。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容