美文网首页ElectronReactIT路上
用JavaScript开发桌面应用:Electron + Rea

用JavaScript开发桌面应用:Electron + Rea

作者: Frederic晓代码 | 来源:发表于2017-03-09 14:07 被阅读7288次

    随着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

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

    相关文章

      网友评论

      • Cosecant:楼主你好,弱弱的问下,你能在dev模式下正常的调起系统的文件选择窗口吗?我的老是electron报错:TypeError: fs.existsSync is not a function
        a8bd7070c63b:@Cosecant 解决了不?能透露下方法么?我也遇到这个问题了
        Cosecant:报错的地方在是electron包的index.js文件
      • 南京前端架构ztao:我把build好的代码放进去之后,打包成exe,都没有问题,但是因为没有本地服务了,界面感觉是js没有执行,整个都出不来,这个该怎么解决?
        a8bd7070c63b:mainWindow.loadURL(`file://${__dirname}/index.html`) 改成这样试下呢
      • b8573ceb749e:首先感谢作者,让小白的我入门,按照文章的步骤我走了一遍,只在最后的地方有些和文章不太一样的地方咨询下作者,window.require这个function,我在启动num start的时候在浏览器里面会报错提示TypeError: window.require is not a function,但是用num run build,跑在electorn里面的结果就和作者一样了,请问是哪里不对需要设置么?

      本文标题:用JavaScript开发桌面应用:Electron + Rea

      本文链接:https://www.haomeiwen.com/subject/yaewgttx.html