背景

目前社区两大Vue+Electron的脚手架:electron-vuevue-cli-plugin-electron-builder

都有这样那样的问题,且都还不支持Vue3,然而Vue3已是大势所趋,

Vite势必也将成为官方Vue脚手架,

下图是尤雨溪在开发好Vite之后与webpack之父的对话

所以开发一个Vite+Vue3+Electron的脚手架的需求日趋强烈

我前段时间做了一个,

但是发现了一些与Vite有关的问题,

比如:Vite会把开发环境的process对象吃掉的问题

这对于web项目来说问题不大,但对于我们的Electron项目来说,就影响很大了

今天我就把这个思路和实现方式的关键代码发出来供大家参考,

同时也希望Vue社区的贡献者们,能注意到这个问题

(给Vue官方的各个项目提issue真的是太难了,Electron官方项目在这方面就做的很好,很open、很包容)

环境

先用Vite创建一个Vue3的工程,这就是你的实际项目工程

接着安装几个Electron相关的依赖,最终我的工程下的依赖情况如下:

    "@vue/compiler-sfc": "^3.0.0",
"vite": "^1.0.0-rc.9",
"vue": "^3.0.2",
"vue-router": "^4.0.0-rc.1",
"electron": "^11.0.2",
"electron-builder": "^22.9.1",
"electron-updater": "^4.3.5",
    "postcss-scss": "^3.0.2",
 
    "sass": "^1.27.0",

注意:这些依赖全部安装在devDependencies下

各个库的版本发文时应该是最新的了,不过如果有更新的版本,你完全可以用,没影响。

工程的目录结构大概是如下这样:

[yourProject]

  node_modules  依赖包

  public  vite创建的目录,为vue服务的,实际没多大用

  release  打包后编译输出的目录,该目录的根目录下存放打包后的安装包

    bundled  该目录存放vue打包后的文件(html js css img等)

    win-unpacked  该目录存放编译后生成的可执行文件及相关的dll,不包含安装包

  resource  资源目录

    unrelease  该目录存放编译期需要的资源

    release   该目录存放编译后需要随安装包分发给客户的资源

  script     此目录存放各种脚本,比如编译脚本,启动脚本,签名脚本等

  src  源码目录

    render  渲染进程源码目录

    main  主进程源码目录

    common  两个进程都会用到的共用源码目录

  package.json  项目配置文件

  index.html  vue3的入口页面

  .gitignore

接着在package.json中,增加两个命令:

  "scripts": {
"start": "node ./script/dev.js",
"release": "node ./script/release.js"
},

同时在script目录下创建相应的文件,接着我们就开始撰写者两个文件的代码了

调试脚本

通过Vite启动Web项目

调试脚本首先要做的工作就是启动Vue项目

让它跑在http://localhost下,这样我们修改渲染进程的代码时,

会通过Vite的热更新机制实时反馈到界面上

Vite除了提供cli的指令启动项目外,也提供了API,我这里就是直接调它的API来启动项目的

关键代码如下:

let vite = require("vite")
createServer () {
return new Promise((resolve, reject) => {
let options = {
root:process.cwd(),
enableEsbuild: true
};
this.server = vite.createServer(options);
this.server.on("error", (e) => this.serverOnErr(e));
this.server.on("data", (e) => console.log(e.toString()));
this.server.listen(this.serverPort, () => {
console.log(`http://localhost:${this.serverPort}`);
resolve();
});
});
},

其中this.serverPort是绑定在当前对象上的一个变量,意义是指定vite项目启动时使用的端口号

启动成功后http server对象绑定到当前对象的server变量上

如果启动过程中报错,则很有可能是端口占用,将执行如下逻辑:

  serverOnErr (err) {
if (err.code === "EADDRINUSE") {
console.log(
`Port ${this.viteServerPort} is in use, trying another one...`
);
setTimeout(() => {
this.server.close();
this.serverPort += 1;
this.server.listen(this.viteServerPort);
}, 100);
} else {
console.error(chalk.red(`[vite] server error:`));
console.error(err);
}
},

这段逻辑就是递增端口号,再次尝试启动http server

设置环境变量

往往每个开发人员的环境变量都是不一样的

有的开发人员需要连开发服务器A,有的开发人员需要连开发服务器B

而且开发环境的环境变量、测试环境、生产环境的环境变量也不一样

所以我把环境变量设置到几个单独的文件中

方便区分不同的环境,也方便gitignore,避免不同开发人员的环境变量互相冲突

开发环境的环境变量保存在src/script/dev.env.js中

let env = require("./dev.env.js")

生产环境的环境变量则为release.env.js

这个文件的代码非常简单,如下:

module.exports = {
APP_VERSION: require("../package.json").version,
ENV_NOW: "dev",
PROTOBUF_SERVER: "******.com",
SENTRY_SERVICE: "https://******.com/34",
ELECTRON_DISABLE_SECURITY_WARNINGS: true
}

需要注意的是:ELECTRON_DISABLE_SECURITY_WARNINGS,

这个环境变量是为了屏蔽Electron开发者调试工具那一大堆警告的

(你如果开发过Electron应用,你应该知道我说的是什么)

APP_VERSION是从项目的package.json中取的版本号,

你当然可以不设置这个环境变量,通过Electron的API获取版本号

app.getVersion() //主进程可用

但通过ElectronAPI获取到的版本号,在开发环境下,是Electron.exe的版本号,不是你的项目的版本号

打包编译后,这个问题是不存在的。

ENV_NOW是当前的环境,开发环境下它的值为dev,打包编译后的生产环境它的值应为product,

因为现在我们是讲如何构建开发环境,引用的是dev.env.js,

等下一篇文章讲如何构建编译环境时,引用的就是release.env.js了,

编译主进程代码

Vite之所以快,有一个很重要的原因是它使用了esbuild模块来编译代码

这里我们也使用esbuild来编译我们的主进程的代码

前面说了主进程是放在src/main/目录下的

这里我使用的是TypeScript开发,入口程序是app.ts,你完全可以使用Js开发,文件名也随你自定义

  buildMain () {
let outfile = path.join(this.bundledDir, "entry.js");
let entryFilePath = path.join(process.cwd(), "src/main/app.ts");
//这个方法得到的结果:{outputFiles: [ { contents: [Uint8Array], path: '<stdout>' } ]}
esbuild.buildSync({
entryPoints: [entryFilePath],
outfile,
minify: false,
bundle: true,
platform: "node",
sourcemap: false,
external: ["electron"],
});
env.WEB_PORT = this.serverPort;
let envScript = `process.env={...process.env,...${JSON.stringify(env)}};`
let js = `${envScript}${os.EOL}${fs.readFileSync(outfile)}`;
fs.writeFileSync(outfile, js)
},

esbuild会自动查找app.ts引用的其他代码,

还有treeshaking机制保证你不会把无用的代码打包到输出目录

我把sourcemap关掉了,因为调试主进程很困难,

基本都是手动console.log信息调试的,朋友们有好的建议请赐教一下

platform要指定成node,要不然esbuild会尝试帮你去找node.js内置的包,肯定找不到,就报错了

同理,还要把electron设置成external

在上一节设置的环境变量的基础上

我们又增加了一个WEB_PORT的环境变量,

Electron启动后,要根据这个变量去加载localhost的页面,

这个变量是应用启动时确定的,是动态的,所以没办法设置到dev.env.js中

输出代码前,我们把环境变量的值也附加在输出代码中了

这样Electron进程启动时,会先设置好环境变量,再执行具体的业务代码

(我们当然也可以通过其他方式设置环境变量,但这样做主要是为了和生产环境保持一致,看到下一篇文章你就会知道了)

最终生成的代码会被输出到这个目录下面:

bundledDir: path.join(process.cwd(), "release/bundled")

稍后我们启动Electron时,也会让Electron加载这个目录下的入口程序。

启动Electron

Electron的node module并没有提供API给开发者调用以启动进程

所以我们只能通过node的child_process模块来启动Electron的进程

代码如下:

  createElectronProcess () {
this.electronProcess = spawn(
require("electron").toString(),
[path.join(this.bundledDir, "entry.js")],
{
cwd: process.cwd(),
env,
}
);
this.electronProcess.on("close", () => {
this.server.close();
process.exit();
});
this.electronProcess.stdout.on("data", (data) => {
data = data.toString();
console.log(data);
});
},

require("electron").toString()得到的是Electron的可执行文件的路径

Windows环境下为:node_modules\electron\dist\electron.exe

Mac环境下为:node_modules/electron/dist/Electron.app/Contents/MacOS/Electron

path.join(this.bundledDir, "entry.js")为Electron进程指定了入口程序文件的地址

cwd: process.cwd()是为Electron指定当前工作目录(此处又为Electron指定了一次环境变量,其实不指定也没关系)

当Electron进程退出时,我们也关闭了Vite创建的http server

主进程加载渲染进程页面

此处最关键的逻辑就是这一句

    if (process.env.ENV_NOW === "dev") {
await win.loadURL(`http://localhost:${process.env.WEB_PORT}/`);
}

process.env.WEB_PORT就是我们上文中设置的WEB_PORT变量

这个逻辑当然还有else分支,那是下一篇博文的内容了

敬请期待!

Vite ❤ Electron——基于Vite搭建Electron+Vue3的开发环境【一】的更多相关文章

  1. 基于 vagrant搭建移动端的开发环境

    # 后端开发环境Homestead启动 Homestead 之前,确保 VirtualBox .Vagrant.Git 软件己安装. ## 安装 laravel/homesteadvagrant bo ...

  2. 基于全志H3芯片的ARM开发环境搭建

    基于全志H3芯片的ARM开发环境搭建 最近买了个友善之臂的NanoPi M1板子,又在网上申请了个NanoPi NEO板子,这两个都是基于全志H3芯片的Crotex-A7四核ARM开发板,两个板子可以 ...

  3. 如何基于Jupyter notebook搭建Spark集群开发环境

    摘要:本文介绍如何基于Jupyter notebook搭建Spark集群开发环境. 本文分享自华为云社区<基于Jupyter Notebook 搭建Spark集群开发环境>,作者:apr鹏 ...

  4. 搭建 AngularJS+Ionic+Cordova 开发环境并运行一个demo

    目前的手机APP有三类:原生APP,WebAPP,HybridApp:HybridApp结合了前两类APP各自的优点,越来越流行. Cordova就是一个中间件,让我们把WebAPP打包成Hybrid ...

  5. 极其简单的搭建eclipse的android开发环境

    这篇博客是关于如何搭建eclipse的android开发环境, 与网上的其他博客不同,我的方法比他们简单的多,所 以推荐给大家. 搭建eclipse的android开发环境步骤: 1.配置JDK(Ja ...

  6. 基于Eclipse的Go语言可视化开发环境

    http://jingyan.baidu.com/article/d7130635032e2f13fdf475b8.html 基于Eclipse的Go语言可视化开发环境 | 浏览:2924 | 更新: ...

  7. 搭建Eclipse C/C++开发环境

    搭建eclipse C/C++开发环境:     1.下载并安装Eclipse for C++:http://www.eclipse.org.最新版是基于Eclipse 3.5 galileo,文件名 ...

  8. 轻松搭建Windows8云平台开发环境

    原文:轻松搭建Windows8云平台开发环境 Windows Store应用是基于Windows 8操作系统的新一代Windows应用程序,其开发平台以及运行模式和以往传统平台略有不同.为了帮助更多开 ...

  9. (cljs/run-at (JSVM. :browser) "搭建刚好可用的开发环境!")

    前言  书接上一回,在了解cljs基本语法后并在clojurescript.net的奇特错误提示后,我们必须痛定思痛地搭建一个本地的开发环境,以便后续深入地学习cljs. 现有的构建工具  由于浏览器 ...

  10. Grunt搭建自动化web前端开发环境--完整流程

    Grunt搭建自动化web前端开发环境-完整流程 jQuery在使用grunt,bootstrap在使用grunt,百度UEditor在使用grunt,你没有理由不学.不用! 1. 前言 各位web前 ...

随机推荐

  1. PuTTY SSH 使用证书免密码登录

    1.用PuTTY SSH 密钥生成工具puttygen.exe生成密钥.生成的密钥类型和位数按照默认的就OK,SSH-2 RSA,1024位生成密钥时你需要在空白区域移动鼠标,以便产生随机数据点击保存 ...

  2. Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道

    Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道 背景 上一讲我们介绍了创建子进程的方式.我们都知道,创建子进程是为了与父进程协作(或者是为了执行新的程序,参考 Linux ...

  3. soloPi安装使用

    SoloPi脚本转化器正式发布,支持转化为 Appium 与 Macaca 脚本:https://github.com/soloPi/SoloPi-Convertor,脚本转化器使用教程: https ...

  4. twoSum问题的核心思想

    Two Sum 系列问题在 LeetCode 上有好几道,这篇文章就挑出有代表性的几道,介绍一下这种问题怎么解决. TwoSum I 这个问题的最基本形式是这样:给你一个数组和一个整数 target, ...

  5. Nginx是什么?有什么用?

    一.Nginx是什么 Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服 ...

  6. Matlab批量绘制图像并保存

    author:ZKe ------------------------------- 以下是一个txt文件,每行11个字段,第一个字段是日期,后面10个是用户id和对应今天发表微博数,所有字段用制表符 ...

  7. Python - 生成 requirement.txt 文件

    前言 Python项目中,一般都会有一个 requirements.txt 文件 这个文件主要是用于记录当前项目下的所有依赖包及其精确的版本号,以方便在一个新环境下更快的进行部署 如何生成 requi ...

  8. 利用 Docker 构建一个简单的 java 开发编译环境

    目前 Java 语言的版本很多,除了常用的 Java 8,有一些遗留项目可能使用了 Java 7,也可能有一些比较新的的项目使用了 Java 10 以上的版本.如果想切换自己本地的 Java 开发环境 ...

  9. Python - Git仓库忽略提交规则 & .gitignore配置

    Git 忽略文件提交的方法 有三种方法可以实现忽略Git中不想提交的文件. 在Git项目中定义 .gitignore 文件 这种方式通过在项目的某个文件夹下定义  .gitignore 文件,在该文件 ...

  10. 论文阅读:Learning Attention-based Embeddings for Relation Prediction in Knowledge Graphs(2019 ACL)

    基于Attention的知识图谱关系预测 论文地址 Abstract 关于知识库完成的研究(也称为关系预测)的任务越来越受关注.多项最新研究表明,基于卷积神经网络(CNN)的模型会生成更丰富,更具表达 ...