動態

詳情 返回 返回

electron-build報錯:cannot find module/ valid " main " entry

解決electron-build打包後運行app報錯:cannot find module xxx/ Please verify that the package . json has a valid " main " entry

先看一個簡單報錯:

圖片

或者類似這種:

圖片

解決方法:

檢查package. Json 中是否寫了“main”,這裏的“main”必須寫,且應當使用npm指令build的dist-electron文件夾中的main.js

那麼有人會問了:還沒有跑過npm命令呢,沒有dist-electron需要自己構建一個嗎?答案是不需要,見附錄1

//package.json
{
    "name": "DXY 1st",
    "version": "5.3.0",
    "private": true,
    "description": "DXY 666",
    "author": "DXY",
    "license": "MIT",
    "main": "dist-electron/main.js",

既然你已經會修bug了,那我們就來打boss吧(截圖我搞丟了,只剩文字了):

Background:打包已有的vue3工程(vue3自己的main.js被放進electron的main.js裏了),preload.js、renderer.js都用的官網的示例代碼,跑完npm run dev總是出bug,且無法transform main.js

圖片

Unable to find Electron app at D :\…… .Cannot find module ' D :\ …… \ dist - electron \ main . js '. Please verify that the package . json has a valid " main " entry

目前為止我沒找到針對這個bug的貼子,那就讓我來水一貼吧:

檢查並修正 main.js中的導入

打開報錯信息中提到的 D:\……\dist-electron\main.js文件:

//問題代碼main.js

/*先寫electron的app塊兒

*/

const { app, BrowserWindow, ipcMain} = require('electron')

const path = require('path')

const createWindow = () => {

  const win = new BrowserWindow({

    width: 800,

    height: 600,

    webPreferences: {

      preload: path.join(__dirname, 'preload.js')

    }

  })

  // 開發環境加載 Vite 開發服務器,生產環境加載打包後的文件

  if (process.env.NODE_ENV === 'development') {

    win.loadURL('你的web網址')

  } else {

    win.loadFile('dist/index.html')

  }

    // win.loadFile('index.html')

}



app.whenReady().then(() => {

  ipcMain.handle('ping', () => 'pong')

  createWindow()



  app.on('activate', () => {

    if (BrowserWindow.getAllWindows().length === 0) {

      createWindow()

    }

  })

})



app.on('window-all-closed', () => {

  if (process.platform !== 'darwin') {

    app.quit()

  }

})

/*以下是雜糅在一塊兒的Vue工程main.js代碼

*/

import { createApp } from 'vue'

import { createPinia } from 'pinia'

import * as ElementPlusIconsVue from '@element-plus/icons-vue'

import App from './App.vue'

import router from './router'

/*………*/

查找其中是否有導入 App.vue的部分(不是説某一行import,而是説一整個相關的代碼塊兒),這才是問題的根源,是因為:主進程的代碼不應該直接導入前端組件,主進程文件(如 main.js)和渲染進程文件應被正確區分和管理,所以你首先需要思考你導入它的目的:

如果是為了創建瀏覽器窗口(BrowserWindow)並加載頁面,正確的方式應該是使用 loadFile或 loadURL方法來加載一個已經編譯好的 HTML 文件(如 index.html),而不是直接導入 .vue文件

具體的做法就是:

1.不要直接使用或拼接Vue工程的main.js,應創建獨立的 Electron 主進程文件 electron/main.js:附錄2

2.更新vite.config.ts配置

//vite.config.ts
export default defineConfig({
    base: './',
    plugins: [
        vue(),
        electron({
            main: {
                entry: 'electron/main.js',//更新主入口路徑
            }
  1. 更新 package.json
//package.json
{
    "name": "DXY 1st",
    "version": "5.3.0",
    "private": true,
    "description": "DXY 666",
    "author": "duandashuaige",
    "license": "MIT",
    "main": "dist-electron/main.js",//修改主入口

這個問題高發於electron+vue全家桶場景,即對已有的Vue工程打包,雖然不算是難點,但也很容易被忽略

附錄:

1.新建electron文件夾,並填充main.js,preload.js,然後終端跑npm run dev會報錯:

圖片

同時會自動生成一個dist-electron文件夾,包含兩個js:

圖片

裏面的倆js和之前填充的electron文件夾內的main.js和preload.js的內容是一樣的,但是這倆js是經過編譯的,未經編譯過的文件electron讀不懂,因此一定要先編譯再打包!具體原因可以參考我的另一篇貼子:解決electron打包Vue工程(Vite)報錯electron : Failed to load URL : xxx... with error : ERR _CONNECTION_REFUSED

2.

// electron/main.js

const { app, BrowserWindow, ipcMain } = require('electron')

const path = require('path')



const createWindow = () => {

  const win = new BrowserWindow({

    width: 1200,

    height: 800,

    webPreferences: {

      preload: path.join(__dirname, 'preload.js')

    }

  })



  // 開發環境加載 Vite 開發服務器,生產環境加載打包後的文件

  if (process.env.NODE_ENV === 'development') {

    win.loadURL('你的web網址')

  } else {

    win.loadFile('dist/index.html')

  }

}



app.whenReady().then(() => {

  ipcMain.handle('ping', () => 'pong')

  createWindow()



  app.on('activate', () => {

    if (BrowserWindow.getAllWindows().length === 0) {

      createWindow()

    }

  })

})



app.on('window-all-closed', () => {

  if (process.platform !== 'darwin') {

    app.quit()

  }

})

3.官網示例代碼4件套,供大家參考:

/*main.js

*/

const { app, BrowserWindow, ipcMain } = require('electron/main')



const path = require('node:path')



const createWindow = () => {

  const win = new BrowserWindow({

    width: 800,

    height: 600,

    webPreferences: {

      preload: path.join(__dirname, 'preload.js')

    }

  })

  win.loadFile('index.html')

}

app.whenReady().then(() => {

  ipcMain.handle('ping', () => 'pong')

  createWindow()

})
/*preload.js

*/

const { contextBridge } = require('electron/renderer')



contextBridge.exposeInMainWorld('versions', {

  node: () => process.versions.node,

  chrome: () => process.versions.chrome,

  electron: () => process.versions.electron

})
/*index.html

*/

<!DOCTYPE html>

<html>

  <head>

    <meta charset="UTF-8" />

    <meta

      http-equiv="Content-Security-Policy"

      content="default-src 'self'; script-src 'self'"

    />

    <meta

      http-equiv="X-Content-Security-Policy"

      content="default-src 'self'; script-src 'self'"

    />

    <title>Hello from Electron renderer!</title>

  </head>

  <body>

    <h1>Hello from Electron renderer!</h1>

    <p>👋</p>

    <p id="info"></p>

  </body>

  <script src="./renderer.js"></script>

</html>
/*renderer.js

*/

const information = document.getElementById('info')

information.innerText = `This app is using Chrome (v${window.versions.chrome()}), Node.js (v${window.versions.node()}), and Electron (v${window.versions.electron()})`

官網:使用預加載腳本 | Electron

user avatar
0 用戶, 點贊了這篇動態!

發表 評論

Some HTML is okay.