index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. "use strict";
  2. Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
  3. const fs = require("node:fs");
  4. const path = require("node:path");
  5. const node_module = require("node:module");
  6. const vite = require("vite");
  7. const esbuild = require("esbuild");
  8. const os = require("node:os");
  9. const keywords = [
  10. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words
  11. ...[
  12. "break",
  13. "case",
  14. "catch",
  15. "class",
  16. "const",
  17. "continue",
  18. "debugger",
  19. "default",
  20. "delete",
  21. "do",
  22. "else",
  23. "export",
  24. "extends",
  25. "false",
  26. "finally",
  27. "for",
  28. "function",
  29. "if",
  30. "import",
  31. "in",
  32. "instanceof",
  33. "new",
  34. "null",
  35. "return",
  36. "super",
  37. "switch",
  38. "this",
  39. "throw",
  40. "true",
  41. "try",
  42. "typeof",
  43. "var",
  44. "void",
  45. "while",
  46. "with",
  47. // The following are only reserved when they are found in strict mode code
  48. "const",
  49. "let",
  50. "static",
  51. "yield",
  52. // The following are only reserved when they are found in module code or async function bodies
  53. "await"
  54. ],
  55. ...[
  56. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#future_reserved_words
  57. "enum",
  58. // The following are only reserved when they are found in strict mode code
  59. "implements",
  60. "interface",
  61. "package",
  62. "private",
  63. "protected",
  64. "public",
  65. // Future reserved words in older standards
  66. // The following are reserved as future keywords by older ECMAScript specifications (ECMAScript 1 till 3).
  67. "abstract",
  68. "boolean",
  69. "byte",
  70. "char",
  71. "double",
  72. "final",
  73. "float",
  74. "goto",
  75. "int",
  76. "long",
  77. "native",
  78. "short",
  79. "synchronized",
  80. "throws",
  81. "transient",
  82. "volatile"
  83. ],
  84. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers_with_special_meanings
  85. ...[
  86. "arguments",
  87. "as",
  88. "async",
  89. "eval",
  90. "from",
  91. "get",
  92. "of",
  93. "set"
  94. ]
  95. ];
  96. function libEsm(options) {
  97. const {
  98. window,
  99. require: require2,
  100. exports: members = [],
  101. conflict = ""
  102. } = options;
  103. const _M_ = "_M_" + conflict;
  104. const windowSnippet = window == null ? "" : `const ${_M_} = window["${window}"];`;
  105. const requireSnippet = require2 == null ? "" : `
  106. import { createRequire } from "node:module";
  107. const ${_M_} = createRequire(import.meta.url)("${require2}");
  108. `.trim();
  109. !members.includes("default") && members.push("default");
  110. const alias = members.filter((member) => keywords.includes(member)).reduce((memo, keyword) => Object.assign(memo, { [keyword]: `keyword_${keyword + conflict}` }), {});
  111. const exportsSnippet = `
  112. ${members.map((member) => {
  113. const LV = alias[member] ? `const ${alias[member]}` : `export const ${member}`;
  114. const RV = member === "default" ? `${_M_}.default || ${_M_}` : `${_M_}.${member}`;
  115. return `${LV} = ${RV};`;
  116. }).join("\n")}
  117. export {
  118. ${Object.entries(alias).map(([member, alias2]) => `${alias2} as ${member},`).join("\n ")}
  119. };
  120. `.trim();
  121. return {
  122. /** `window[iife-name]` snippets */
  123. window: windowSnippet,
  124. /** `require(id)` snippets */
  125. require: requireSnippet,
  126. /** `export` snippets */
  127. exports: exportsSnippet,
  128. /** Keywords alias */
  129. keywords: alias
  130. };
  131. }
  132. function relativeify(relative) {
  133. if (relative === "") {
  134. return ".";
  135. }
  136. if (!relative.startsWith("./") || !relative.startsWith(".\\")) {
  137. return "./" + relative;
  138. }
  139. return relative;
  140. }
  141. const isWindows = os.platform() === "win32";
  142. function slash(p) {
  143. return p.replace(/\\/g, "/");
  144. }
  145. function normalizePath(id) {
  146. return path.posix.normalize(isWindows ? slash(id) : id);
  147. }
  148. const COLOURS = {
  149. $: (c) => (str) => `\x1B[${c}m` + str + "\x1B[0m",
  150. gary: (str) => COLOURS.$(90)(str),
  151. cyan: (str) => COLOURS.$(36)(str),
  152. yellow: (str) => COLOURS.$(33)(str),
  153. green: (str) => COLOURS.$(32)(str),
  154. red: (str) => COLOURS.$(31)(str)
  155. };
  156. const VOLUME_RE = /^[A-Z]:/i;
  157. function node_modules(root, paths = []) {
  158. if (!root)
  159. return paths;
  160. if (!(root.startsWith("/") || VOLUME_RE.test(root)))
  161. return paths;
  162. const p = path.posix.join(normalizePath(root), "node_modules");
  163. if (fs.existsSync(p) && fs.statSync(p).isDirectory()) {
  164. paths = paths.concat(p);
  165. }
  166. root = path.posix.join(root, "..");
  167. return root === "/" || /^[A-Z]:$/i.test(root) ? paths : node_modules(root, paths);
  168. }
  169. const require$1 = node_module.createRequire(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : document.currentScript && document.currentScript.src || new URL("index.js", document.baseURI).href);
  170. const builtins = node_module.builtinModules.filter((m) => !m.startsWith("_"));
  171. const electronBuiltins = [
  172. "electron",
  173. ...builtins,
  174. ...builtins.map((module2) => `node:${module2}`)
  175. ];
  176. const CACHE_DIR = ".vite-electron-renderer";
  177. const TAG = "[electron-renderer]";
  178. const cwd = vite.normalizePath(process.cwd());
  179. const electron = `
  180. const electron = typeof require !== 'undefined'
  181. // All exports module see https://www.electronjs.org -> API -> Renderer process Modules
  182. ? (function requireElectron() {
  183. const avoid_parse_require = require;
  184. return avoid_parse_require("electron");
  185. }())
  186. : (function nodeIntegrationWarn() {
  187. console.error(\`If you need to use "electron" in the Renderer process, make sure that "nodeIntegration" is enabled in the Main process.\`);
  188. return {
  189. // TODO: polyfill
  190. };
  191. }());
  192. // Proxy in Worker
  193. let _ipcRenderer;
  194. if (typeof document === 'undefined') {
  195. _ipcRenderer = {};
  196. const keys = [
  197. 'invoke',
  198. 'postMessage',
  199. 'send',
  200. 'sendSync',
  201. 'sendTo',
  202. 'sendToHost',
  203. // propertype
  204. 'addListener',
  205. 'emit',
  206. 'eventNames',
  207. 'getMaxListeners',
  208. 'listenerCount',
  209. 'listeners',
  210. 'off',
  211. 'on',
  212. 'once',
  213. 'prependListener',
  214. 'prependOnceListener',
  215. 'rawListeners',
  216. 'removeAllListeners',
  217. 'removeListener',
  218. 'setMaxListeners',
  219. ];
  220. for (const key of keys) {
  221. _ipcRenderer[key] = () => {
  222. throw new Error(
  223. 'ipcRenderer doesn\\'t work in a Web Worker.\\n' +
  224. 'You can see https://github.com/electron-vite/vite-plugin-electron/issues/69'
  225. );
  226. };
  227. }
  228. } else {
  229. _ipcRenderer = electron.ipcRenderer;
  230. }
  231. export { electron as default };
  232. export const clipboard = electron.clipboard;
  233. export const contextBridge = electron.contextBridge;
  234. export const crashReporter = electron.crashReporter;
  235. export const ipcRenderer = _ipcRenderer;
  236. export const nativeImage = electron.nativeImage;
  237. export const shell = electron.shell;
  238. export const webFrame = electron.webFrame;
  239. export const deprecate = electron.deprecate;
  240. `.trim();
  241. function renderer(options = {}) {
  242. let root;
  243. let cacheDir;
  244. const resolveKeys = [];
  245. const moduleCache = /* @__PURE__ */ new Map();
  246. return {
  247. name: "vite-plugin-electron-renderer",
  248. async config(config, { command }) {
  249. root = vite.normalizePath(config.root ? path.resolve(config.root) : cwd);
  250. cacheDir = path.posix.join(node_modules(root)[0] ?? cwd, CACHE_DIR);
  251. for (const [key, option] of Object.entries(options.resolve ?? {})) {
  252. if (command === "build" && option.type === "esm") {
  253. continue;
  254. }
  255. resolveKeys.push(key);
  256. }
  257. const aliases = [{
  258. find: new RegExp(`^(?:node:)?(${["electron", ...builtins].join("|")})$`),
  259. // https://github.com/rollup/plugins/blob/alias-v5.0.0/packages/alias/src/index.ts#L90
  260. replacement: "$1",
  261. async customResolver(source) {
  262. let id = moduleCache.get(source);
  263. if (!id) {
  264. id = path.posix.join(cacheDir, source) + ".mjs";
  265. if (!fs.existsSync(id)) {
  266. ensureDir(path.dirname(id));
  267. fs.writeFileSync(
  268. // lazy build
  269. id,
  270. source === "electron" ? electron : getSnippets({ import: source, export: source })
  271. );
  272. }
  273. moduleCache.set(source, id);
  274. }
  275. return { id };
  276. }
  277. }];
  278. resolveKeys.length && aliases.push({
  279. find: new RegExp(`^(${resolveKeys.join("|")})$`),
  280. replacement: "$1",
  281. async customResolver(source, importer, resolveOptions) {
  282. var _a;
  283. let id = moduleCache.get(source);
  284. if (!id) {
  285. const filename = path.posix.join(cacheDir, source) + ".mjs";
  286. if (fs.existsSync(filename)) {
  287. id = filename;
  288. } else {
  289. const resolved = (_a = options.resolve) == null ? void 0 : _a[source];
  290. if (resolved) {
  291. let snippets;
  292. if (typeof resolved.build === "function") {
  293. snippets = await resolved.build({
  294. cjs: (module2) => Promise.resolve(getSnippets({ import: module2, export: module2 })),
  295. esm: (module2, buildOptions) => getPreBundleSnippets({
  296. module: module2,
  297. outdir: cacheDir,
  298. buildOptions
  299. })
  300. });
  301. } else if (resolved.type === "cjs") {
  302. snippets = getSnippets({ import: source, export: source });
  303. } else if (resolved.type === "esm") {
  304. snippets = await getPreBundleSnippets({
  305. module: source,
  306. outdir: cacheDir
  307. });
  308. }
  309. console.log(
  310. COLOURS.gary(TAG),
  311. COLOURS.cyan("pre-bundling"),
  312. COLOURS.yellow(source)
  313. );
  314. ensureDir(path.dirname(filename));
  315. fs.writeFileSync(filename, snippets ?? `/* ${TAG}: empty */`);
  316. id = filename;
  317. } else {
  318. id = source;
  319. }
  320. }
  321. moduleCache.set(source, id);
  322. }
  323. return id === source ? this.resolve(
  324. source,
  325. importer,
  326. Object.assign({ skipSelf: true }, resolveOptions)
  327. ).then((resolved) => resolved || { id: source }) : { id };
  328. }
  329. });
  330. modifyAlias(config, aliases);
  331. modifyOptimizeDeps(config, resolveKeys);
  332. adaptElectron(config);
  333. }
  334. };
  335. }
  336. function adaptElectron(config) {
  337. var _a;
  338. config.base ?? (config.base = "./");
  339. config.build ?? (config.build = {});
  340. (_a = config.build).rollupOptions ?? (_a.rollupOptions = {});
  341. setOutputFreeze(config.build.rollupOptions);
  342. withIgnore(config.build, electronBuiltins);
  343. }
  344. function setOutputFreeze(rollupOptions) {
  345. var _a;
  346. rollupOptions.output ?? (rollupOptions.output = {});
  347. if (Array.isArray(rollupOptions.output)) {
  348. for (const o of rollupOptions.output) {
  349. o.freeze ?? (o.freeze = false);
  350. }
  351. } else {
  352. (_a = rollupOptions.output).freeze ?? (_a.freeze = false);
  353. }
  354. }
  355. function withIgnore(configBuild, modules) {
  356. configBuild.commonjsOptions ?? (configBuild.commonjsOptions = {});
  357. if (configBuild.commonjsOptions.ignore) {
  358. if (typeof configBuild.commonjsOptions.ignore === "function") {
  359. const userIgnore = configBuild.commonjsOptions.ignore;
  360. configBuild.commonjsOptions.ignore = (id) => {
  361. if ((userIgnore == null ? void 0 : userIgnore(id)) === true) {
  362. return true;
  363. }
  364. return modules.includes(id);
  365. };
  366. } else {
  367. configBuild.commonjsOptions.ignore.push(...modules);
  368. }
  369. } else {
  370. configBuild.commonjsOptions.ignore = modules;
  371. }
  372. }
  373. function modifyOptimizeDeps(config, exclude) {
  374. var _a;
  375. config.optimizeDeps ?? (config.optimizeDeps = {});
  376. (_a = config.optimizeDeps).exclude ?? (_a.exclude = []);
  377. for (const str of exclude) {
  378. if (!config.optimizeDeps.exclude.includes(str)) {
  379. config.optimizeDeps.exclude.push(str);
  380. }
  381. }
  382. }
  383. function modifyAlias(config, aliases) {
  384. var _a;
  385. config.resolve ?? (config.resolve = {});
  386. (_a = config.resolve).alias ?? (_a.alias = []);
  387. if (Object.prototype.toString.call(config.resolve.alias) === "[object Object]") {
  388. config.resolve.alias = Object.entries(config.resolve.alias).reduce((memo, [find, replacement]) => memo.concat({ find, replacement }), []);
  389. }
  390. config.resolve.alias.push(...aliases);
  391. }
  392. function getSnippets(module2) {
  393. const { exports: exports2 } = libEsm({ exports: Object.getOwnPropertyNames(
  394. /* not await import */
  395. require$1(module2.import)
  396. ) });
  397. return `const avoid_parse_require = require; const _M_ = avoid_parse_require("${module2.export}");
  398. ${exports2}`;
  399. }
  400. async function getPreBundleSnippets(options) {
  401. const {
  402. module: module2,
  403. outdir,
  404. buildOptions = {}
  405. } = options;
  406. const outfile = path.posix.join(outdir, module2) + ".cjs";
  407. await esbuild.build({
  408. entryPoints: [module2],
  409. outfile,
  410. target: "node14",
  411. format: "cjs",
  412. bundle: true,
  413. sourcemap: "inline",
  414. platform: "node",
  415. external: electronBuiltins,
  416. ...buildOptions
  417. });
  418. return getSnippets({
  419. import: outfile,
  420. // `require()` in script-module lookup path based on `process.cwd()` 🤔
  421. export: relativeify(path.posix.relative(cwd, outfile))
  422. });
  423. }
  424. function ensureDir(dirname) {
  425. if (!fs.existsSync(dirname)) {
  426. fs.mkdirSync(dirname, { recursive: true });
  427. }
  428. }
  429. exports.default = renderer;
  430. exports.electron = electron;