React+Electron搭建桌面应用方法和步骤

React+Electron搭建桌面应用方法和步骤

步骤:

【一: 构建、配置入口】

  1. 创建react 项目应用
  2. 安装 Electron 依赖项
  3. 修改 package.json 文件
  4. 新建主线程文件 main.js 主线程文件
  5. 运行项目

【二: 改造配置、环境域名】

  1. 非必须:添加 合并启动执行命令 ,(有配置环境,不要用)
  2. 非必须:安装 cross-env 环境变量,(根据环境请求不同域名和内容)

具体步骤如下:

【一: 构建、配置入口】

【1.1】创建react 项目应用

创建 react 应用:

// 安装react脚手架
npm install -g create-react-app

// 创建项目(projectname替换自己的项目名,不能有横杠大写,可以用下划线)
create-react-app projectname

// 打开目录
cd projectname

//启动测试是否正常
npm start

详见我另一个博客:
react+js或react+ts(tsx)使用creat-react-app、yarn搭建步骤

【1.2】react 项目内安装 Electron 依赖项

// 优先使用这个
npm i --save-dev electron

// 或者(node版本过低的不能用):
npm install electron

【1.3】修改 package.json 文件

  • 添加 定义执行命令,详见【1.5】
  • 实际需要 删除package.json内的 所有注释。对象数组最后一个元素结尾不能有逗号
{
  "name": "my-electron",
  "version": "0.1.0",
  "private": true,
  "main": "main.js", // 配置启动文件 -- 需新建
  "homepage": ".", // 设置应用打包的根路径
  "author": "author name",
  "description": "描述描述",
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "cross-env": "^7.0.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start", // 【原始】react 启动命令,需要额外执行 electron。同时启动这两个
    "electron": "electron .", // 【添加】electron 启动命令,需要额外执行 start。同时启动这两个
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "dev": "react-scripts start | electron . --debug", // 【2.1介绍】合并命令,若有环境变量配置,不能使用
    "dev:debug": "react-scripts start | electron . --debug", // 【2.1介绍】合并命令,debug 模式。若有环境变量配置,不能使用
    "start:dev": "cross-env MODE_ENV=development react-scripts start", // 【2.2介绍】配置环境变量
    "electron:dev": "cross-env MODE_ENV=development electron .", // 【2.2介绍】配置环境变量
    "electron-forge": "electron-forge make",
    "build-ele": "electron-builder"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@electron-forge/cli": "^6.2.1",
    "electron": "^25.1.0",
    "electron-builder": "^24.6.3",
    "electron-packager": "^17.1.1",
    "rimraf": "^5.0.1"
  },
  "build": { // electron-builder打包配置项可抽离,如使用electron-packager等打包则忽略
    "appId": "appId.electron.xxxx",
    "copyright": "xxxx",
    "productName": "myElectron",
    "directories": {
      "buildResources": "build",
      "output": "output"
    },
    "nsis": {
      "oneClick": false,
      "language": "2052", // 2052 是汉语
      "perMachine": true,
      "allowToChangeInstallationDirectory": true  // 这里很重要,允许用户自定义安装路径
    },
    "dmg": {
      "background": "build/logo512.png",
      "icon": "build/logo512.png",
      "iconSize": 100,
      "contents": [
        {
          "x": 380,
          "y": 180,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 130,
          "y": 180,
          "type": "file"
        }
      ],
      "window": {
        "x": 100,
        "y": 100,
        "width": 500,
        "height": 300
      }
    },
    "mac": {
      "target": [
        "dmg",
        "zip"
      ],
      "category": "public.app-category.utilities"
    },
    "win": {
      "icon": "build/logo512.png",
      "target": [{
        "target": "nsis",
        "arch": [
          "x64", // 实际打包此行可删除,64的包很大,没有32的包小
          "ia32"
        ]
      }]
    },
    "files": [
      "build/**/*",
      "main.js",
      "public/preload.js"
    ],
    "extends": null
  }
}

【1.4】新建 main.js 主线程文件

路径:与package.json 同层次

// 导入app、BrowserWindow模块
// app 控制应用程序的事件生命周期。事件调用app.on('eventName', callback),方法调用app.functionName(arg)
// BrowserWindow 创建和控制浏览器窗口。new BrowserWindow([options]) 事件和方法调用同app
// Electron参考文档 https://www.electronjs.org/docs

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

function createWindow () {
  let mainWindow = new BrowserWindow({
    width: 1000, // 窗口宽度
    height: 800, // 窗口高度
    title: "Electron", // 窗口标题,如果由loadURL()加载的HTML文件中含有标签<title>,该属性可忽略
    icon: nativeImage.createFromPath('src/public/favicon.ico'), // "string" || nativeImage.createFromPath('src/image/icons/256x256.ico')从位于 path 的文件创建新的 NativeImage 实例
    webPreferences: { // 网页功能设置
      nodeIntegration: true, // 是否启用node集成 渲染进程的内容有访问node的能力
      webviewTag: true, // 是否使用<webview>标签 在一个独立的 frame 和进程里显示外部 web 内容
      webSecurity: false, // 禁用同源策略
      nodeIntegrationInSubFrames: true // 是否允许在子页面(iframe)或子窗口(child window)中集成Node.js
    }
  });

// --------------------------------------------------------------------------------------------

  // 【二选一:打包时候使用】__dirname为当前文件路径
  // mainWindow.loadURL(url.format({
  //   pathname: path.join(__dirname, './build/index.html'),
  //   protocol: 'file:',
  //   slashes: true
  // }));

  // 【二选一:开发时候使用】
  //需要和本地项目启动会端口号一致,一般不需要改。多项目启动会有端口被占用而 改变情况
  mainWindow.loadURL('http://localhost:3000/'); 

// --------------------------------------------------------------------------------------------

  // 解决应用启动白屏问题
  mainWindow.on('ready-to-show', () => {
    mainWindow.show();
    mainWindow.focus();
  });

  // 当窗口关闭时发出。在你收到这个事件后,你应该删除对窗口的引用,并避免再使用它。
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
});

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
});

【1.5】 运行项目

【改造前】开发阶段,原本需要启动两个终端(react + electron),同时跑起来

// 第一个
npm run start

// 第二个
npm run electron

.

【二: 改造配置、环境域名】

【2.1】非必须: 添加 合并启动执行命令
若配置环境变量【2.2】,此步骤忽略

位置:package.json / scripts。详见:【1.3】

"dev": "react-scripts start | electron .", // 【2.1介绍】合并命令,若有环境变量配置,不能使用
"dev:debug": "react-scripts start | electron . --debug" // 【2.1介绍】合并命令,debug 模式。若有环境变量配置,不能使用

执行命令

npm run dev
// 或:
npm run dev:debug

若空白页刷新下,react的本地服务没有启动好就打开了客户端

【2.2】非必须: 配置环境变量,区分开发和打包模式,使用不同环境接口地址

  • 若不嫌弃麻烦,自己手动注释切换也行

详见:我的另一个博客: React自定义node、cross-env、webpack等方式不同环境配置命令整理https://blog.csdn.net/weixin_44461275/article/details/122988359

  • 安装:cross-env
npm方式:
	npm install --save cross-env

cnpm方式:
	cnpm install --save cross-env

yarn方式:
	yarn add cross-env
  • 配置执行命令:详见【1.3】package.json 文件
"start:dev": "cross-env MODE_ENV=development react-scripts start",
"electron:dev": "cross-env MODE_ENV=development electron .",
  • 修改main.js
// 导入app、BrowserWindow模块
// app 控制应用程序的事件生命周期。事件调用app.on('eventName', callback),方法调用app.functionName(arg)
// BrowserWindow 创建和控制浏览器窗口。new BrowserWindow([options]) 事件和方法调用同app
// Electron参考文档 https://www.electronjs.org/docs

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

function createWindow () {
  let mainWindow = new BrowserWindow({
    width: 1000, // 窗口宽度
    height: 800, // 窗口高度
    title: "Electron", // 窗口标题,如果由loadURL()加载的HTML文件中含有标签<title>,该属性可忽略
    icon: nativeImage.createFromPath('src/public/favicon.ico'), // "string" || nativeImage.createFromPath('src/image/icons/256x256.ico')从位于 path 的文件创建新的 NativeImage 实例
    webPreferences: { // 网页功能设置
      nodeIntegration: true, // 是否启用node集成 渲染进程的内容有访问node的能力
      webviewTag: true, // 是否使用<webview>标签 在一个独立的 frame 和进程里显示外部 web 内容
      webSecurity: false, // 禁用同源策略
      nodeIntegrationInSubFrames: true // 是否允许在子页面(iframe)或子窗口(child window)中集成Node.js
    }
  });

  // -----------------------------------------------------------------------------

  console.log('process.env.MODE_ENV--------------');
  console.log(process.env.MODE_ENV);

  if (process.env.MODE_ENV === 'development') {
    // 【开发时候使用】
    //需要和本地项目启动会端口号一致,一般不需要改。多项目启动会有端口被占用而 改变情况
    mainWindow.loadURL('http://localhost:3000/'); 
  } else {
    // 【打包时候使用】__dirname为当前文件路径
    mainWindow.loadURL(url.format({
      pathname: path.join(__dirname, './build/index.html'),
      protocol: 'file:',
      slashes: true
    }));
  }

  // -----------------------------------------------------------------------------

  // 解决应用启动白屏问题
  mainWindow.on('ready-to-show', () => {
    mainWindow.show();
    mainWindow.focus();
  });

  // 当窗口关闭时发出。在你收到这个事件后,你应该删除对窗口的引用,并避免再使用它。
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
});

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
});
  • 运行:(都要执行)
npm run start:dev
// +
npm run electron:dev

.

【3】打包项目

【3.1】核对package.json中: homepage: “.” 配置信息,若无则添加,详见【1.3】

  • react项目打包后,所有资源文件路径都是 /static,而 Electron 调用的入口是 file :协议,/static
    就会定位到根目录去,所以找不到静态文件。
  • package.json 文件中 homepage 字段设置为"."后,静态文件的路径就变成了相对路径。

【3.2】修改 main.js 打包项

  • 若配置了【2.2】环境变量,此步骤省略。已经配置更好的方式,不需要手动注释解开代码再执行
  • 详见:【1.4】
  // 【二选一:打包时候使用】__dirname为当前文件路径
   mainWindow.loadURL(url.format({
     pathname: path.join(__dirname, './build/index.html'),
     protocol: 'file:',
     slashes: true
   }));

  // 【二选一:开发时候使用】
  //需要和本地项目启动会端口号一致,一般不需要改。多项目启动会有端口被占用而 改变情况
  // mainWindow.loadURL('http://localhost:3000/'); 

【3.3】 安装 electron-builder 打包依赖

package.json内有,详见【1.3】devDependencies 部分

npm install electron-builder --save-dev
或:
npm install electron-builder -g

【3.4】 配置打包参数

package.json内build配置,详见【1.3】build部分

【3.5】 修改电脑rc文件源配置, 若未遇到下载 gitlab文件超时报错,可忽略

electron 打包会从 gitlab下载很多包,外网下载不到,导致打包失败
修改 rc 文件源配置(npm打包就修改 npmrc文件,cnpm、yarn等同理)

C:\Users\用户当前登录名

如我的虚拟机上是用户是 1234 ,则打开是:
在这里插入图片描述

用记事本打开,添加一行。若没有对应rc文件自己手动添加一下:

electron-builder-binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/

【3.5.2】或者你也可以下载对应electron的缓存文件包

win + R 输入:

%LOCALAPPDATA%\electron-builder\cache

在这里插入图片描述

网上有相关资源路径可以看到层级关系
引自:https://blog.csdn.net/peade/article/details/122368409

├── AppImage
│   └── AppImage-17-06-17-mac
├── AppImage-packages
│   └── 10.03.17
├── Squirrel.Windows
│   └── Squirrel.Windows-1.6.0.0
├── fpm
│   └── fpm-1.8.1-20150715-2.2.2
├── linux-tools
│   └── linux-tools-mac-10.12
├── nsis
│   └── nsis-3.0.1.13
│  └── nsis-resources-3.1.0
├── winCodeSign
│   └── winCodeSign-1.9.0
└── wine
    └── wine-2.0.1-mac-10.12

不建议这种,首次打包需要下载安装好几个

【3.6】 执行打包

// 安装依赖
npm install

// 打包
npm run build-ele

到此,结束


electron 打包优化后续会出

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值