Skip to content
索引

vite-electron

vite项目中引入electron

sh
yarn add -D electron
yarn add -D electron

根目录新建electron.ts

ts
// 控制应用生命周期和创建原生浏览器窗口的模组
const { app, BrowserWindow } = require("electron")
const path = require("path")

function createWindow() {
  // 创建浏览器窗口
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  })

  // 加载vite开发服务器
  mainWindow.loadURL("http://localhost:3000/")

  // 打开开发工具
  // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
  createWindow()

  app.on("activate", function () {
    // 如果没有打开的窗口,那么会创建一个窗口
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此,通常对程序和它们在
// 任务栏上的图标来说,应当保持活跃状态,直到用户使用 Cmd + Q 退出。
app.on("window-all-closed", function () {
  if (process.platform !== "darwin") app.quit()
})
// 控制应用生命周期和创建原生浏览器窗口的模组
const { app, BrowserWindow } = require("electron")
const path = require("path")

function createWindow() {
  // 创建浏览器窗口
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  })

  // 加载vite开发服务器
  mainWindow.loadURL("http://localhost:3000/")

  // 打开开发工具
  // mainWindow.webContents.openDevTools()
}

// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
  createWindow()

  app.on("activate", function () {
    // 如果没有打开的窗口,那么会创建一个窗口
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此,通常对程序和它们在
// 任务栏上的图标来说,应当保持活跃状态,直到用户使用 Cmd + Q 退出。
app.on("window-all-closed", function () {
  if (process.platform !== "darwin") app.quit()
})

package.json设置main

json
"main": "electron.ts",
"main": "electron.ts",

electron热更新

vite开发服务器具备热更新功能,electron开发时直接加载vite开发服务器,即可实现electron开发热更新,即下方这句代码(代码已存在于上方的electron.ts中)

ts
 mainWindow.loadURL("http://localhost:3000/")
 mainWindow.loadURL("http://localhost:3000/")

因为electron开发需要等待vite先行启动开发服务器,加载其url, 所以需要安装两个库:

  • concurrently:阻塞运行多个命令,-k参数用来清除其它已经存在或者挂掉的进程
  • wait-on:等待资源,此处用来等待url可访问
sh
yarn add -D concurrently wait-on
yarn add -D concurrently wait-on

更新package.jsonscripts修改如下:

json
 "scripts": {
    "vite:dev": "vite",
    "electron": "wait-on tcp:3000 && electron .",
    "dev": "concurrently -k \"yarn vite:dev\" \"yarn electron\"",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
  },
 "scripts": {
    "vite:dev": "vite",
    "electron": "wait-on tcp:3000 && electron .",
    "dev": "concurrently -k \"yarn vite:dev\" \"yarn electron\"",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
  },
  • yarn electron等待tcp协议3000端口可访问,然后执行electron
  • yarn dev阻塞执行开发服务器运行和yarn electron命令

运行项目只要执行命令yarn dev即可,当修改项目文件时,桌面应用也将自动更新

exports is not defined

问题描述

开发环境是可以正常使用vue-router的,但打包后electron控制台出现Uncaught ReferenceError: exports is not defined报错 找了下是vue-router源码里面开头代码的问题Object.defineProperty(exports, '__esModule', { value: true });,

vite.config.ts中加入rollupOptions: {output: {format: "cjs"}},编译为commonjs就解决了问题

ts
 build: {
    sourcemap: true,
    outDir: "../../dist/renderer",
    rollupOptions: {
      output: {
        format: "cjs"
      }
    }
  },
  
 build: {
    sourcemap: true,
    outDir: "../../dist/renderer",
    rollupOptions: {
      output: {
        format: "cjs"
      }
    }
  },
  

官方关于这个问题的探讨

https://github.com/electron-vite/electron-vite-vue/issues/103

总结一下,官方插件影响了es模块的正常使用,导致vue-router出现报错

解决办法一(推荐)

针对此,官方给出了解决方案

vite.config.ts

ts
import polyfillExports from 'vite-plugin-electron/polyfill-exports'

export default {
  plugins: [
    // ...other plugins
    polyfillExports(),
  ],
}
import polyfillExports from 'vite-plugin-electron/polyfill-exports'

export default {
  plugins: [
    // ...other plugins
    polyfillExports(),
  ],
}

解决办法二

由原先的

ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: () => import("../pages/index.vue")
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: () => import("../pages/index.vue")
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

改为

ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"

import index from "../pages/index.vue"

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: index
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"

import index from "../pages/index.vue"

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: index
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

解决办法三

我个人使用的是vite-plugin-pages插件,动态生成路由信息,如果你也使用了这个插件,如下配置,也可以正常打包

vite.config.ts

ts
build: {
    outDir: "../../dist/renderer",
    emptyOutDir: true,
    sourcemap: true
    rollupOptions: {
      output: {
      format: "commonjs"
      }
    }
  }
build: {
    outDir: "../../dist/renderer",
    emptyOutDir: true,
    sourcemap: true
    rollupOptions: {
      output: {
      format: "commonjs"
      }
    }
  }

Released under the MIT License.