用JavaScript開發(fā)桌面應用:Electron + React DeskTop開發(fā)環(huán)境搭建

隨著JavaScript開源社區(qū)的發(fā)展蒙谓,JavaScript的應用場景越來越廣泛剥啤,到目前為止,JavaScript在Web開發(fā)减余、桌面開發(fā)综苔、APP開發(fā)、服務端開發(fā)方面都可以勝任。

在桌面開發(fā)方面如筛,Electron是我個人最喜歡的解決方案堡牡,它基于HTML、CSS杨刨、JavaScript晤柄,跨平臺崩溪。目前有很多優(yōu)秀的桌面軟件都是使用Electron開發(fā)的:清單

Electron案例
Electron案例

(沒錯吉捶,微軟的VSCode也是Electron開發(fā)的,微軟居然沒用自己的開發(fā)套件角钩,可見Electron的桌面解決方案應該是很優(yōu)秀的赚抡。)

創(chuàng)建一個簡單的桌面應用

前提條件是在開發(fā)環(huán)境必須安裝了NodeJS

  1. 安裝Electron
    npm install electron -g
  2. 創(chuàng)建一個目錄和必備文件
    mkdir hello-world && cd hello-world
    touch main.js && touch package.json && touch index.html
  3. 在package.json文件中寫入
{
  "name"    : "your-app",
  "version" : "0.1.0",
  "main"    : "main.js"
}
  1. 在main.js文件中寫入
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 800, height: 600})

  // and load the index.html of the app.
  win.loadURL(url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Open the DevTools.
  win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
  1. 在index.html中寫入
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </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>
  1. 在終端運行
    electron .

  2. 你可以看到一個桌面應用程序


    第一個應用

Electron詳細文檔可以參看官方文檔

創(chuàng)建一個React項目

用Electron創(chuàng)建一個桌面應用很簡單爬坑,但是用HTML+Javascript肯定會需要用到一些前端庫來輔助開發(fā)。

目前比較主流的前端庫Vue.JS涂臣、AngularJS以及ReactJS盾计。三個庫/框架都很優(yōu)秀,不過我選擇了React肉康。

React創(chuàng)建一個項目其實很繁瑣闯估,因為它用了JSX,所以需要配置Babel吼和、webpack or Browserify

不過好在官方提供了一個工具 Create React App涨薪,可以非常簡單快速的創(chuàng)建React 項目,并且提供了熱調試環(huán)境炫乓。詳細參考官方文檔

簡單的來說刚夺,Create React App 創(chuàng)建了一個React的項目模版、配置末捣,并且提供了一些很方便的腳本命令用于調試和部署React前端程序侠姑。

使用Create React App創(chuàng)建的項目可以通過 npm start 啟動http://localhost:3000/ 服務熱調試;通過npm run build 編譯所有文件放在根目錄下build目錄里箩做。

整合Electron和React

Create React App創(chuàng)建的項目是一個純前端項目莽红,整合React項目和Electron并且保留熱調試和本地包引用需要以下幾個簡單的操作

  1. 需要在React項目的根目錄(不是src目錄)創(chuàng)建Electron的啟動文件main.js(前文中有詳細內容)
  2. 在React項目中的package.json文件中增加main字段,值為 "./main.js"
  3. 修改main.js 中的win.loadURL邦邦,改為
 win.loadURL(url.format({
    pathname: path.join(__dirname, './build/index.html'),
    protocol: 'file:',
    slashes: true
  }))

到目前為止安吁,在根目錄下運行 electron .就可以啟動React創(chuàng)建的桌面應用了。

但是還有幾個問題

  • 資源文件顯示不出來燃辖,在調試面板出現(xiàn)找不到文件的錯誤提示
  • 每次都要 npm run build 后才能看到修改項
  • 無法獲得系統(tǒng)包鬼店,例如用 os.cpus()無法得到系統(tǒng)cpus信息。

解決這些問題還需要幾個小步驟

  1. 修改package.json添加字段 "homepage":"."
    默認情況下黔龟,homepage是 http://localhost:3000 ,build后妇智,所有資源文件路徑都是/static滥玷,而Electron調用的入口是以file:協(xié)議,/staitc就會定位到系統(tǒng)的根目錄去巍棱,所以找不到靜態(tài)文件惑畴。在package.json文件中添加homepage字段并設置為"."后,靜態(tài)文件的路徑就變成了相對路徑拉盾,就能正確的找到了桨菜。

  2. main.js啟動頁修改為 http://localhost:3000/

 win.loadURL('http://localhost:3000/')

開發(fā)時,啟動nom start 后捉偏,在另一個終端啟動 electron . 這樣在electron中就可以熱調試了

不過編譯后需要改回從build/index.html啟動倒得,這樣很麻煩,可以在package.json中定義個 DEV字段夭禽,設置為 true/false霞掺,然后修改main.js
代碼如下:

  const pkg = require('./package.json') // 引用package.json

//判斷是否是開發(fā)模式
  if(pkg.DEV){
      win.loadURL("http://localhost:3000/")
  }else{
    win.loadURL(url.format({
    pathname: path.join(__dirname, './build/index.html'),
    protocol: 'file:',
    slashes: true
  }))
}

以后運行electron .之前,根據需要修改DEV為true/false就行了

最后讹躯,無論是運行build中的index.html還是http://localhost:3000 都無法通過require調用本地包的菩彬,需要使用window.require。

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

var os = window.require('os') // not be : var os = require('os')
console.log("got:",os.cpus())

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
        </div>
         CPU count: {os.cpus().length}
      </div>
    );
  }
}
export default App;

使用require

Paste_Image.png

使用window.require

Paste_Image.png

無論啟動頁是 http://localhost:3000/ 還是 build/index.html都有效潮梯。

至此骗灶,整合Electron和React就完成了,整個過程大部分工作都使用React官方和Electron官方提供的工具生成工程項目秉馏,只需要修改幾個配置和入口文件即可耙旦。

總結一下

  1. 用Create-React-App創(chuàng)建React項目
  2. 根目錄下創(chuàng)建Electron入口文件 main.js,修改main.js的啟動頁
  3. 在package.json中添加main字段為"main.js",添加 homepage字段為"."萝究,添加DEV字段為true/false(DEV字段選擇性添加免都,如果你更喜歡修改mian.JS的話)
  4. 應用本地庫使用window.require替代require

歡迎大家簡書或我的個人博客與我交流

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市帆竹,隨后出現(xiàn)的幾起案子绕娘,更是在濱河造成了極大的恐慌,老刑警劉巖栽连,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件险领,死亡現(xiàn)場離奇詭異,居然都是意外死亡秒紧,警方通過查閱死者的電腦和手機舷暮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來噩茄,“玉大人,你說我怎么就攤上這事复颈〖ㄆ福” “怎么了沥割?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凿菩。 經常有香客問我机杜,道長,這世上最難降的妖魔是什么衅谷? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任椒拗,我火速辦了婚禮,結果婚禮上获黔,老公的妹妹穿的比我還像新娘蚀苛。我一直安慰自己,他們只是感情好玷氏,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布堵未。 她就那樣靜靜地躺著,像睡著了一般盏触。 火紅的嫁衣襯著肌膚如雪渗蟹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天赞辩,我揣著相機與錄音雌芽,去河邊找鬼。 笑死辨嗽,一個胖子當著我的面吹牛世落,可吹牛的內容都是我干的。 我是一名探鬼主播召庞,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼岛心,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了篮灼?” 一聲冷哼從身側響起忘古,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诅诱,沒想到半個月后髓堪,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡娘荡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年干旁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炮沐。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡争群,死狀恐怖,靈堂內的尸體忽然破棺而出大年,到底是詐尸還是另有隱情换薄,我是刑警寧澤玉雾,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站轻要,受9級特大地震影響复旬,放射性物質發(fā)生泄漏。R本人自食惡果不足惜冲泥,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一驹碍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凡恍,春花似錦志秃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至革半,卻和暖如春碑定,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背又官。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工延刘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人六敬。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓碘赖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親外构。 傳聞我的和親對象是個殘疾皇子普泡,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內容