用JavaScript开发桌面应用:Electron + React DeskTop开发环境搭建

随着JavaScript开源社区的发展,JavaScript的应用场景越来越广泛,到目前为止,JavaScript在Web开发、桌面开发、APP开发、服务端开发方面都可以胜任。

在桌面开发方面,Electron是我个人最喜欢的解决方案,它基于HTML、CSS、JavaScript,跨平台。目前有很多优秀的桌面软件都是使用Electron开发的:清单

Electron案例
Electron案例

(没错,微软的VSCode也是Electron开发的,微软居然没用自己的开发套件,可见Electron的桌面解决方案应该是很优秀的。)

创建一个简单的桌面应用

前提条件是在开发环境必须安装了NodeJS

  1. 安装Electron
    npm install electron -g
  2. 创建一个目录和必备文件
    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详细文档可以参看官方文档

创建一个React项目

用Electron创建一个桌面应用很简单,但是用HTML+Javascript肯定会需要用到一些前端库来辅助开发。

目前比较主流的前端库Vue.JS、AngularJS以及ReactJS。三个库/框架都很优秀,不过我选择了React。

React创建一个项目其实很繁琐,因为它用了JSX,所以需要配置Babelwebpack or Browserify

不过好在官方提供了一个工具 Create React App,可以非常简单快速的创建React 项目,并且提供了热调试环境。详细参考官方文档

简单的来说,Create React App 创建了一个React的项目模版、配置,并且提供了一些很方便的脚本命令用于调试和部署React前端程序。

使用Create React App创建的项目可以通过 npm start 启动http://localhost:3000/ 服务热调试;通过npm run build 编译所有文件放在根目录下build目录里。

整合Electron和React

Create React App创建的项目是一个纯前端项目,整合React项目和Electron并且保留热调试和本地包引用需要以下几个简单的操作

  1. 需要在React项目的根目录(不是src目录)创建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创建的桌面应用了。

但是还有几个问题

  • 资源文件显示不出来,在调试面板出现找不到文件的错误提示
  • 每次都要 npm run build 后才能看到修改项
  • 无法获得系统包,例如用 os.cpus()无法得到系统cpus信息。

解决这些问题还需要几个小步骤

  1. 修改package.json添加字段 "homepage":"."
    默认情况下,homepage是 http://localhost:3000 ,build后,所有资源文件路径都是/static,而Electron调用的入口是以file:协议,/staitc就会定位到系统的根目录去,所以找不到静态文件。在package.json文件中添加homepage字段并设置为"."后,静态文件的路径就变成了相对路径,就能正确的找到了。

  2. main.js启动页修改为 http://localhost:3000/

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

开发时,启动nom start 后,在另一个终端启动 electron . 这样在electron中就可以热调试了

不过编译后需要改回从build/index.html启动,这样很麻烦,可以在package.json中定义个 DEV字段,设置为 true/false,然后修改main.js
代码如下:

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

//判断是否是开发模式
  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创建React项目
  2. 根目录下创建Electron入口文件 main.js,修改main.js的启动页
  3. 在package.json中添加main字段为"main.js",添加 homepage字段为".",添加DEV字段为true/false(DEV字段选择性添加,如果你更喜欢修改mian.JS的话)
  4. 应用本地库使用window.require替代require

欢迎大家简书或我的个人博客与我交流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容