从 0 搭建 electron 项目

413 阅读5分钟

Talk is Cheap, show me the ** code!

第一步:安装electron

找一个前端项目,没有的话就建一个(下文是以create-react-app建的一个新项目),首先安装electron

npm install electron --save-dev

如果人在国内,🪜又不给力的话,通常安装的会很慢,此处不是npm安装的慢,是npm在下完electron后,electron会调用自己的安装脚本,脚本下载的慢,因此在设置npm源外,如果太慢了顶不住了的话,还需要设置一下electron源

npm config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/

这样就ok了,electron在安装的时候会去找ELECTRON_MIRROR这个变量,有就会修改下载源的,亲测有效

第二步:编写main.js文件

编写入口文件,首先在package.json文件中加个字段"main": "main.js" 让 electron 知道改去读哪个入口文件,再建一个main.js文件就可以了,以下是一个简单的例子

const { BrowserWindow, ipcMain } = require('electron')
const { app, dialog } = require('electron')
const path = require('path')
// const remote = require('@electron/remote/main') 这个是干嘛的,后续文章会说明
// const ElectronStore = require('electron-store') 后续会说明这个东东

const isDevelopment = process.env.NODE_ENV === 'development'
let mainWindow = null

function createMainWindow() {
    mainWindow = new BrowserWindow({
        width: 1160,
        height: 752,
        minHeight: 632,
        minWidth: 960,
        show: false,
        // frame: false, 是否使用无边框模式,(应用程序关闭最小化那一条东西)
        title: 'Markdown Editor',
        webPreferences: {
            nodeIntegration: true, // 如果想在渲染进制中使用nodejs相关的功能需要设置一下
            contextIsolation: false // 是否隔离主进程和渲染进程,如果隔离的话,相关的通信方式都需要在preload的前置脚本中把需要与主进程通信的函数、挂载在window中给渲染进程使用,具体可看下官网的例子
          // preload: path.resolve(__dirname, '.preload.js') 可以写一些前置脚本
        },
        icon: path.join(__dirname, './assets/appdmg.png')
    })

    if (isDevelopment) {
        // 为什么electron可以直接装直接用,因为它的窗口可以通过url进行渲染
        mainWindow.loadURL('http://localhost:3000/')
    } else {
        const entryPath = path.join(__dirname, './build/index.html')
        mainWindow.loadFile(entryPath)
    }

    mainWindow.once('ready-to-show', () => {
        mainWindow.show()
    })
    // remote.initialize()
    // remote.enable(mainWindow.webContents)
    if (isDevelopment) mainWindow.webContents.openDevTools()
}

app.on('ready', () => {
    createMainWindow()
    // ElectronStore.initRenderer()
    // ipcMain.handle('choose-file', async (event, args) => {
    //     const res = await dialog.showOpenDialog(args)
    //     return res
    // })
})

第三步:配置启动命令

在 package.json 文件配置的script中配置启动命令

{
  "scripts": {
    "dev": "concurrently "wait-on http://localhost:3000 && cross-env NODE_ENV=development electron ." "npm start"",
  }
}

大家可以仔细看看这条启动命令,其中还用到了concurrently和wait-on这两个工具,因此还要装一下

npm insatll --save-dev concurrently wait-on

这两个命令是干嘛的呢?我们在看第二部的时候可以发现,一个 BrowserWindow 需要 LoadURL 或者 LoadFile,因此在启动 electron 之前得需要先启一个前端页面服务或者把前端项目打包好。我们启动命令只需要启项目开发服务,这样开发才有热更,因此我们想开发一个 electron 应用需要启动 frontend 服务以及 electron 进程。同时启两个服务就要用到 concurrently 这个工具了。

我们再来考虑服务启动先后的问题,要先启动 electron,得先把 frontend 服务启动好才行,不然开发中一开始打开electron,里面什么都没有,这不是我们想要的效果,应该electron打开的时候页面已经加载好了才行,因此就需要用到 wait-on 这个工具,这个工具就是用来等待某个套接字这里可以理解为等服务启动好了,才执行后面的命令。

最后:出包

走完前三步,我们其实已经可以进行愉快的跨端开发了,在开发完之后我们就可以出包了。

这里我们可以用 electron-builder 这个工具帮我们打包 electron 应用(传送门),首先我们可以先安装它。

npm install --save-dev electron-builder

配置相关的打包配置,我们直接配置在package.json里就可以了,除了打包配置写在build里外pakage.json还要写好name、author、version,不然安装不了

{
  "name": "切图仔的妈宕编辑器", // 如果用window安装的话,安装出来的目录名就叫这个
  "author": "切图仔",
  "version": "9.9.9",
  "description": "看心情写描述信息,不是必须项",
  "build": {
    "appId": "madang-editor",
    "productName": "妈宕编辑器",
    "copyright": "Copyright © 2024 切图仔",
    "extends": null,
    "files": [ // 要打包进去应用里的文件
      "build/**/*",
      "node_modules/**/*",
      "package.json",
      "main.js"
    ],
    "directories": {
      "buildResources": "assets" // 静态资源的目录,应用的icon什么的
    },
    "mac": {
      "category": "public.app-category.productivity",
      "artifactName": "${productName}-${version}-${arch}.${ext}"// 安装包的名字
    },
    "dmg": {// macOS安装包
      "background": "assets/appdmg.png",
      "icon": "assets/icon.icns",
      "iconSize": 100,
      "contents": [
        {
          "x": 380,
          "y": 280,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 110,
          "y": 280,
          "type": "file"
        }
      ],
      "window": {
        "width": 500,
        "height": 500
      }
    },
    "win": {// windows 安装包
      "target": [
        "msi", // 我在写这篇文章的时候在高版本的macOS出msi包会有些问题,如果报错了去掉msi安装包只出nsis也可以,window 也能安装
        "nsis"
      ],
      "icon": "assets/icon.ico", // 高版本的ico有大小限制,最小尺寸是256×256,某些垃圾线上转ico的工具装出来有问题,可以试试这个 https://redketchup.io/icon-converter
      "artifactName": "${productName}-Setup-${version}.${ext}",// 安装包的名字
      "publisherName": "Jamsdfn"
    },
    "nsis": {
      "allowToChangeInstallationDirectory": true,
      "oneClick": false,
      "perMachine": false
    }
  }
}

配置好上面的配置之后就可以配置一下打包命令了,也是package.json,不过懒得配的话也可以直接跑命令,不用npm启

{
	"script": {
    "pack": "node scripts/build.js && electron-builder --dir",
    "pack-mac": "node scripts/build.js && electron-builder --dir --mac",
    "pack-win": "node scripts/build.js && electron-builder --dir --win",
    "dist": "node scripts/build.js && electron-builder",
    "dist-mac": "node scripts/build.js && electron-builder --mac",
    "dist-win": "node scripts/build.js && electron-builder --win"
	}
}

附上我自己写的一个小项目地址,可以clone到本地玩一玩,一个markdown编辑器:github.com/Jamsdfn/mar…