webpack 5 如何以 target 为 electron 构建主进程与渲染进程代码
2026/9/11 14:14:50 网站建设 项目流程

webpack 5 如何以 target 为 electron 构建主进程与渲染进程代码

【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack

在把 JS 代码打进 Electron 应用时,主进程和渲染进程里require("app")require("ipc-renderer")这类 Electron 内置模块不能被打包进产物——它们在运行环境里由 Electron 提供,应该保持为 external,由运行时加载。webpack 5 通过target选项直接支持这个场景:指定electron-mainelectron-preloadelectron-renderer,webpack 会自动启用对应的externalsPresets,把该进程可用的内置模块按上下文分别外部化。本文说明如何为两个进程各配置一次构建,以及产物应满足什么特征来验证配置生效。

适用前提:使用 webpack 5 打包一个同时包含主进程与渲染进程代码的 Electron 应用。渲染进程代码若使用了浏览器 API,target 中还包含 web 语义,这一点由 webpack 内部的目标解析决定(见 lib/config/target.js 中electron[X[.Y]]-main/preload/renderer的定义:web: context !== "main",即只有 main 上下文不带 web 环境,preload/renderer 视为有 web 环境)。

target 的三个取值与进程上下文

在 lib/config/target.js 中,target 的格式为:

electron[X[.Y]]-main/preload/renderer

其中X.Y是可选的 Electron 版本号。格式描述为 "Electron in version X.Y. Script is running in main, preload resp. renderer context."。常用取值:

target含义
electron-main脚本运行在 Electron 主进程
electron-preload脚本运行在 preload 脚本
electron-renderer脚本运行在渲染进程(node integration)
electron30-main同上,但额外声明 Electron 版本号为 30,用于按版本裁剪环境特性

target 字符串中的版本号会映射到一组环境能力,例如 lib/config/target.js 中给出的版本相关能力:Electron 15 起 Node 核心模块可带node:前缀(nodePrefixForCoreModules: v(15))、Electron 11 起支持动态import()dynamicImport: v(11))、Electron 28 起支持 ESM(module: v(28))、Electron 12 起渲染进程支持顶层 await 等。这些值决定了 webpack 为该版本生成代码时允许使用哪些语法特性。

webpack 如何自动外部化 Electron 内置模块

target含 electron 时,lib/config/defaults.js 会自动推导externalsPresetselectron总为 true,electronMain/electronPreload/electronRenderer分别由 target 中的上下文决定(见 lib/config/defaults.js)。这三个 preset 的官方描述来自 schemas/WebpackOptions.json:

  • electron:把 main 和 preload 上下文共有的内置模块(如electronipcshell)当作 external,用require()加载;
  • electronMain:把 main 上下文可用的内置模块(如appipc-mainshell)当作 external;
  • electronPreload:把 preload 上下文可用的内置模块(如web-frameipc-renderershell)当作 external;
  • electronRenderer:把 renderer 上下文可用的内置模块(如web-frameipc-renderershell)当作 external。

具体外部化的模块清单在 lib/electron/ElectronTargetPlugin.js 中定义:

  • 共享模块(SHARED_MODULES):clipboardcrash-reporterelectronipcnative-imageoriginal-fsscreenshell
  • 主进程模块(MAIN_MODULES):appauto-updaterbrowser-windowcontent-tracingdialogglobal-shortcutipc-mainmenumenu-itempower-monitorpower-save-blockerprotocolsessiontrayweb-contents
  • 渲染进程模块(RENDERER_MODULES):desktop-captureripc-rendererremoteweb-frame

也就是说,用electron-main构建时,appipc-main等会保持为 external,而ipc-renderer不会被外部化;用electron-renderer构建时则相反。如果只写electron而不带-main等上下文后缀,则只启用共享模块的外部化(lib/WebpackOptionsApply.js 中,当三个细粒度 preset 都未启用时传入undefined上下文,只外部化 SHARED_MODULES)。

配置示例

主进程与渲染进程的上下文不同,需要用两套 target。下面是一个完整的webpack.config.js示例:

const path = require("path"); /** @type {import('webpack').Configuration} */ module.exports = [ { // 主进程 target: "electron-main", entry: { main: path.resolve(__dirname, "src/main.js"), }, output: { path: path.resolve(__dirname, "dist"), filename: "[name].js", }, }, { // 渲染进程 target: "electron-renderer", entry: { renderer: path.resolve(__dirname, "src/renderer.js"), }, output: { path: path.resolve(__dirname, "dist"), filename: "[name].js", }, }, ];

示例中的src/main.jssrc/renderer.js与输出目录dist是占位路径,替换为你项目里实际的入口文件与输出位置。src/main.js里可以const { app, ipcMain } = require("electron")src/renderer.js里可以const { ipcRenderer } = require("electron")——这些引用都会按上文的清单外部化,而不是被打包。

如果应用还有 preload 脚本,可以加第三个配置对象,target 用electron-preload,配置结构与上面一致。

如果你的项目对 Electron 版本有明确下限,也可以把 target 写成带版本号的形式,如electron30-main,webpack 会据此生成该版本支持的语法(例如顶层 await 只在 Electron 12+ 的渲染进程产物中可用)。

执行构建

npx webpack --config webpack.config.js

npx会调用项目node_modules中的 webpack CLI;前提是已在项目内安装 webpack(如yarn add -D webpack webpack-clinpm i -D webpack webpack-cli)。多配置数组下,webpack 会依次为 main 和 renderer 生成构建,产物落在各自配置的output.path中。

验证产物

构建完成后,验证方式是对照 lib/electron/ElectronTargetPlugin.js 与 schemas/WebpackOptions.json 中"external +require()加载"的说明来检查产物:

  1. 在产物文件中检索被外部化模块的引用形式。以 main 产物为例,源码中的require("electron")require("app")require("ipc-main")应原样保留为require(...)调用,而不是被替换为打包进来的模块实现;renderer 产物中require("electron")require("ipc-renderer")同理。
  2. 检查产物中不包含这些内置模块的实现代码。例如 main 产物中不应出现browser-windowsession等模块的实现,它们只应以 external 依赖的形式出现在产物里。
  3. stats检查 external 依赖:运行构建时 webpack 的 stats 输出会把require("app")这类模块列为 external;也可以用npx webpack --config webpack.config.js --json > stats.json导出 JSON,检索其中 external 条目是否覆盖你代码中用到的内置模块名。
  4. 反向检查:在 renderer 产物中,require("app")这种主进程模块不会被外部化(它不在 RENDERER_MODULES 清单里),如果你的渲染代码误引用了主进程模块,说明代码放错了上下文,而不是 webpack 配置问题。

关于 ESM 输出的一个警告

webpack 5 还支持output.module(ESM 输出)。当output.module启用且 target 的 Electron 版本支持 ESM 时,内置模块会以外部的module-import形式加载;若output.module启用但 target 对应的 Electron 版本不支持 ESM,webpack 会降级为node-commonjs并在产物中追加一条编译警告,原文为:

'output.module' is enabled, but the targeted electron version does not support ECMAScript modules (added in electron 28). Electron built-in modules are externalized as 'node-commonjs'.

见 lib/WebpackOptionsApply.js。即 ESM 支持从 Electron 28 开始;目标版本低于 28 时出现这条警告属于预期行为,外部化类型仍按node-commonjs处理。构建时看到这条警告,先确认你的 target 版本号是否写对(如electron28-renderer),再判断是否需要处理。

边界与限制

  • target 不带上下文后缀的electron只外部化共享模块清单,主进程/渲染进程各自的模块清单不会生效;要完整外部化,必须使用-main/-preload/-renderer后缀(lib/electron/ElectronTargetPlugin.js)。
  • preload 与 renderer 使用同一份 RENDERER_MODULES 清单(lib/electron/ElectronTargetPlugin.js),即 preload 产物中外部化的内置模块与 renderer 相同,不含app等主进程模块。
  • commonjs类别的引用(即require)无论外部化类型如何都会输出为node-commonjs,这是为了在模块产物下保持require兼容性(lib/electron/ElectronTargetPlugin.js)。
  • 内置模块之外的 npm 依赖仍会被正常打包;Electron 的外部化只针对上面列出的内置模块清单。

完成上述配置与验证后,main 与 renderer 两份产物即可分别被 Electron 主进程和渲染进程直接加载,内置模块的 require 会在运行时由 Electron 解析。

【免费下载链接】webpackA bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.项目地址: https://gitcode.com/GitHub_Trending/web/webpack

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询