打包Electron vue vite应用时找不到Preload JS

问题描述 投票:0回答:1

我正在尝试构建一个 vue 3 应用程序,使用 vite 编译并使用 Electron 打包,无需任何插件。这是我到目前为止所拥有的:

文件夹结构:

Project
 |    
 +-- electron
 |  |  
 |  +-- main.js
 |  +-- preload.js
 |    
 +-- src
 |  |  
 |  +-- main.js
 |  +-- App.vue
 |    
 +-- package.json
 |    
 +-- vite.config.js

电子/main.js

import { app, BrowserWindow } from "electron";
import path from "path"
const __dirname = path.resolve();

const createWindow = () => {
    const mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            contextIsolation: true,
            enableRemoteModule: false,
            preload: path.join(app.getAppPath(), 'preload.js'),
        },
    });

    if (app.isPackaged) {
        try {
            mainWindow.loadFile('app://./index.html').catch(e => console.log(e));
        }
        catch (e) {
            console.log(e);
        }
    }
    else {
        mainWindow.loadURL('http://localhost:3000');
    }
};

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

app.whenReady().then(createWindow);

预加载.js

window.addEventListener('DOMContentLoaded', () => {
    console.log('Preload script loaded');
});

src/main.js

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app')

package.json

{
  "name": "testme",
  "version": "0.0.1",
  "description": "demo app",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "electron:start": "electron electron/main.js",
    "start": "vite & electron electron/main.js",
    "buildElectron": "npx electron-builder build --mac"
  },
  "dependencies": {
    "vue": "^3.5.10"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.1.4",
    "electron": "^33.0.0-beta.8",
    "electron-builder": "^25.1.7",
    "vite": "^5.4.8"
  },
  "main": "electron/main.js",
  "type": "module",
  "build": {
    "appId": "com.ex.me",
    "productName": "TEST 1",
    "files": [
      "dist/**/*",
      "electron/**/*",
      "preload.js"
    ],
    "directories": {
      "buildResources": "assets"
    },
    "mac": {
      "target": [
        {
          "target": "zip",
          "arch": ["x64"]
        }
      ]
    }
  }
}

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path';

export default defineConfig({
  plugins: [vue()],
  base: './',
  server: {
    port: 3000,
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  build: {
    outDir: 'dist',
    sourcemap: true,
    rollupOptions: {
      input: {
        main: 'src/main.js',
        preload: './electron/preload.js',
      },
      external: ['electron'],
    },
  },
});

当我运行 npm start 时,该应用程序可以完美运行。换句话说,vite & electro electro/main.js 工作得很好。但是当我运行 buildElectron 时,它成功构建了应用程序,但我收到两个错误:

  1. 无法加载预加载脚本:和错误:ENOENT,在 /Users/xxx/Desktop/Projects/abc/new/dist/mac/Test 1.app/Contents/Resources/app.asar 中找不到 preload.js
  2. 不允许加载本地资源:file:///Users/xxx/Desktop/Projects/abc/...

看来 __dirname 可能引起了一些问题?由于找不到 preload.js。打包时查找或打开 index.html 似乎存在问题。有人知道如何调试这个吗?我尝试了很多组合来尝试使预加载可见,但没有成功。

javascript node.js electron vite
1个回答
0
投票

您在 Electron 构建过程中遇到的问题源于打包应用程序时如何处理路径,特别是关于

preload.js
index.html
文件。在打包的 Electron 应用程序中,像
preload.js
index.html
这样的文件被捆绑到
app.asar
存档中,并且使用
__dirname
(指向构建环境)访问它们不再像开发期间那样工作。

以下是解决这两个问题的方法:

1. 未找到预加载脚本

preload.js
文件的问题可能是由于您在打包环境中解析其路径的方式造成的。打包时,
__dirname
并不指向与开发时相同的位置。您需要调整生产版本的路径分辨率。

修改您的

electron/main.js
以根据应用程序是打包还是正在开发来以不同方式处理此问题:

import { app, BrowserWindow } from "electron";
import path from "path";
import fs from "fs";

const isDevelopment = !app.isPackaged;

const createWindow = () => {
    const mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            contextIsolation: true,
            enableRemoteModule: false,
            preload: isDevelopment
                ? path.join(__dirname, '../electron/preload.js') // in development
                : path.join(app.getAppPath(), 'electron', 'preload.js'), // when packaged
        },
    });

    if (isDevelopment) {
        mainWindow.loadURL('http://localhost:3000');
    } else {
        mainWindow.loadFile(path.join(app.getAppPath(), 'dist', 'index.html'));
    }
};

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

app.whenReady().then(createWindow);

2. 加载本地资源(index.html)时出错

Electron 打包应用程序时,需要确保使用正确的路径来加载

index.html
文件。在生产中,
index.html
通常捆绑在
dist
文件夹中。您的
main.js
应使用
mainWindow.loadFile
而不是
loadURL
来加载它。

更改打包时处理加载 HTML 文件的代码:

if (isDevelopment) {
    mainWindow.loadURL('http://localhost:3000');
} else {
    mainWindow.loadFile(path.join(app.getAppPath(), 'dist', 'index.html')); // load from packaged app
}

3. 确保文件包含在包中

在您的

package.json
构建配置中,确保包含必要的文件,尤其是
preload.js
index.html
。您可能需要调整
files
字段以包含适当的路径:

"files": [
  "dist/**/*",         // include all built Vue files
  "electron/**/*",     // include the Electron-related files
  "preload.js"         // ensure preload.js is included
],

您还可以在构建后使用

preload.js
等工具检查
app.asar
内容来确认
app.asar
和其他文件是否已正确复制到
asar

4. 生产中的Vite基本URL

确保 Vite 在打包时正确配置为为应用程序提供服务。将

base
中的
vite.config.js
选项设置为
./
,这可确保使用相对路径:

export default defineConfig({
  plugins: [vue()],
  base: './',  // Ensure relative paths are used for production build
  ...
});

调试提示:

要调试打包的 Electron 应用程序,您可以在

mainWindow.webContents.openDevTools()
函数中临时设置
createWindow
。这将帮助您直接在打包环境中检查问题。

通过这些更改,您的预加载脚本应该正确加载,并且打包应用程序时应该正确找到

index.html
文件。

© www.soinside.com 2019 - 2024. All rights reserved.