从 0 开始搭建Electron模板-构建项目

前言

本人后端开发,思维比较活跃,脑子里经常会冒出些小点子,但很多时候,只有后端手段的我难以将他们实现出来,故此借助electron系统学习一下前端的技术栈。

本文目标:搭建一套 Electron + Vite + React + TypeScript 的模板。

创建 electron 项目

既然是以学习为目的,那就不使用quick-start了,照着 官网教程走一遍。

先初始化一个node项目:

bash 复制代码
cd electron-demo && cd electron-demo
npm init -y

npm init -y 命令将自动创建一个 package.json 文件,并填充默认值。

这里了解一下几个字段:

  • scripts : 这个字段是一个对象,它包含了可以运行的脚本命令。这些脚本可以通过npm run <script>命令来执行。常用的 npm run dev就来自于它。

  • dependencies: 这个字段列出了项目运行时所需的依赖包。当你发布或部署应用时,这些依赖是必须的。

  • devDependencies: 这个字段列出了只在开发过程中需要的依赖包,比如编译工具或测试框架。这些依赖不会被包含在生产环境的部署中。我的理解是能放这里的都尽量放这里,别让打出的包太臃肿。

  • repository : 这个字段指定了项目的存储库信息(第一眼我以为这是指定发包maven仓的呢)。这个字段通常包含类型(如git)、URL(项目的存储库地址),以及可能的分支(如master)。这有助于其他开发者找到项目的源代码。例如:

JSON 复制代码
"repository": {
  "type": "git",
  "url": "https://github.com/bby580/electron-demo.git"
}

将 Electron 加入项目

现在项目里空空荡荡,只有package.json一个光杆司令,我们将electron引入进来:

bash 复制代码
npm install --save-dev electron electron-builder

附带上了构建所需依赖,这里都不指定版本,用最新的。

这时候应该添加主程序了,为了方便管理,我选择创建一个文件夹专门存储于electron有关的代码,并将入口改为 main.js,如下图:

新建 main.js 文件,只填入一条打印语句:

js 复制代码
console.log("Hello World!");

引入 TypeScript

添加依赖

将 typescript 添加项目:

bash 复制代码
 npm install --save-dev typescript eslint

配置文件

添加ts的配置文件: tsconfig.json

tsconfig.json 是一个用于配置TypeScript编译器的JSON文件,它可以用来指定TypeScript项目的根文件、编译选项和类型检查规则,以下配置使用GPT添加了注释。

json 复制代码
// 这个 tsconfig.json 文件是用来配置 TypeScript 编译器的
{
  "compilerOptions": {
    // 指定编译后的目标 JavaScript 版本,ESNext 表示使用最新的 ES 标准
    "target": "ESNext",
    // 指定是否使用 class 字段的新语法,true 表示使用,false 表示使用旧的赋值语法
    "useDefineForClassFields": true,
    // 指定要包含在编译中的库文件,这里包含了 ES2020 标准库,DOM 库和 DOM 可迭代库
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    // 指定生成的模块代码的类型,ESNext 表示使用最新ES标准,即使用 import 和 export 关键字
    "module": "ESNext",
    // 指定是否跳过对所有声明文件(*.d.ts)的类型检查,true 表示跳过,可以提高编译速度,但可能会忽略一些类型错误
    "skipLibCheck": true,
    // 指定模块解析策略,bundler 表示使用与打包工具(如 webpack 或 rollup)相同的策略,即尝试解析相对路径和非相对路径的模块
    "moduleResolution": "bundler",
    // 指定是否允许导入扩展名为 .ts 的文件,true 表示允许,false 表示不允许
    "allowImportingTsExtensions": true,
    // 指定是否支持导入 JSON 模块,true 表示支持,false 表示不支持
    "resolveJsonModule": true,
    // 指定是否将每个文件作为单独的模块,true 表示是,false 表示否,这对于使用 babel 或 ts-loader 的项目有用
    "isolatedModules": true,
    // 指定是否生成输出文件,true 表示不生成,false 表示生成,这对于只进行类型检查的项目有用
    "noEmit": true,
    // 指定是否允许编译 JavaScript 文件,true 表示允许,false 表示不允许
    "allowJs": true,
    // 指定是否启用所有严格类型检查选项,true 表示启用,false 表示不启用
    "strict": true,
    // 指定是否报告未使用的局部变量错误,false 表示不报告,true 表示报告
    "noUnusedLocals": false,
    // 指定是否报告未使用的参数错误,false 表示不报告,true 表示报告
    "noUnusedParameters": false,
    // 指定是否报告 switch 语句中缺少 break 或 return 的错误,true 表示报告,false 表示不报告
    "noFallthroughCasesInSwitch": true
  },
  // 指定要包含在编译中的文件或目录的列表,这里包含了 web 和 electron 两个目录
  "include": ["web", "electron"]
}

顺便查一下 module 选项可以常用的模式:

  • None:不生成任何模块代码,适用于脚本或全局作用域的代码。
  • CommonJS:使用 requiremodule.exports 的模块系统,适用于 Node.js 或其他 CommonJS 兼容的环境。
  • AMD:使用 definerequire 的模块系统,适用于异步加载的场景,如 RequireJS。
  • System:使用 System.register 的模块系统,适用于动态加载的场景,如 SystemJS。
  • UMD:使用通用模块定义(Universal Module Definition)的模块系统,适用于多种环境,如浏览器或 Node.js。
  • ESNext:使用最新的 ES 标准的模块系统,使用import(),用于支持原生 ES 模块的环境,如现代浏览器。

运行

将 js 文件换成 ts,并将package.json 里的 main 地址修改成tsc输出路径:

json 复制代码
"main": "dist-electron/main.js",

还需修改启动脚本,先编译再启动:

json 复制代码
"scripts": {
  "start": "tsc && electron ./dist-electron/main.js"
},

整体如下:

引入 ESLint

这是一个可选项,对于个人项目而言,不配这玩意儿也完全没问题,但是还是那句话,我们的目的是学习,所以还是搞里头!

添加依赖

ESLint 是一个用来识别和报告 JavaScript 代码中的模式的静态代码分析工具1。ESLint 可以帮助你找到和修复代码中的问题,提高代码的质量和一致性。ESLint 是完全可配置的,你可以自定义规则,使用自定义解析器,或者使用预定义的配置集合2。

记得以前还有个TSLint的,后面好像被 TypeScript 官方弃用了,我们不纠结,直接用 ESLint。

添加 eslint 和 其相关插件:

bash 复制代码
 npm install --save-dev eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser

配置文件

添加 ESLint 的配置文件 eslintrc.cjs

eslintrc.cjs 是一个用于配置ESLint的JavaScript文件,它可以在使用"type":"module"的JavaScript包中运行ESLint。

js 复制代码
// 这个 .eslintrc.cjs 文件是一个用于配置 ESLint 的 JavaScript 文件,它可以在使用 "type":"module" 的 JavaScript 包中运行 ESLint[^1^] [^2^]
module.exports = {
  // 表示这是最顶层的配置文件,ESLint 会停止在父文件夹中查找其他配置文件
  root: true,
  // 表示指定代码运行的环境,这里是浏览器和 ES2020 标准
  env: { browser: true, es2020: true },
  // 表示继承一些共享的配置,这里是 ESLint 推荐的配置,TypeScript 推荐的配置,和 React Hooks 推荐的配置
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended'
  ],
  // 表示指定要忽略的文件或目录,这里是 dist 和 .eslintrc.cjs
  ignorePatterns: ['dist', '.eslintrc.cjs'],
  // 表示指定要使用的解析器,这里是 TypeScript 的解析器
  parser: '@typescript-eslint/parser',
  // 表示指定要使用的插件,这里是 react-refresh 插件
  plugins: ['@typescript-eslint'],
  // 表示指定要启用或禁用的规则,以及它们的错误级别或选项
  rules: {
    // 启用 @typescript-eslint 插件的 no-unused-vars 规则,它会报告未使用的变量或参数,这里忽略所有变量,但不忽略参数
    '@typescript-eslint/no-unused-vars': [
      'error',
      { varsIgnorePattern: '.*', args: 'none' }
    ],
  },
}

测试

可添加脚本 lint,这里要注意使用--ext,否则默认不检查ts文件:

json 复制代码
"scripts": {
  "start": "tsc && electron ./dist-electron/main.js",
  "lint": "eslint ./ --ext ts,tsx --max-warnings 0"
}

执行结果如下:

引入 Vite

添加依赖

此事不着急去写逻辑,我们先把项目配置好。

Vite 是尤大在出Vue3时推出的新一代的前端构建工具,按理说使用React更好的选择应该是webpack,但谁让Vite上手简单呢?

使用Vite打包electron,只引Vite肯定是不行的,还需两个插件:vite-plugin-electronvite-plugin-electron-renderer,看名字就知道干啥的了。

bash 复制代码
npm install --save-dev vite vite-plugin-electron vite-plugin-electron-renderer

配置文件

1、Vite.config.ts

vite.config.ts 是一个用于配置Vite的TypeScript文件,它可以用来指定Vite项目的基本信息、插件、构建选项和服务端渲染设置。

ts 复制代码
import {defineConfig} from 'vite'
import electron from 'vite-plugin-electron/simple'
import * as path from 'path';


export default defineConfig({
  plugins: [
    electron({
      main: {
        entry: 'electron/main.ts',
      },
      preload: {
        input: path.join(__dirname, 'electron/preload.js'),
      },
      renderer: {},
    }),
  ]
})

2、tsconfig.node.json

tsconfig.node.json 是一个用于配置Node.js环境下的TypeScript编译器的JSON文件,它可以用来指定Node.js项目的根文件、编译选项和类型检查规则,以下配置也使用GPT添加了注释。

json 复制代码
// 这个tsconfig.node.json文件是用来配置Node.js环境下的TypeScript编译器的
{
  "compilerOptions": {
    // 启用项目引用,表示这个配置文件可以被其他配置文件引用
    "composite": true,
    // 跳过对所有声明文件的类型检查,可以提高编译速度,但可能会忽略一些类型错误
    "skipLibCheck": true,
    // 使用ESNext标准的模块系统,即使用import和export关键字
    "module": "ESNext",
    // 使用与打包工具相同的模块解析策略,即尝试解析相对路径和非相对路径的模块
    "moduleResolution": "bundler",
    // 允许从没有默认导出的模块中导入默认成员,例如import React from 'react'
    "allowSyntheticDefaultImports": true
  },
  // 只包含vite.config.ts文件,表示只对这个文件进行编译
  "include": ["vite.config.ts"]
}

那么为什么要创建 tsconfig. json 和 tsconfig.node.json两个 TypeScript 配置文件 ?

这是一个很好的问题。

  • Vite 的项目包含两种不同的环境:浏览器和 Node.js。浏览器是用来运行应用程序的,而 Node.js 是用来运行 Vite 本身和它的配置的。这两种环境有不同的模块系统、API 和约束,所以需要不同的编译选项和类型检查规则。
  • tsconfig.json 是一个通用的配置文件,它适用于浏览器环境,也就是你的应用程序的源代码。它使用 ES2020 标准的模块系统,即使用 import 和 export 关键字12。
  • tsconfig.node.json 是一个针对 Node.js 环境的配置文件,它适用于 Vite 的配置文件,也就是 vite.config.ts 文件。它使用 CommonJS 的模块系统,即使用 require 和 module.exports12。
  • tsconfig.node.json 会继承 tsconfig.json 的部分设置,但也会根据 Node.js 的特性进行一些调整。例如,tsconfig.node.json 会设置 module 为 CommonJS,而 tsconfig.json 会设置 module 为 ES202012。
  • tsconfig.json 会通过 references 字段引入 tsconfig.node.json 中的配置,这样可以启用项目引用的功能,即可以在不同的配置文件之间建立依赖关系。

测试

添加dev和build到scripts:

json 复制代码
"scripts": {
  "dev": "vite",
  "build": "tsc && vite build && electron-builder",
  "start": "tsc && electron ./dist-electron/main.js",
  "lint": "eslint ./ --ext ts,tsx --max-warnings 0"
}

直接运行 npm run dev

引入 React

创建一个窗口

先在主进程创建一个窗口,这个窗口加载百度主页。修改main.ts:

ts 复制代码
import {app, BrowserWindow} from 'electron'
import path from "node:path";

console.log('Hello World!')

app.whenReady().then(() => {
  const window = new BrowserWindow({
    width: 1100, height: 700,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  })
  window.loadURL('https://www.baidu.com')
  window.show()
})

添加依赖

shell 复制代码
# 添加依赖,与之前不同,这里是添加到 `dependencies` 中的
npm install react react-dom

# 添加 react 的 ts 类型信息
npm install --save-dev @types/react @types/react-dom

# 添加 Vite 的 react 插件
npm install --save-dev @vitejs/plugin-react

添加文件

在根目录新建一个web文件夹,用于存放所有网页文件,并创建两个入口文件

├─ web
│  └─index.html
│  └─index.tsx

index.tsx 是 react 的入口文件,通过 index.html 被读取。在这个文件写了一句"Hello React!"

js 复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <h1>Hello React!</h1>
  </React.StrictMode>,
)

index.html 是 Vite 启动服务的入口文件,服务启动后从此处加载资源,我们在该文件中引入 index.tsx。默认情况下,index.html应该是在根目录的,具体见 官方文档,此处我想把它和react放在一起,用了多入口的方式,说不定以后还会再开一个页面呢!

index.html 默认写了一句"Hello, world!",与index.tsx中不同,因为我们要看看react是否会成功运行。

html 复制代码
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>electron-demo</title>
    </head>
    <body>
        <div id="root">
            <h1>Hello, world!</h1>
        </div>
        <!-- 以模块方式导入index.tsx -->
        <script type="module" src="index.tsx"></script>
    </body>
</html>

修改代码

修改 vite.config.ts,此处改动两处

  • 修改入口文件位置
  • 将插件注册:
ts 复制代码
import {defineConfig} from 'vite'
import electron from 'vite-plugin-electron/simple'
import react from '@vitejs/plugin-react'
import path from 'node:path';
import { resolve } from 'path'

export default defineConfig({
  build: {
    rollupOptions: {
      input: { // 这里修改了配置文件入口
        index: resolve(__dirname, '/web/index.html')
      },
    },
  },
  plugins: [
    react(), // 添加 react 插件
    electron({
      main: {
        entry: 'electron/main.ts',
      },
      preload: {
        input: path.join(__dirname, 'electron/preload.ts'),
      },
      renderer: {},
    }),
  ]
})

修改主进程 main.ts,让窗口浏览器加载 Vite 服务器:

ts 复制代码
import {app, BrowserWindow} from 'electron'
import path from "node:path";

// Vite 服务器地址,这里使用了web文件夹中的入口
const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL+'web/'
app.whenReady().then(() => {
  const window = new BrowserWindow({
    width: 1100, height: 700,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  })

  window.loadURL(VITE_DEV_SERVER_URL)
  window.show()
})

结果

如此,程序完美运行:

另外,我试了下,打包还是有问题,下周末再研究吧,先不卷了。

源码:github.com/bby580/elec...

相关推荐
今天也想MK代码2 天前
在Swift开发中简化应用程序发布与权限管理的解决方案——SparkleEasy
前端·javascript·chrome·macos·electron·swiftui
yqcoder3 天前
electron 中 ipcRenderer 的常用方法有哪些?
前端·javascript·electron
yqcoder3 天前
electron 中 ipcRenderer 作用
前端·javascript·electron
伍嘉源4 天前
关于electron进程管理的一些认识
前端·javascript·electron
yqcoder4 天前
electron 设置最小窗口缩放
前端·javascript·electron
yqcoder5 天前
区分 electron 全屏和最大化
前端·javascript·electron
li.siyuan5 天前
electron + vue 打包完成后,运行提示 electrion-updater 不存在
前端·vue.js·electron
努力挣钱的小鑫6 天前
【客户端开发】electron 中无法使用 js-cookie 的问题
前端·javascript·electron
蓝胖子不是胖子6 天前
尝鲜electron --将已有vue/react项目转换为桌面应用
vue.js·react.js·electron
非晓为骁6 天前
windows 下 electron-builder ERR_ELECTRON_BUILDER_CANNOT_EXECUTE 报错处理
javascript·windows·electron