electron-vite-vue: [🐞] exports is not defined

What did I do

renderer vite.config.ts

// 这个位置, 按你的样例更新了原先的脚手架
// import electron from 'vite-plugin-electron/renderer' 0.2.1
    plugins: [
        vue(),
        electron(),
        resolve(
            /**
             * Here you can specify other modules
             * 🚧 You have to make sure that your module is in `dependencies` and not in the` devDependencies`,
             *    which will ensure that the electron-builder can package it correctly
             */
            {
                // If you use electron-store, this will work
               // 'electron-store': 'const Store = require("electron-store"); export default Store;',
            }
        ),
    ],

// 原来是
    plugins: [
        vue(),
        resolveElectron(
            /**
             * Here you can specify other modules
             * 🚧 You have to make sure that your module is in `dependencies` and not in the` devDependencies`,
             *    which will ensure that the electron-builder can package it correctly
             * @example
             * {
             *   'electron-store': 'const Store = require("electron-store"); export default Store;',
             * }
             */
        ),
    ], 

/**
 * For usage of Electron and NodeJS APIs in the Renderer process
 * @see https://github.com/caoxiemeihao/electron-vue-vite/issues/52
 */
export function resolveElectron(
    resolves: Parameters<typeof resolve>[0] = {}
): Plugin {
    const builtins = builtinModules.filter((t) => !t.startsWith('_'))

    /**
     * @see https://github.com/caoxiemeihao/vite-plugins/tree/main/packages/resolve#readme
     */
    return resolve({
        electron: electronExport(),
        ...builtinModulesExport(builtins),
        ...resolves,
    })

    function electronExport() {
        return `
/**
 * For all exported modules see https://www.electronjs.org/docs/latest/api/clipboard -> Renderer Process Modules
 */
const electron = require("electron");
const {
  clipboard,
  nativeImage,
  shell,
  contextBridge,
  crashReporter,
  ipcRenderer,
  webFrame,
  desktopCapturer,
  deprecate,
} = electron;

export {
  electron as default,
  clipboard,
  nativeImage,
  shell,
  contextBridge,
  crashReporter,
  ipcRenderer,
  webFrame,
  desktopCapturer,
  deprecate,
}
`
    }

    function builtinModulesExport(modules: string[]) {
        return modules
            .map((moduleId) => {
                const nodeModule = require(moduleId)
                const requireModule = `const M = require("${moduleId}");`
                const exportDefault = `export default M;`
                const exportMembers =
                    Object.keys(nodeModule)
                        .map((attr) => `export const ${attr} = M.${attr}`)
                        .join(';\n') + ';'
                const nodeModuleCode = `
${requireModule}

${exportDefault}

${exportMembers}
`

                return {[moduleId]: nodeModuleCode}
            })
            .reduce((memo, item) => Object.assign(memo, item), {})
    }
}

// 这里没去动它, 因为我希望运行环境保持隔离
    webPreferences: {
      preload: join(__dirname, '../preload/index.cjs'),
      nodeIntegration: true,// 使用false
      contextIsolation: false, // 使用true
    },

What happened

直接按你当前脚手架的配置, dev是没有问题的, 但是打包之后, 入口文件就会出现 exports is not defined 似乎是什么模块没有正确打包

Expected

我不确定这是不是一个BUG, 或者说使用’vite-plugin-electron/renderer’时还需要一些额外的配置, 看了源码, 好像也没什么需要配置的, 旧脚手架里的export function resolveElectron 内的方法也被你拆分到vite-plugin-electron中了

Environment

  • OS: macOS 12.3.1 / windows11
  • electron-vue-vite version (or commit hash), e.g. v1.0.0

More detail


// import resolve from 'vite-plugin-resolve' 2.0.1
// 目前我是去掉'vite-plugin-electron/renderer'
// 按之前旧版本脚手架的 builtinModulesExport 和 electronExport 修改后使用, 这样做可以正常打包运行
    plugins: [
        vue(),
        resolve({
            electron: electronExport(), // 
            ...builtinModulesExport()
        }),
    ],

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 22 (7 by maintainers)

Most upvoted comments

简而言之:
In general:

如果你需要在 Renderer-porcess 中使用 Electron、Node.js API 时候,你必须指定 rollupOptions.output.format='cjs'
If you need use Electron, Node.js API in Renderer-process, you must be explicit specify rollupOptions.output.format=‘cjs’

// ❌ don't work
import fs from 'fs'
import electron from 'electron'

// ✅ work normally
const fs = require('fs')
const electron = require('electron')

否则,那么你可能没必要使用 vite-plugin-electron/renderer
Otherwise, you may not need to use vite-plugin-electron/renderer


此外,在没更好的方案之前 v0.4.2 新增了 vite-plugin-electron/polyfill-exports 修复该问题
In addition, Before there is no answer v0.4.2 add vite-plugin-electron/polyfill-exports for fix the problem.

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

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

2022-06-02

https://github.com/electron-vite/vite-plugin-electron/commit/e6decf42164bc1e3801e27984322c41b9c2724b7#r75138942

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

这个问题的答案,我也追踪到了。 现象是:electron-builder 执行后,会在release文件夹下出现一个空的${version}文件夹。 实际上这个文件夹并不是空文件夹,而是有隐藏文件macOS系统会默认将以点开头的文件设为隐藏文件。所以一开始我才没有看到。

After electron-builder execution, an empty ${version} folder will appear under the release folder.
In fact, it is not an empty folder. It contains the .icon-${outputFormat} files.
On MacOS, files named after . are invisible.

tree -al \$\{version\}/
${version}/
└── .icon-icns
    └── icon.icns

1 directory, 1 file

对应源码的位置为: https://github.com/electron-userland/electron-builder/blob/master/packages/app-builder-lib/src/platformPackager.ts#L684

electron-builder当发现有图标文件在项目中后,会调用icon … --out ???来将图标转格式。 而这段代码的第684行,path.resolve(this.projectDir, this.config.directories!.output!, `.icon-${outputFormat}`), 中 this.config.directories!.output!的值,就是项目中electron-builder.json中设置的release/${version}

如果你看了vite的源码就会发现,如果vite.config.ts里,root和build.outDir的关系不是父子文件夹的话,这个emptyOutDir是关闭的。而你的配置碰巧是这种情况。你的root是${project}/dist/renderer,outDir是${project}/packages/renderer ,而vite的源码里是判断root是否有outDir的开头。 https://github.com/vitejs/vite/blob/83d32d965e3abd78fe390e347923e68dfb6de773/packages/vite/src/node/build.ts#L584

这个在vite官方文档的描述里写的很清楚,和你看到源码里的注释不太一样。

https://cn.vitejs.dev/config/#build-emptyoutdir


草鞋没号:哈哈哈!学到了 🎉


大佬!加入这个项目可好

并且当在根目录下新建build文件夹(这是electron-builder默认的electron app icon放置的位置),并添加icon.png文件时,再打包,会在release文件夹下多出一个名为${name}空的文件夹


English:

And when you create a new build folder under the root directory (this is the default location of “electron app icon” of electron-builder) and add the “icon. png” file, and then run packaging, an empty folder named ${name} will be added under the release folder.