Electron开发实践(3)——环境&工程搭建(Vite+Electron+React)

1,318 阅读4分钟

一站式Electron开发解决方案: Electron-Prokit

Electron开发实践系列文章

Electron开发实践(1)——为什么选择Electron

Electron开发实践(2)——Electron生态开发技术选型

Electron开发实践(3)——环境&工程搭建(Vite+Electron+React)

Electron开发实践(4)——跨进程通信

Electron开发实践(5)——原生模块调用&开发(dll,dylib,rust)

Electron开发实践(6)——应用打包

Electron开发实践(7)——应用升级

Electron开发实践(8)——网络请求封装(axios + net + lowdb + koa)

源码地址:github.com/Xutaotaotao…

在Electron开发实践(2)——Electron生态开发技术选型中提到,用Vite+Electron+React构建一个Electron项目,现在我们就开始吧!

为什么用Vite

cn.vitejs.dev/guide/why.h…已经说得非常清楚了,这里不做过多赘述,在开始用Vite构建Electorn的项目之前,我也用过Webpack来构建,但是从开发体验来说,Vite给人的感觉就是爽,没啥说的,爽就完了😊。

创建一个Vite+React的项目

用Vite官方的指引创建一个vite+react的项目

pnpm create vite

选择React,选择Typescript + SWC,SWC是什么——>swc.rs

修改项目结构

我们把src下创建一个render目录和main目录,故名思义就是渲染进程和主进程,然后改变index.html中script的引入<script type="module" src="/src/render/main.tsx"></script>,这样极简的项目结构就出现了

自定义开发脚本

到现在为止,我们还是一个普通的web项目,现在我们需要自定义开发脚本来融合主进程和渲染进程的启动。

首先实现render进程的启动,删除vite.config.ts,添加scripts目录,然后加入dev.js,用来启动开发服务,第一阶段我们先完成渲染进程的启动配置,添加config/vite文件目录,加入render.js,然后在dev.js中使用config/vite/render.js作为配置文件,用来启动服务,核心代码如下

import path from "path";
import electronPath from "electron";
import { spawn } from "child_process";
import { createServer, build } from "vite";
import { fileURLToPath } from "url";

const __dirname = fileURLToPath(new URL(".", import.meta.url));

const sharedOptions = {
  mode: "dev",
  build: {
    watch: {},
  },
};

const renderDev = {
  async createRenderServer() {
    const options = {
      ...sharedOptions,
      configFile: path.resolve(__dirname, "../config/vite/render.js"),
    };
    this.server = await createServer(options);
    await this.server.listen();
    this.server.printUrls();
    return this.server;
  },
};

const initDev = async () => {
  try {
    await renderDev.createRenderServer();
  } catch (err) {
    console.error(err);
  }
};

initDev();

现阶段的目录结构如下:

现在render进程的脚本基本差不多了,下一步就是要把Electron集成进去。

集成Electorn进程

下面对config/vite/main.jssrc/main/index.ts以及scripts/dev.js进行编码。config/vite/main.js主要是为了给主进程使用的Vite配置文件,src/main/index.ts主要是Electron进程的入口文件,最后在scripts/dev.js中去启动服务。

编写代码之前我们先下载一下Electron的依赖。

tips:如果下载Electron慢的话,可以进行一下下载源的配置。

pnpm config set registry https://registry.npm.taobao.org

pnpm config set electron_mirror https://npm.taobao.org/mirrors/electron/

主要是需要改造scripts/dev.js使其支持启动electron进程服务,然后将渲染进程和Electron进程合并,这样就可以构造一个最基础的Electron开发环境了,现在我们来尝试启动Electron进程。

核心代码如下

let spawnProcess = null;

const mainDev = {
  async createMainServer(renderDevServer) {
    const protocol = `http${renderDevServer.config.server.https ? "s" : ""}:`;
    const host = renderDevServer.config.server.host || "localhost";
    const port = renderDevServer.config.server.port;
    process.env.VITE_DEV_SERVER_URL = `${protocol}//${host}:${port}/`;
    process.env.VITE_CURRENT_RUN_MODE = "main";
    const options = {
      ...sharedOptions,
      configFile: path.resolve(__dirname, "../config/vite/main.js"),
    };
    return build({
      ...options,
      plugins: [
        {
          name: "reload-app-on-main-package-change",
          writeBundle() {
            if (spawnProcess !== null) {
              spawnProcess.kill("SIGINT");
              spawnProcess = null;
            }

            spawnProcess = spawn(String(electronPath), ["."]);

            spawnProcess.stdout.on("data", (d) => {
              const data = d.toString().trim();
              console.log(data);
            });

            spawnProcess.stderr.on("data", (data) => {
              console.error(`stderr: ${data}`);
            });
          },
        },
      ],
    });
  },
};

const initDev = async () => {
  try {
    const renderDevServer = await renderDev.createRenderServer();
    await mainDev.createMainServer(renderDevServer);
  } catch (err) {
    console.error(err);
  }
};

initDev();;

注意几个点

1.我们这里利用了writeBundle,就是等chunk都写入文件后,再启动Electron进程。

2.这里没有利用Electron的命令启动,而是通过Node.js的child_process模块的spawn方法启动Electron子进程,主要是因为我们需要依赖开发环境的渲染进程。

3.另外就是config/vite/main.js中需要对rollupOptionsexternal进行electron的配置,把导入包转成外部依赖,不然在启动Electron会找不到Electron的路径。

4.在createMainServer中我们注入了全局可使用的变量,以便Electorn加载页面的时候可以使用这些变量

现阶段的代码结构如下:

 

不出意外pnpm dev会出现下面的界面。

到现在,一个最简单的Electron开发环境搭建好了。

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3天,点击查看活动详情

原文链接

taotaoxu.com/summary/ele…