你的electron开发为什么不能一键启动?

395 阅读2分钟

背景

electron 开发环境一般会有两个进程需要启动

yarn electron 或 yarn start:main 来启动主进程

yarn start 或 yarn start: renderer 来启动渲染进程

这样,每次需要本地启动项目的时候,就要分成两个 terminal 终端窗口并输入两次指令

并且,一定要先 启动渲染进程 再 启动主进程,不然会造成如👇现象:

因为主进程先启动成功,渲染进程还没有启动成功、此时你的应用有electon 窗口但是空白,没有页面内容

等到渲染进程启动成功之后,如果没有热更新或者有的情况无法触发渲染进程热更新又或者没有触发,会导致需要手动 ctrl + r 来刷新页面 或者 重新启动 主进程

是不是很麻烦? 怎么解?

解法一

作为一个老前端,第一个想到的解法:

直接在package.json, scripts 字段中加入如👇指令:

both:"yarn start && yarn electron"

both: "yarn electron && yarn start"

是不是皆大欢喜了~

如果是这样,那么本文就到这里结束了

事情远远没有这么简单~~~~ 启动失败、不管是👆面哪种都只能启动前一个命令,后一个没有反应

解法二

细细理解了一下为什么不能启动成功?

如果你要是注意到 electron 的核心原理就是架构在双进程之上的

那么问题就迎来了转机

主进程和渲染进程分属两个不同的进程,👆那种 “&&” 的方式在纯前端开发中很常见,之所以能启动成功是因为前端web开发一般不会涉及多进程,而 electron 开发则不同、它有两个进程,在同一个 terminal 中同时启动两个进程肯定是不行

所以由此想到 通过 node 再启动一个进程不就好了吗

为了改造的代码尽可能少,我们在 webpack dev 配置中来进行改造:

import { execSync, spawn } from 'child_process';

...


devServer: {
  port,
    compress: true,
    hot: true,
    headers: { 'Access-Control-Allow-Origin': '*' },
  static: {
    publicPath: '/',
  },
  historyApiFallback: {
    verbose: true,
      },
      setupMiddlewares(middlewares) {
      console.log('Starting preload.js builder...');
      const preloadProcess = spawn('npm', ['run', 'start:preload'], {
        shell: true,
        stdio: 'inherit',
      })
        .on('close', (code: number) => process.exit(code!))
        .on('error', (spawnError) => console.error(spawnError));

      console.log('Starting Main Process...');
      let args = ['run', 'start:main'];
      if (process.env.MAIN_ARGS) {
        args = args.concat(
          ['--', ...process.env.MAIN_ARGS.matchAll(/"[^"]+"|[^\s"]+/g)].flat()
        );
      }
      spawn('npm', args, {
        shell: true,
        stdio: 'inherit',
      })
        .on('close', (code: number) => {
          preloadProcess.kill();
          process.exit(code!);
        })
        .on('error', (spawnError) => console.error(spawnError));
      return middlewares;
    },
  }import { execSync, spawn } from 'child_process';

...


devServer: {
  port,
    compress: true,
    hot: true,
    headers: { 'Access-Control-Allow-Origin': '*' },
  static: {
    publicPath: '/',
  },
  historyApiFallback: {
    verbose: true,
      },
      setupMiddlewares(middlewares) {
      console.log('Starting preload.js builder...');
      const preloadProcess = spawn('npm', ['run', 'start:preload'], {
        shell: true,
        stdio: 'inherit',
      })
        .on('close', (code: number) => process.exit(code!))
        .on('error', (spawnError) => console.error(spawnError));

      console.log('Starting Main Process...');
      let args = ['run', 'start:main'];
      if (process.env.MAIN_ARGS) {
        args = args.concat(
          ['--', ...process.env.MAIN_ARGS.matchAll(/"[^"]+"|[^\s"]+/g)].flat()
        );
      }
      spawn('npm', args, {
        shell: true,
        stdio: 'inherit',
      })
        .on('close', (code: number) => {
          preloadProcess.kill();
          process.exit(code!);
        })
        .on('error', (spawnError) => console.error(spawnError));
      return middlewares;
    },
  }

改造完成,直接 yarn start 启动整个应用

ps:如果你使用的 electron 自带的脚手架模版生成的项目、electron-forge/cli 已经帮你做了这个事情了。