Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请教一下vite-renderer.config中的resolveElectron函数 #52

Closed
qianjiachun opened this issue Jan 18, 2022 · 5 comments
Closed

请教一下vite-renderer.config中的resolveElectron函数 #52

qianjiachun opened this issue Jan 18, 2022 · 5 comments
Labels
documentation Improvements or additions to documentation

Comments

@qianjiachun
Copy link

resolveElectron似乎在plugins中删掉也是可以正常调试和打包的。
想请教一下这个函数的意图和作用。
最近在学习electron相关技术,该项目让我受益匪浅,感谢作者

@caoxiemeihao caoxiemeihao added the documentation Improvements or additions to documentation label Jan 18, 2022
@caoxiemeihao
Copy link
Member

caoxiemeihao commented Jan 18, 2022

一些前奏解释

一、 首先这个项目的本意不希望用户在 Renderer-process 中使用 Electron、NodeJs API

二、 resolveElectron 插件设计目的是为了一些仍然希望在 Renderer-process 中使用 Electron、NodeJs API 的用户
  然后他们会在 Main-process 中开启 nodeIntegration: true contextIsolation: true 这会直接导致一个报错 __dirname is not defined

三、 为此为了解决上述的潜在问题,我设计了 resolveElectron 这也解释了“如果不去触碰上述两点 resolveElectron 可有可无”


经典报错: __dirname is not defined

一切要从 ESModule 开始 👉 NodeJs 在 ESModule 下 No __filename or __dirname

  vite 在开发时期强依赖 ESModule 打包时期默认也是 ESModule

众所周知 👉 electron 共有三种环境/三种状态即: NodeJs、Electron-Main、Electron-Renderer

  使用 vite 启动 electron 时候,为 NodeJs 运行环境,node_modules/electron 包导出的只是一个 electron.exe 的文件路径
  当使用 vite 且在 Electron-Renderer 中使用 import electron from 'electron' 时候 vite 的默认行为会使用 NodeJs 环境下的 electron —— 遂报错

node_modules/electron/index.js 👉 真实情况此文件会被编译到 .vite 缓存目录下

const fs = require('fs');
const path = require('path');

// 🐞 🐞 🐞 🐞 __dirname is not defined 报错就会出现在下面这行 🐛 🐛 🐛 🐛
const pathFile = path.join(__dirname, 'path.txt');

function getElectronPath () {
  let executablePath;
  if (fs.existsSync(pathFile)) {
    executablePath = fs.readFileSync(pathFile, 'utf-8');
  }
  if (process.env.ELECTRON_OVERRIDE_DIST_PATH) {
    return path.join(process.env.ELECTRON_OVERRIDE_DIST_PATH, executablePath || 'electron');
  }
  if (executablePath) {
    return path.join(__dirname, 'dist', executablePath);
  } else {
    throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again');
  }
}

module.exports = getElectronPath();

Renderer-process 中正确加载 Electron、NodeJs API

一、 设想下如果我们避开 vite 的默认行为,Renderer-process 中的 import electron 'electron' 本意是指的 Electron 的内置模块,就像 NodeJs 中集成了 fs、path 那样

二、 vite 最重要的概念 bundless 我喜欢叫 non-bundle
vite 在 web 开发下,也就是 Renderer-process 加载的通过 vite serve 启动的本地服务代码就是 bundless 形式,这种代码全部是 ESModule 格式

  • 思考一:
    Renderer-process 开启 NodeJs 集成后 require 函数就有了,那么如果我用了 require('electron') 可以工作么?答案是可以的
    而且还能避开浏览器识别 import 而向 vite 发出 electron 请求!妙啊~
    require('electron') 真是好从西啊 -- 但是我还想用 import electron from 'electron' 啊啊啊啊~

  • 思考二:
    我让你用 import electron from 'electron' 允许请求到 vite 服务器;我给你返回 require('electron') 不就行了么~!哎 - 就是玩儿~!


import -- Electron、NodeJS API 设计

一、 在 vite 中通过配置 resolve.aliaselectron 指向一个我做的文件 - 例如:

项目目录/node_modules/.自定义文件夹/electron.js

/**
 * 🚧 下面的代码会被 vite 抛到 Renderer-process 中运行
 */
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,
}
  • alias 配置改一下
config.resolve.alias = {
  electron: '项目目录/node_modules/.自定义文件夹/electron.js',
}
  • 生成下缓存文件
// 生成缓存文件代码

🚧 实际中 “alias 配置,缓存文件生成” 这两件事儿交给 vite-plugin-resolve 去做!

二、 同理可证 NodeJs 模块也可以像 Electron 那样设计

就不一一列出了。。。

三、 最后 resolveElectron 中还有个 vite-plugin-electron-config

  • vite 会预构建所有依赖的模块,并且放到 node_modeules/.vite 缓存目录中,且优先命中
    我们需要 打断下 vite 的缓存命中 -- 不要编译我们辛辛苦苦做好的 Electron、NodeJs 内置模块的 ESModule 版本

  • 2022-01-30 该功能已内置到 vite-plugin-resolve

config.optimizeDeps.exclude = [
  'electron',
  'fs',
  'path',
  ...其他 NodeJs 内置模块
];

@qianjiachun
Copy link
Author

感谢解答!

@K3NZ11
Copy link

K3NZ11 commented Jun 21, 2022

@caoxiemeihao I think this documentation is really helpful. If you don't mind, can you add an English translation for this please?

@caoxiemeihao
Copy link
Member

@K3NZ11 Thanks for your feedback, I'll trying to do it, but my english is poor. 😅

@caoxiemeihao
Copy link
Member

文档已发布在 知乎专栏 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants