@snoirtrom/electron-vite 6.0.1 → 6.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ const vm = require('node:vm')
2
+ const v8 = require('node:v8')
3
+
4
+ v8.setFlagsFromString('--no-lazy')
5
+ v8.setFlagsFromString('--no-flush-bytecode')
6
+
7
+ const params = ['exports', 'require', 'module', '__filename', '__dirname']
8
+
9
+ module.exports = function compile(code) {
10
+ if (typeof code !== 'string') throw new TypeError('Compilation source must be a string')
11
+ const { cachedData } = vm.compileFunction(code, params, { produceCachedData: true })
12
+ if (!Buffer.isBuffer(cachedData)) throw new Error('V8 did not produce cached data')
13
+ // Explicit wire format works across both Node IPC and Electron structured clone.
14
+ return { sourceLength: code.length, cachedData: cachedData.toString('base64') }
15
+ }
@@ -0,0 +1,107 @@
1
+ const { app, BrowserWindow, ipcMain } = require('electron')
2
+ const path = require('node:path')
3
+ const RpcPeer = require('./rpc-peer.cjs')
4
+ const compile = require('./bytecode-compiler.cjs')
5
+
6
+ if (process.platform === 'darwin') {
7
+ app.dock.hide()
8
+ }
9
+
10
+ const channel = 'electron-vite:bytecode:rpc'
11
+ const readyChannel = 'electron-vite:bytecode:ready'
12
+ let win
13
+ let rendererRPC
14
+ let stopping = false
15
+
16
+ function fail(error) {
17
+ console.error(error)
18
+ parentRPC.close(error)
19
+ rendererRPC?.close(error)
20
+ app.exit(1)
21
+ }
22
+
23
+ const parentRPC = new RpcPeer(
24
+ message =>
25
+ new Promise((resolve, reject) => {
26
+ if (!process.connected || !process.send) return reject(new Error('Parent IPC is disconnected'))
27
+ process.send(message, error => (error ? reject(error) : resolve()))
28
+ })
29
+ )
30
+
31
+ function createRenderer() {
32
+ return new Promise((resolve, reject) => {
33
+ let ready = false
34
+ const timer = setTimeout(() => finish(new Error('Compiler preload readiness timed out')), 30000)
35
+ function finish(error) {
36
+ clearTimeout(timer)
37
+ ipcMain.removeListener(readyChannel, onReady)
38
+ if (error) reject(error)
39
+ else {
40
+ ready = true
41
+ resolve()
42
+ }
43
+ }
44
+ function onReady(event) {
45
+ if (event.sender === win.webContents) finish()
46
+ }
47
+ function onFailure(error) {
48
+ if (stopping) return
49
+ if (ready) fail(error)
50
+ else finish(error)
51
+ }
52
+ ipcMain.on(readyChannel, onReady)
53
+ win = new BrowserWindow({
54
+ show: false,
55
+ webPreferences: {
56
+ preload: path.join(__dirname, 'electron-bytecode-preload.cjs'),
57
+ sandbox: false,
58
+ contextIsolation: true
59
+ }
60
+ })
61
+ rendererRPC = new RpcPeer(message => {
62
+ if (win.isDestroyed()) throw new Error('Compiler window is closed')
63
+ win.webContents.send(channel, message)
64
+ })
65
+ ipcMain.on(channel, (event, message) => {
66
+ if (!win.isDestroyed() && event.sender === win.webContents) void rendererRPC.receive(message)
67
+ })
68
+ win.webContents.on('preload-error', (_event, _path, error) => onFailure(error))
69
+ win.webContents.on('render-process-gone', (_event, details) => {
70
+ onFailure(new Error(`Compiler renderer exited: ${details.reason}`))
71
+ })
72
+ win.on('closed', () => onFailure(new Error('Compiler window closed unexpectedly')))
73
+ win.loadURL('data:text/html,<!doctype html><html></html>').catch(onFailure)
74
+ })
75
+ }
76
+
77
+ // Register readiness immediately, but only resolve it after the selected backend is usable.
78
+ const initialized = app.whenReady().then(async () => {
79
+ if (process.env.ELECTRON_VITE_RENDERER === '1' || process.env.ELECTRON_VITE_RENDERER === 'true') {
80
+ await createRenderer()
81
+ parentRPC.register('compile', (...args) => rendererRPC.request('compile', ...args))
82
+ } else {
83
+ parentRPC.register('compile', compile)
84
+ }
85
+ return true
86
+ })
87
+ parentRPC.register('ready', () => initialized)
88
+ initialized.catch(fail)
89
+
90
+ process.on('message', message => {
91
+ if (message?.type === 'shutdown') {
92
+ stopping = true
93
+ app.quit()
94
+ } else {
95
+ void parentRPC.receive(message)
96
+ }
97
+ })
98
+ process.on('disconnect', () => {
99
+ stopping = true
100
+ app.quit()
101
+ })
102
+ app.on('before-quit', () => {
103
+ stopping = true
104
+ parentRPC.close()
105
+ rendererRPC?.close()
106
+ })
107
+ if (!process.send) fail(new Error('Bytecode compiler must be launched with an IPC channel'))
@@ -0,0 +1,10 @@
1
+ const { ipcRenderer } = require('electron')
2
+ const RpcPeer = require('./rpc-peer.cjs')
3
+ const compile = require('./bytecode-compiler.cjs')
4
+
5
+ const channel = 'electron-vite:bytecode:rpc'
6
+ const rpc = new RpcPeer(message => ipcRenderer.send(channel, message))
7
+ rpc.register('ready', () => true)
8
+ rpc.register('compile', compile)
9
+ ipcRenderer.on(channel, (_event, message) => void rpc.receive(message))
10
+ ipcRenderer.send('electron-vite:bytecode:ready')
@@ -0,0 +1,89 @@
1
+ // Transport-independent peer. Messages must be JSON serializable.
2
+ class RpcPeer {
3
+ constructor(send, timeout = 30000) {
4
+ this.send = send
5
+ this.timeout = timeout
6
+ this.methods = new Map()
7
+ this.pending = new Map()
8
+ this.nextId = 0
9
+ this.closed = false
10
+ }
11
+
12
+ register(cmd, method) {
13
+ this.methods.set(cmd, method)
14
+ return this
15
+ }
16
+
17
+ request(cmd, ...args) {
18
+ if (this.closed) return Promise.reject(new Error('RPC connection is closed'))
19
+ const invocationId = this.nextId++
20
+ return new Promise((resolve, reject) => {
21
+ const timer = setTimeout(() => {
22
+ this.pending.delete(invocationId)
23
+ reject(new Error(`RPC request timed out: ${cmd}`))
24
+ }, this.timeout)
25
+ this.pending.set(invocationId, { resolve, reject, timer })
26
+ Promise.resolve()
27
+ .then(() => this.send({ type: 'request', invocationId, cmd, args }))
28
+ .catch(error => {
29
+ const pending = this.pending.get(invocationId)
30
+ if (!pending) return
31
+ clearTimeout(timer)
32
+ this.pending.delete(invocationId)
33
+ reject(error)
34
+ })
35
+ })
36
+ }
37
+
38
+ async receive(message) {
39
+ if (this.closed || !message || !Number.isSafeInteger(message.invocationId)) return
40
+ const { type, invocationId } = message
41
+ if (type === 'response') {
42
+ const pending = this.pending.get(invocationId)
43
+ if (!pending) return
44
+ this.pending.delete(invocationId)
45
+ clearTimeout(pending.timer)
46
+ if (message.error) {
47
+ const error = new Error(message.error.message)
48
+ error.name = message.error.name || 'Error'
49
+ if (message.error.stack) error.stack = message.error.stack
50
+ pending.reject(error)
51
+ } else {
52
+ pending.resolve(message.result)
53
+ }
54
+ return
55
+ }
56
+ if (type !== 'request' || typeof message.cmd !== 'string' || !Array.isArray(message.args)) return
57
+ const response = { type: 'response', invocationId }
58
+ try {
59
+ const method = this.methods.get(message.cmd)
60
+ if (!method) throw new Error(`Invalid method: ${message.cmd}`)
61
+ response.result = await method(...message.args)
62
+ } catch (error) {
63
+ response.error = {
64
+ name: error instanceof Error ? error.name : 'Error',
65
+ message: error instanceof Error ? error.message : String(error),
66
+ stack: error instanceof Error ? error.stack : undefined
67
+ }
68
+ }
69
+ if (!this.closed) {
70
+ try {
71
+ await this.send(response)
72
+ } catch (error) {
73
+ this.close(error)
74
+ }
75
+ }
76
+ }
77
+
78
+ close(error = new Error('RPC connection is closed')) {
79
+ this.closed = true
80
+ for (const pending of this.pending.values()) {
81
+ clearTimeout(pending.timer)
82
+ pending.reject(error)
83
+ }
84
+ this.pending.clear()
85
+ this.methods.clear()
86
+ }
87
+ }
88
+
89
+ module.exports = RpcPeer
@@ -1,16 +1,16 @@
1
1
  import { build as build$1 } from 'vite';
2
- import { r as resolveConfig } from './lib-CbKPgmtQ.js';
2
+ import { r as resolveConfig } from './lib-wmKiubLV.js';
3
3
  import 'node:path';
4
+ import 'picocolors';
4
5
  import 'node:fs';
5
- import 'node:url';
6
6
  import 'node:module';
7
- import 'picocolors';
8
- import 'esbuild';
9
7
  import 'node:child_process';
10
8
  import 'node:crypto';
11
9
  import 'node:fs/promises';
12
10
  import 'magic-string';
13
11
  import '@babel/core';
12
+ import 'node:url';
13
+ import 'rolldown';
14
14
 
15
15
  /**
16
16
  * Bundles the electron app for production.
@@ -1,16 +1,16 @@
1
1
  import { createLogger, createServer as createServer$1, mergeConfig, build } from 'vite';
2
2
  import colors from 'picocolors';
3
- import { r as resolveConfig, c as resolveHostname, s as startElectron } from './lib-CbKPgmtQ.js';
3
+ import { r as resolveConfig, c as resolveHostname, s as startElectron } from './lib-wmKiubLV.js';
4
4
  import 'node:path';
5
5
  import 'node:fs';
6
- import 'node:url';
7
6
  import 'node:module';
8
- import 'esbuild';
9
7
  import 'node:child_process';
10
8
  import 'node:crypto';
11
9
  import 'node:fs/promises';
12
10
  import 'magic-string';
13
11
  import '@babel/core';
12
+ import 'node:url';
13
+ import 'rolldown';
14
14
 
15
15
  async function createServer(inlineConfig = {}, options) {
16
16
  process.env.NODE_ENV_ELECTRON_VITE = 'development';
@@ -1,17 +1,17 @@
1
1
  import colors from 'picocolors';
2
2
  import { createLogger } from 'vite';
3
- import { s as startElectron } from './lib-CbKPgmtQ.js';
4
- import { build } from './lib-B8n2vQeG.js';
3
+ import { s as startElectron } from './lib-wmKiubLV.js';
4
+ import { build } from './lib-DaHzt8UE.js';
5
5
  import 'node:path';
6
6
  import 'node:fs';
7
- import 'node:url';
8
7
  import 'node:module';
9
- import 'esbuild';
10
8
  import 'node:child_process';
11
9
  import 'node:crypto';
12
10
  import 'node:fs/promises';
13
11
  import 'magic-string';
14
12
  import '@babel/core';
13
+ import 'node:url';
14
+ import 'rolldown';
15
15
 
16
16
  async function preview(inlineConfig = {}, options) {
17
17
  if (!options.skipBuild) {
@@ -1,15 +1,15 @@
1
1
  import path from 'node:path';
2
- import fs from 'node:fs';
3
- import { pathToFileURL } from 'node:url';
4
- import { createRequire, builtinModules } from 'node:module';
5
2
  import colors from 'picocolors';
6
3
  import { loadEnv as loadEnv$1, mergeConfig, normalizePath, version, build, createLogger } from 'vite';
7
- import { build as build$1 } from 'esbuild';
4
+ import fs from 'node:fs';
5
+ import { createRequire, builtinModules } from 'node:module';
8
6
  import { spawn } from 'node:child_process';
9
- import { createHash } from 'node:crypto';
7
+ import { createHash, randomBytes } from 'node:crypto';
10
8
  import fs$1 from 'node:fs/promises';
11
9
  import MagicString from 'magic-string';
12
10
  import * as babel from '@babel/core';
11
+ import { pathToFileURL } from 'node:url';
12
+ import { rolldown } from 'rolldown';
13
13
 
14
14
  /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-function-type */
15
15
  function isObject(value) {
@@ -69,27 +69,54 @@ function isFilePathESM(filePath) {
69
69
  return pkg?.type === 'module';
70
70
  }
71
71
  }
72
- function deepClone(value) {
73
- if (Array.isArray(value)) {
74
- return value.map(v => deepClone(v));
75
- }
76
- if (isObject(value)) {
77
- const cloned = {};
78
- for (const key in value) {
79
- cloned[key] = deepClone(value[key]);
72
+ /**
73
+ * Isolate configuration data without cloning plugins or runtime instances.
74
+ * Plugins may capture their own object in hooks, so their identity must survive.
75
+ */
76
+ function cloneConfig(config) {
77
+ const seen = new WeakMap();
78
+ const pluginArrays = new WeakMap();
79
+ function clone(value, plugins = false) {
80
+ if (value === null || typeof value !== 'object')
81
+ return value;
82
+ const cache = plugins ? pluginArrays : seen;
83
+ if (cache.has(value))
84
+ return cache.get(value);
85
+ if (Array.isArray(value)) {
86
+ const result = new Array(value.length);
87
+ cache.set(value, result);
88
+ value.forEach((item, index) => {
89
+ result[index] = clone(item, plugins);
90
+ });
91
+ return result;
80
92
  }
81
- return cloned;
82
- }
83
- if (typeof value === 'function') {
84
- return value;
85
- }
86
- if (value instanceof RegExp) {
87
- return new RegExp(value);
88
- }
89
- if (typeof value === 'object' && value != null) {
90
- throw new Error('Cannot deep clone non-plain object');
93
+ // Preserve plugin objects, promises and other opaque plugin options.
94
+ if (plugins)
95
+ return value;
96
+ if (value instanceof RegExp) {
97
+ const result = new RegExp(value);
98
+ result.lastIndex = value.lastIndex;
99
+ cache.set(value, result);
100
+ return result;
101
+ }
102
+ const prototype = Object.getPrototypeOf(value);
103
+ if (prototype !== Object.prototype && prototype !== null)
104
+ return value;
105
+ const result = Object.create(prototype);
106
+ cache.set(value, result);
107
+ for (const key of Reflect.ownKeys(value)) {
108
+ if (!Object.prototype.propertyIsEnumerable.call(value, key))
109
+ continue;
110
+ Object.defineProperty(result, key, {
111
+ value: clone(value[key], key === 'plugins'),
112
+ enumerable: true,
113
+ configurable: true,
114
+ writable: true
115
+ });
116
+ }
117
+ return result;
91
118
  }
92
- return value;
119
+ return clone(config);
93
120
  }
94
121
  async function asyncFlatten(arr) {
95
122
  do {
@@ -160,6 +187,7 @@ function getElectronPath() {
160
187
  function getElectronNodeTarget() {
161
188
  const electronVer = getElectronMajorVer();
162
189
  const nodeVer = {
190
+ '45': '24.21',
163
191
  '44': '24.20',
164
192
  '41': '24.14',
165
193
  '40': '24.14',
@@ -193,6 +221,7 @@ function getElectronNodeTarget() {
193
221
  function getElectronChromeTarget() {
194
222
  const electronVer = getElectronMajorVer();
195
223
  const chromeVer = {
224
+ '45': '156',
196
225
  '44': '152',
197
226
  '41': '146',
198
227
  '40': '144',
@@ -1165,124 +1194,223 @@ function externalizeDepsPlugin(options = {}) {
1165
1194
  };
1166
1195
  }
1167
1196
 
1168
- // Inspired by https://github.com/bytenode/bytenode
1169
- const _require$1 = createRequire(import.meta.url);
1170
- function getBytecodeCompilerPath() {
1171
- return path.join(path.dirname(_require$1.resolve('electron-vite/package.json')), 'bin', 'electron-bytecode.cjs');
1172
- }
1173
- function compileToBytecode(code) {
1174
- return new Promise((resolve, reject) => {
1175
- let data = Buffer.from([]);
1176
- const electronPath = getElectronPath();
1177
- const bytecodePath = getBytecodeCompilerPath();
1178
- const proc = spawn(electronPath, [bytecodePath], {
1179
- env: { ELECTRON_RUN_AS_NODE: '1' },
1180
- stdio: ['pipe', 'pipe', 'pipe', 'ipc']
1197
+ class ElectronCompiler {
1198
+ options;
1199
+ ps;
1200
+ rpcMap = new Map();
1201
+ invocationId = 0;
1202
+ starting;
1203
+ stopping;
1204
+ ready = false;
1205
+ constructor(options) {
1206
+ this.options = options;
1207
+ for (const timeout of [options.timeout, options.shutdownTimeout]) {
1208
+ if (timeout !== undefined && (!Number.isFinite(timeout) || timeout <= 0)) {
1209
+ throw new RangeError('ElectronCompiler timeouts must be positive finite numbers');
1210
+ }
1211
+ }
1212
+ }
1213
+ start() {
1214
+ if (this.stopping)
1215
+ return Promise.reject(new Error('ElectronCompiler is stopping'));
1216
+ if (this.starting)
1217
+ return this.starting;
1218
+ if (this.ready)
1219
+ return Promise.resolve();
1220
+ if (this.ps)
1221
+ return Promise.reject(new Error('Previous Electron process has not closed; await stop() first'));
1222
+ this.starting = this.initialize().finally(() => {
1223
+ this.starting = undefined;
1224
+ });
1225
+ return this.starting;
1226
+ }
1227
+ async initialize() {
1228
+ const env = { ...process.env, ...this.options.env, ELECTRON_VITE_RPC: 'true' };
1229
+ delete env.ELECTRON_RUN_AS_NODE;
1230
+ const ps = spawn(this.options.path, this.options.args, {
1231
+ stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
1232
+ windowsHide: true,
1233
+ env
1181
1234
  });
1182
- if (proc.stdin) {
1183
- proc.stdin.write(code);
1184
- proc.stdin.end();
1235
+ this.ps = ps;
1236
+ ps.on('message', (message) => {
1237
+ if (this.ps !== ps || !message || message.type !== 'response')
1238
+ return;
1239
+ const pending = this.rpcMap.get(message.invocationId);
1240
+ if (!pending)
1241
+ return;
1242
+ clearTimeout(pending.timer);
1243
+ this.rpcMap.delete(message.invocationId);
1244
+ if (message.error) {
1245
+ const error = new Error(message.error.message);
1246
+ error.name = message.error.name;
1247
+ if (message.error.stack)
1248
+ error.stack = message.error.stack;
1249
+ pending.reject(error);
1250
+ }
1251
+ else
1252
+ pending.resolve(message.result);
1253
+ });
1254
+ ps.on('error', error => {
1255
+ if (this.ps === ps)
1256
+ this.rejectPending(error);
1257
+ });
1258
+ ps.on('disconnect', () => {
1259
+ if (this.ps === ps)
1260
+ this.rejectPending(new Error('Electron IPC disconnected'));
1261
+ });
1262
+ ps.on('exit', (code, signal) => {
1263
+ if (this.ps === ps)
1264
+ this.rejectPending(new Error('Electron exited (code ' + code + ', signal ' + signal + ')'));
1265
+ });
1266
+ ps.on('close', () => {
1267
+ if (this.ps === ps) {
1268
+ this.rejectPending(new Error('Electron process closed'));
1269
+ this.ps = undefined;
1270
+ }
1271
+ });
1272
+ try {
1273
+ await this.sendRequest('ready', []);
1274
+ if (!ps.connected || this.stopping)
1275
+ throw new Error('Electron stopped during initialization');
1276
+ this.ready = true;
1185
1277
  }
1186
- if (proc.stdout) {
1187
- proc.stdout.on('data', chunk => {
1188
- data = Buffer.concat([data, chunk]);
1189
- });
1190
- proc.stdout.on('error', err => {
1191
- console.error(err);
1192
- });
1193
- proc.stdout.on('end', () => {
1194
- resolve(data);
1195
- });
1278
+ catch (error) {
1279
+ await this.stop();
1280
+ throw error;
1196
1281
  }
1197
- if (proc.stderr) {
1198
- proc.stderr.on('data', chunk => {
1199
- console.error('Error: ', chunk.toString());
1200
- });
1201
- proc.stderr.on('error', err => {
1202
- console.error('Error: ', err);
1203
- });
1282
+ }
1283
+ compile(code) {
1284
+ return this.request('compile', code);
1285
+ }
1286
+ async request(cmd, ...args) {
1287
+ if (!this.ready || this.stopping)
1288
+ throw new Error('ElectronCompiler is not ready; await start() first');
1289
+ return this.sendRequest(cmd, args);
1290
+ }
1291
+ sendRequest(cmd, args) {
1292
+ const ps = this.ps;
1293
+ if (!ps?.connected)
1294
+ return Promise.reject(new Error('Electron IPC is not connected'));
1295
+ const invocationId = this.invocationId++;
1296
+ return new Promise((resolve, reject) => {
1297
+ const fail = (error) => {
1298
+ const pending = this.rpcMap.get(invocationId);
1299
+ if (!pending)
1300
+ return;
1301
+ clearTimeout(pending.timer);
1302
+ this.rpcMap.delete(invocationId);
1303
+ reject(error);
1304
+ };
1305
+ const timer = setTimeout(() => fail(new Error('Electron RPC timed out: ' + cmd)), this.options.timeout ?? 30000);
1306
+ this.rpcMap.set(invocationId, { resolve, reject, timer });
1307
+ try {
1308
+ ps.send({ type: 'request', invocationId, cmd, args }, error => {
1309
+ if (error)
1310
+ fail(error);
1311
+ });
1312
+ }
1313
+ catch (error) {
1314
+ fail(error instanceof Error ? error : new Error(String(error)));
1315
+ }
1316
+ });
1317
+ }
1318
+ rejectPending(error) {
1319
+ this.ready = false;
1320
+ for (const pending of this.rpcMap.values()) {
1321
+ clearTimeout(pending.timer);
1322
+ pending.reject(error);
1204
1323
  }
1205
- proc.addListener('message', message => console.log(message));
1206
- proc.addListener('error', err => console.error(err));
1207
- proc.on('error', err => reject(err));
1208
- proc.on('exit', () => {
1209
- resolve(data);
1324
+ this.rpcMap.clear();
1325
+ }
1326
+ stop() {
1327
+ if (this.stopping)
1328
+ return this.stopping;
1329
+ this.rejectPending(new Error('ElectronCompiler stopped'));
1330
+ const ps = this.ps;
1331
+ if (!ps)
1332
+ return Promise.resolve();
1333
+ this.stopping = new Promise(resolve => {
1334
+ const timer = setTimeout(() => ps.kill('SIGKILL'), this.options.shutdownTimeout ?? 3000);
1335
+ ps.once('close', () => {
1336
+ clearTimeout(timer);
1337
+ resolve();
1338
+ });
1339
+ if (ps.connected) {
1340
+ try {
1341
+ ps.send({ type: 'shutdown' }, error => {
1342
+ if (error)
1343
+ ps.kill();
1344
+ });
1345
+ }
1346
+ catch {
1347
+ ps.kill();
1348
+ }
1349
+ }
1350
+ else
1351
+ ps.kill();
1352
+ }).finally(() => {
1353
+ this.stopping = undefined;
1210
1354
  });
1211
- });
1355
+ return this.stopping;
1356
+ }
1357
+ }
1358
+
1359
+ // Inspired by https://github.com/bytenode/bytenode
1360
+ const _require$1 = createRequire(import.meta.url);
1361
+ function getBytecodeCompilerPath() {
1362
+ return path.join(path.dirname(_require$1.resolve('electron-vite/package.json')), 'bin', 'electron-bytecode-main.cjs');
1363
+ }
1364
+ // Versioned envelope: magic/version (8), UTF-16 source length (4), module ID (16), V8 cache.
1365
+ // Keep our metadata separate from the private V8 cache header.
1366
+ async function compileToBytecode(compiler, code) {
1367
+ const id = randomBytes(16);
1368
+ // Reserve enough source space for an untruncated, per-artifact placeholder identity.
1369
+ const source = code + '\n/*' + id.toString('hex') + '*/';
1370
+ const result = await compiler.compile(source);
1371
+ const header = Buffer.alloc(28);
1372
+ header.write('EVBC0001', 0, 'ascii');
1373
+ header.writeUInt32LE(result.sourceLength, 8);
1374
+ id.copy(header, 12);
1375
+ return Buffer.concat([header, Buffer.from(result.cachedData, 'base64')]);
1212
1376
  }
1213
1377
  const bytecodeModuleLoaderCode = [
1214
- `"use strict";`,
1215
- `const fs = require("fs");`,
1216
- `const path = require("path");`,
1217
- `const vm = require("vm");`,
1218
- `const v8 = require("v8");`,
1219
- `const Module = require("module");`,
1220
- `v8.setFlagsFromString("--no-lazy");`,
1221
- `v8.setFlagsFromString("--no-flush-bytecode");`,
1222
- `const FLAG_HASH_OFFSET = 12;`,
1223
- `const SOURCE_HASH_OFFSET = 8;`,
1224
- `let dummyBytecode;`,
1225
- `function setFlagHashHeader(bytecodeBuffer) {`,
1226
- ` if (!dummyBytecode) {`,
1227
- ` const script = new vm.Script("", {`,
1228
- ` produceCachedData: true`,
1229
- ` });`,
1230
- ` dummyBytecode = script.createCachedData();`,
1231
- ` }`,
1232
- ` dummyBytecode.slice(FLAG_HASH_OFFSET, FLAG_HASH_OFFSET + 4).copy(bytecodeBuffer, FLAG_HASH_OFFSET);`,
1233
- `};`,
1234
- `function getSourceHashHeader(bytecodeBuffer) {`,
1235
- ` return bytecodeBuffer.slice(SOURCE_HASH_OFFSET, SOURCE_HASH_OFFSET + 4);`,
1236
- `};`,
1237
- `function buffer2Number(buffer) {`,
1238
- ` let ret = 0;`,
1239
- ` ret |= buffer[3] << 24;`,
1240
- ` ret |= buffer[2] << 16;`,
1241
- ` ret |= buffer[1] << 8;`,
1242
- ` ret |= buffer[0];`,
1243
- ` return ret;`,
1244
- `};`,
1245
- `Module._extensions[".jsc"] = Module._extensions[".cjsc"] = function (module, filename) {`,
1246
- ` const bytecodeBuffer = fs.readFileSync(filename);`,
1247
- ` if (!Buffer.isBuffer(bytecodeBuffer)) {`,
1248
- ` throw new Error("BytecodeBuffer must be a buffer object.");`,
1249
- ` }`,
1250
- ` setFlagHashHeader(bytecodeBuffer);`,
1251
- ` const length = buffer2Number(getSourceHashHeader(bytecodeBuffer));`,
1252
- ` let dummyCode = "";`,
1253
- ` if (length > 1) {`,
1254
- ` dummyCode = "\\"" + "\\u200b".repeat(length - 2) + "\\"";`,
1255
- ` }`,
1256
- ` const script = new vm.Script(dummyCode, {`,
1257
- ` filename: filename,`,
1258
- ` lineOffset: 0,`,
1259
- ` displayErrors: true,`,
1260
- ` cachedData: bytecodeBuffer`,
1261
- ` });`,
1262
- ` if (script.cachedDataRejected) {`,
1263
- ` throw new Error("Invalid or incompatible cached data (cachedDataRejected)");`,
1264
- ` }`,
1265
- ` const require = function (id) {`,
1266
- ` return module.require(id);`,
1267
- ` };`,
1268
- ` require.resolve = function (request, options) {`,
1269
- ` return Module._resolveFilename(request, module, false, options);`,
1270
- ` };`,
1271
- ` if (process.mainModule) {`,
1272
- ` require.main = process.mainModule;`,
1273
- ` }`,
1274
- ` require.extensions = Module._extensions;`,
1275
- ` require.cache = Module._cache;`,
1276
- ` const compiledWrapper = script.runInThisContext({`,
1277
- ` filename: filename,`,
1278
- ` lineOffset: 0,`,
1279
- ` columnOffset: 0,`,
1280
- ` displayErrors: true`,
1281
- ` });`,
1282
- ` const dirname = path.dirname(filename);`,
1283
- ` const args = [module.exports, require, module, filename, dirname, process, global];`,
1284
- ` return compiledWrapper.apply(module.exports, args);`,
1285
- `};`
1378
+ '"use strict";',
1379
+ 'const fs = require("node:fs");',
1380
+ 'const path = require("node:path");',
1381
+ 'const vm = require("node:vm");',
1382
+ 'const v8 = require("node:v8");',
1383
+ 'const Module = require("node:module");',
1384
+ 'v8.setFlagsFromString("--no-lazy");',
1385
+ 'v8.setFlagsFromString("--no-flush-bytecode");',
1386
+ 'const params = ["exports", "require", "module", "__filename", "__dirname"];',
1387
+ 'Module._extensions[".jsc"] = Module._extensions[".cjsc"] = function (module, filename) {',
1388
+ ' const data = fs.readFileSync(filename);',
1389
+ ' if (data.length <= 28 || data.toString("ascii", 0, 8) !== "EVBC0001") {',
1390
+ ' throw new Error("Invalid electron-vite bytecode format; rebuild the application: " + filename);',
1391
+ ' }',
1392
+ ' const length = data.readUInt32LE(8);',
1393
+ ' const tag = "/*" + data.subarray(12, 28).toString("hex") + "*/";',
1394
+ ' if (length < tag.length || length > 0x1fffffff) {',
1395
+ ' throw new Error("Invalid bytecode source length: " + filename);',
1396
+ ' }',
1397
+ ' const placeholder = tag + " ".repeat(length - tag.length);',
1398
+ ' const compiledWrapper = vm.compileFunction(placeholder, params, {',
1399
+ ' filename,',
1400
+ ' cachedData: data.subarray(28)',
1401
+ ' });',
1402
+ ' if (compiledWrapper.cachedDataRejected) {',
1403
+ ' throw new Error("Invalid or incompatible cached data (cachedDataRejected): " + filename);',
1404
+ ' }',
1405
+ ' const require = function (id) { return module.require(id); };',
1406
+ ' require.resolve = function (request, options) {',
1407
+ ' return Module._resolveFilename(request, module, false, options);',
1408
+ ' };',
1409
+ ' if (process.mainModule) require.main = process.mainModule;',
1410
+ ' require.extensions = Module._extensions;',
1411
+ ' require.cache = Module._cache;',
1412
+ ' return compiledWrapper.call(module.exports, module.exports, require, module, filename, path.dirname(filename));',
1413
+ '};'
1286
1414
  ];
1287
1415
  const bytecodeChunkExtensionRE = /.(jsc|cjsc)$/;
1288
1416
  /**
@@ -1309,12 +1437,13 @@ function bytecodePlugin(options = {}) {
1309
1437
  }
1310
1438
  const shouldTransformBytecodeChunk = plugins.length !== 0;
1311
1439
  const _transform = (code, sourceMaps = false) => {
1312
- const re = babel.transform(code, { plugins, sourceMaps });
1440
+ const re = babel.transformSync(code, { plugins, sourceMaps });
1313
1441
  return re ? { code: re.code || '', map: re.map } : null;
1314
1442
  };
1315
1443
  const useStrict = '"use strict";';
1316
1444
  const bytecodeModuleLoader = 'bytecode-loader.cjs';
1317
1445
  let supported = false;
1446
+ let isPreload = false;
1318
1447
  return {
1319
1448
  name: 'vite:bytecode',
1320
1449
  apply: 'build',
@@ -1323,7 +1452,8 @@ function bytecodePlugin(options = {}) {
1323
1452
  if (supported) {
1324
1453
  return;
1325
1454
  }
1326
- const useInRenderer = config.plugins.some(p => p.name === 'vite:electron-renderer-preset-config');
1455
+ isPreload = config.plugins.some(p => p.name === 'vite:electron-preload-config-preset');
1456
+ const useInRenderer = config.plugins.some(p => p.name === 'vite:electron-renderer-config-preset');
1327
1457
  if (useInRenderer) {
1328
1458
  config.logger.warn(colors.yellow('bytecodePlugin does not support renderer.'));
1329
1459
  return;
@@ -1364,76 +1494,91 @@ function bytecodePlugin(options = {}) {
1364
1494
  };
1365
1495
  let bytecodeChunkCount = 0;
1366
1496
  const bundles = Object.keys(output);
1367
- await Promise.all(bundles.map(async (name) => {
1368
- const chunk = output[name];
1369
- if (chunk.type === 'chunk') {
1370
- let _code = chunk.code;
1371
- if (bytecodeRE) {
1372
- let match;
1373
- let s;
1374
- while ((match = bytecodeRE.exec(_code))) {
1375
- s ||= new MagicString(_code);
1376
- const [prefix, chunkName] = match;
1377
- const len = prefix.length + chunkName.length;
1378
- s.overwrite(match.index, match.index + len, prefix + chunkName + 'c', {
1379
- contentOnly: true
1380
- });
1381
- }
1382
- if (s) {
1383
- _code = s.toString();
1497
+ const compiler = new ElectronCompiler({
1498
+ path: getElectronPath(),
1499
+ args: [getBytecodeCompilerPath()],
1500
+ env: { ELECTRON_VITE_RENDERER: isPreload ? '1' : '0' }
1501
+ });
1502
+ try {
1503
+ await compiler.start();
1504
+ for (const name of bundles) {
1505
+ const chunk = output[name];
1506
+ if (chunk.type === 'chunk') {
1507
+ let _code = chunk.code;
1508
+ if (bytecodeRE) {
1509
+ let match;
1510
+ let s;
1511
+ while ((match = bytecodeRE.exec(_code))) {
1512
+ s ||= new MagicString(_code);
1513
+ const [prefix, chunkName] = match;
1514
+ const len = prefix.length + chunkName.length;
1515
+ s.overwrite(match.index, match.index + len, prefix + chunkName + 'c', {
1516
+ contentOnly: true
1517
+ });
1518
+ }
1519
+ if (s) {
1520
+ _code = s.toString();
1521
+ }
1384
1522
  }
1385
- }
1386
- if (bytecodeChunks.includes(name)) {
1387
- const bytecodeBuffer = await compileToBytecode(_code);
1388
- this.emitFile({
1389
- type: 'asset',
1390
- fileName: name + 'c',
1391
- source: bytecodeBuffer
1392
- });
1393
- if (!removeBundleJS) {
1523
+ if (bytecodeChunks.includes(name)) {
1524
+ const bytecodeBuffer = await compileToBytecode(compiler, _code);
1394
1525
  this.emitFile({
1395
1526
  type: 'asset',
1396
- fileName: '_' + chunk.fileName,
1397
- source: chunk.code
1527
+ fileName: name + 'c',
1528
+ source: bytecodeBuffer
1398
1529
  });
1399
- }
1400
- if (chunk.isEntry) {
1401
- const bytecodeLoaderBlock = getBytecodeLoaderBlock(chunk.fileName);
1402
- const bytecodeModuleBlock = `require("./${path.basename(name) + 'c'}");`;
1403
- const code = `${useStrict}\n${bytecodeLoaderBlock}\n${bytecodeModuleBlock}\n`;
1404
- chunk.code = code;
1530
+ if (!removeBundleJS) {
1531
+ this.emitFile({
1532
+ type: 'asset',
1533
+ fileName: '_' + chunk.fileName,
1534
+ source: chunk.code
1535
+ });
1536
+ }
1537
+ if (chunk.isEntry) {
1538
+ const bytecodeLoaderBlock = getBytecodeLoaderBlock(chunk.fileName);
1539
+ const bytecodeModuleBlock = `require("./${path.basename(name) + 'c'}");`;
1540
+ const code = `${useStrict}\n${bytecodeLoaderBlock}\n${bytecodeModuleBlock}\n`;
1541
+ chunk.code = code;
1542
+ }
1543
+ else {
1544
+ delete output[chunk.fileName];
1545
+ }
1546
+ bytecodeChunkCount += 1;
1405
1547
  }
1406
1548
  else {
1407
- delete output[chunk.fileName];
1408
- }
1409
- bytecodeChunkCount += 1;
1410
- }
1411
- else {
1412
- if (chunk.isEntry) {
1413
- let hasBytecodeMoudle = false;
1414
- const idsToHandle = new Set([...chunk.imports, ...chunk.dynamicImports]);
1415
- for (const moduleId of idsToHandle) {
1416
- if (bytecodeChunks.includes(moduleId)) {
1417
- hasBytecodeMoudle = true;
1418
- break;
1549
+ if (chunk.isEntry) {
1550
+ let hasBytecodeMoudle = false;
1551
+ const idsToHandle = new Set([...chunk.imports, ...chunk.dynamicImports]);
1552
+ for (const moduleId of idsToHandle) {
1553
+ if (bytecodeChunks.includes(moduleId)) {
1554
+ hasBytecodeMoudle = true;
1555
+ break;
1556
+ }
1557
+ const moduleInfo = this.getModuleInfo(moduleId);
1558
+ if (moduleInfo) {
1559
+ const { importers, dynamicImporters } = moduleInfo;
1560
+ for (const importerId of importers)
1561
+ idsToHandle.add(importerId);
1562
+ for (const importerId of dynamicImporters)
1563
+ idsToHandle.add(importerId);
1564
+ }
1419
1565
  }
1420
- const moduleInfo = this.getModuleInfo(moduleId);
1421
- if (moduleInfo) {
1422
- const { importers, dynamicImporters } = moduleInfo;
1423
- for (const importerId of importers)
1424
- idsToHandle.add(importerId);
1425
- for (const importerId of dynamicImporters)
1426
- idsToHandle.add(importerId);
1566
+ if (hasBytecodeMoudle) {
1567
+ const loader = getBytecodeLoaderBlock(chunk.fileName);
1568
+ const strictRE = /^(#![^\n]*\n)?(["'])use strict\2;/;
1569
+ _code = strictRE.test(_code)
1570
+ ? _code.replace(strictRE, `$&\n${loader}`)
1571
+ : _code.replace(/^(#![^\n]*\n)?/, `$&${loader}\n`);
1427
1572
  }
1428
1573
  }
1429
- _code = hasBytecodeMoudle
1430
- ? _code.replace(/("use strict";)|('use strict';)/, `${useStrict}\n${getBytecodeLoaderBlock(chunk.fileName)}`)
1431
- : _code;
1574
+ chunk.code = _code;
1432
1575
  }
1433
- chunk.code = _code;
1434
1576
  }
1435
1577
  }
1436
- }));
1578
+ }
1579
+ finally {
1580
+ await compiler.stop();
1581
+ }
1437
1582
  if (bytecodeChunkCount && !_chunks.some(ass => ass.type === 'asset' && ass.fileName === bytecodeModuleLoader)) {
1438
1583
  this.emitFile({
1439
1584
  type: 'asset',
@@ -1518,6 +1663,114 @@ function protectStringsPlugin(api) {
1518
1663
  };
1519
1664
  }
1520
1665
 
1666
+ const CONFIG_FILE_NAME = 'electron.vite.config';
1667
+ function findConfigFile(configRoot, extensions = ['js', 'ts', 'mjs', 'cjs', 'mts', 'cts']) {
1668
+ for (const ext of extensions) {
1669
+ const configFile = path.resolve(configRoot, `${CONFIG_FILE_NAME}.${ext}`);
1670
+ if (fs.existsSync(configFile)) {
1671
+ return configFile;
1672
+ }
1673
+ }
1674
+ return '';
1675
+ }
1676
+ async function bundleConfigFile(fileName, isESM) {
1677
+ const dirnameVarName = '__electron_vite_injected_dirname';
1678
+ const filenameVarName = '__electron_vite_injected_filename';
1679
+ const importMetaUrlVarName = '__electron_vite_injected_import_meta_url';
1680
+ const bundle = await rolldown({
1681
+ input: path.resolve(fileName),
1682
+ platform: 'node',
1683
+ transform: {
1684
+ target: 'node20',
1685
+ define: {
1686
+ __dirname: dirnameVarName,
1687
+ __filename: filenameVarName,
1688
+ 'import.meta.url': importMetaUrlVarName
1689
+ }
1690
+ },
1691
+ plugins: [
1692
+ {
1693
+ name: 'externalize-deps',
1694
+ resolveId(id) {
1695
+ if (id[0] !== '.' && !path.isAbsolute(id)) {
1696
+ return { id, external: true };
1697
+ }
1698
+ return null;
1699
+ }
1700
+ },
1701
+ {
1702
+ name: 'inject-file-scope-variables',
1703
+ transform: {
1704
+ filter: { id: /\.[cm]?[jt]s$/ },
1705
+ handler(code, id) {
1706
+ const injectValues = `const ${dirnameVarName} = ${JSON.stringify(path.dirname(id))};` +
1707
+ `const ${filenameVarName} = ${JSON.stringify(id)};` +
1708
+ `const ${importMetaUrlVarName} = ${JSON.stringify(pathToFileURL(id).href)};`;
1709
+ return { code: injectValues + code, map: null };
1710
+ }
1711
+ }
1712
+ }
1713
+ ]
1714
+ });
1715
+ let result;
1716
+ try {
1717
+ result = await bundle.generate({
1718
+ format: isESM ? 'esm' : 'cjs',
1719
+ sourcemap: 'inline',
1720
+ sourcemapPathTransform(relative, sourcemapPath) {
1721
+ return path.resolve(path.dirname(sourcemapPath), relative);
1722
+ },
1723
+ codeSplitting: false
1724
+ });
1725
+ }
1726
+ finally {
1727
+ await bundle.close();
1728
+ }
1729
+ const entryChunk = result.output.find((chunk) => chunk.type === 'chunk' && chunk.isEntry);
1730
+ if (!entryChunk) {
1731
+ throw new Error(`Failed to bundle config file: ${fileName}`);
1732
+ }
1733
+ return {
1734
+ code: entryChunk.code,
1735
+ dependencies: entryChunk.moduleIds.filter(id => !id.startsWith('\0'))
1736
+ };
1737
+ }
1738
+ const _require = createRequire(import.meta.url);
1739
+ async function loadConfigFormBundledFile(fileName, bundledCode, isESM) {
1740
+ if (isESM) {
1741
+ const fileNameTmp = `${fileName}.${Date.now()}-${Math.random().toString(16).slice(2)}.mjs`;
1742
+ fs.writeFileSync(fileNameTmp, bundledCode);
1743
+ const fileUrl = pathToFileURL(fileNameTmp);
1744
+ try {
1745
+ return (await import(fileUrl.href)).default;
1746
+ }
1747
+ finally {
1748
+ try {
1749
+ fs.unlinkSync(fileNameTmp);
1750
+ }
1751
+ catch { }
1752
+ }
1753
+ }
1754
+ else {
1755
+ const extension = path.extname(fileName);
1756
+ const realFileName = fs.realpathSync(fileName);
1757
+ const loaderExt = extension in _require.extensions ? extension : '.js';
1758
+ const defaultLoader = _require.extensions[loaderExt];
1759
+ _require.extensions[loaderExt] = (module, filename) => {
1760
+ if (filename === realFileName) {
1761
+ module._compile(bundledCode, filename);
1762
+ }
1763
+ else {
1764
+ defaultLoader(module, filename);
1765
+ }
1766
+ };
1767
+ delete _require.cache[_require.resolve(fileName)];
1768
+ const raw = _require(fileName);
1769
+ _require.extensions[loaderExt] = defaultLoader;
1770
+ return raw.__esModule ? raw.default : raw;
1771
+ }
1772
+ }
1773
+
1521
1774
  function defineConfig(config) {
1522
1775
  return config;
1523
1776
  }
@@ -1574,7 +1827,7 @@ class ConfigFactory {
1574
1827
  }
1575
1828
  async build(cleanMode) {
1576
1829
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
1577
- const config = mergeConfig(deepClone(this.baseConfig), deepClone(this.inlineConfig));
1830
+ const config = mergeConfig(cloneConfig(this.baseConfig), cloneConfig(this.inlineConfig));
1578
1831
  config.mode = this.inlineConfig.mode || config.mode || process.env.NODE_ENV;
1579
1832
  if (this.options.outDir) {
1580
1833
  resetOutDir(config, this.options.outDir, this.processType());
@@ -1687,14 +1940,11 @@ async function resolveConfigDrivenPlugins(config) {
1687
1940
  function isOptions(value) {
1688
1941
  return typeof value === 'object' && value !== null;
1689
1942
  }
1690
- const CONFIG_FILE_NAME = 'electron.vite.config';
1691
1943
  async function loadConfigFromFile(configEnv, configFile, configRoot = process.cwd(), logLevel, ignoreConfigWarning = false) {
1692
1944
  if (configFile && /^vite.config.(js|ts|mjs|cjs|mts|cts)$/.test(configFile)) {
1693
1945
  throw new Error(`config file cannot be named ${configFile}.`);
1694
1946
  }
1695
- const resolvedPath = configFile
1696
- ? path.resolve(configFile)
1697
- : findConfigFile(configRoot, ['js', 'ts', 'mjs', 'cjs', 'mts', 'cts']);
1947
+ const resolvedPath = configFile ? path.resolve(configFile) : findConfigFile(configRoot);
1698
1948
  if (!resolvedPath) {
1699
1949
  return {
1700
1950
  path: '',
@@ -1705,7 +1955,7 @@ async function loadConfigFromFile(configEnv, configFile, configRoot = process.cw
1705
1955
  const isESM = isFilePathESM(resolvedPath);
1706
1956
  try {
1707
1957
  const { code, dependencies } = await bundleConfigFile(resolvedPath, isESM);
1708
- const configExport = await loadConfigFormBundledFile(configRoot, resolvedPath, code, isESM);
1958
+ const configExport = await loadConfigFormBundledFile(resolvedPath, code, isESM);
1709
1959
  const config = await (typeof configExport === 'function' ? configExport(configEnv) : configExport);
1710
1960
  if (!isObject(config)) {
1711
1961
  throw new Error(`config must export or return an object`);
@@ -1727,106 +1977,5 @@ async function loadConfigFromFile(configEnv, configFile, configRoot = process.cw
1727
1977
  throw e;
1728
1978
  }
1729
1979
  }
1730
- function findConfigFile(configRoot, extensions) {
1731
- for (const ext of extensions) {
1732
- const configFile = path.resolve(configRoot, `${CONFIG_FILE_NAME}.${ext}`);
1733
- if (fs.existsSync(configFile)) {
1734
- return configFile;
1735
- }
1736
- }
1737
- return '';
1738
- }
1739
- async function bundleConfigFile(fileName, isESM) {
1740
- const dirnameVarName = '__electron_vite_injected_dirname';
1741
- const filenameVarName = '__electron_vite_injected_filename';
1742
- const importMetaUrlVarName = '__electron_vite_injected_import_meta_url';
1743
- const result = await build$1({
1744
- absWorkingDir: process.cwd(),
1745
- entryPoints: [fileName],
1746
- write: false,
1747
- target: ['node20'],
1748
- platform: 'node',
1749
- bundle: true,
1750
- format: isESM ? 'esm' : 'cjs',
1751
- sourcemap: false,
1752
- metafile: true,
1753
- define: {
1754
- __dirname: dirnameVarName,
1755
- __filename: filenameVarName,
1756
- 'import.meta.url': importMetaUrlVarName
1757
- },
1758
- plugins: [
1759
- {
1760
- name: 'externalize-deps',
1761
- setup(build) {
1762
- build.onResolve({ filter: /.*/ }, args => {
1763
- const id = args.path;
1764
- if (id[0] !== '.' && !path.isAbsolute(id)) {
1765
- return {
1766
- external: true
1767
- };
1768
- }
1769
- return null;
1770
- });
1771
- }
1772
- },
1773
- {
1774
- name: 'replace-import-meta',
1775
- setup(build) {
1776
- build.onLoad({ filter: /\.[cm]?[jt]s$/ }, async (args) => {
1777
- const contents = await fs.promises.readFile(args.path, 'utf8');
1778
- const injectValues = `const ${dirnameVarName} = ${JSON.stringify(path.dirname(args.path))};` +
1779
- `const ${filenameVarName} = ${JSON.stringify(args.path)};` +
1780
- `const ${importMetaUrlVarName} = ${JSON.stringify(pathToFileURL(args.path).href)};`;
1781
- return {
1782
- loader: args.path.endsWith('ts') ? 'ts' : 'js',
1783
- contents: injectValues + contents
1784
- };
1785
- });
1786
- }
1787
- }
1788
- ]
1789
- });
1790
- const { text } = result.outputFiles[0];
1791
- return {
1792
- code: text,
1793
- dependencies: result.metafile ? Object.keys(result.metafile.inputs) : []
1794
- };
1795
- }
1796
- const _require = createRequire(import.meta.url);
1797
- async function loadConfigFormBundledFile(configRoot, configFile, bundledCode, isESM) {
1798
- if (isESM) {
1799
- const fileNameTmp = path.resolve(configRoot, `${CONFIG_FILE_NAME}.${Date.now()}.mjs`);
1800
- fs.writeFileSync(fileNameTmp, bundledCode);
1801
- const fileUrl = pathToFileURL(fileNameTmp);
1802
- try {
1803
- return (await import(fileUrl.href)).default;
1804
- }
1805
- finally {
1806
- try {
1807
- fs.unlinkSync(fileNameTmp);
1808
- }
1809
- catch { }
1810
- }
1811
- }
1812
- else {
1813
- const extension = path.extname(configFile);
1814
- const realFileName = fs.realpathSync(configFile);
1815
- const loaderExt = extension in _require.extensions ? extension : '.js';
1816
- const defaultLoader = _require.extensions[loaderExt];
1817
- _require.extensions[loaderExt] = (module, filename) => {
1818
- if (filename === realFileName) {
1819
- module._compile(bundledCode, filename);
1820
- }
1821
- else {
1822
- defaultLoader(module, filename);
1823
- }
1824
- };
1825
- delete _require.cache[_require.resolve(configFile)];
1826
- const raw = _require(configFile);
1827
- _require.extensions[loaderExt] = defaultLoader;
1828
- return raw.__esModule ? raw.default : raw;
1829
- }
1830
- }
1831
1980
 
1832
1981
  export { ConfigFactory as C, MainConfigFactory as M, PreloadConfigFactory as P, RendererConfigFactory as R, loadEnv as a, bytecodePlugin as b, resolveHostname as c, defineConfig as d, externalizeDepsPlugin as e, loadConfigFromFile as l, resolveConfig as r, startElectron as s };
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@ import { cac } from 'cac';
2
2
  import colors from 'picocolors';
3
3
  import { createLogger } from 'vite';
4
4
 
5
- var version = "6.0.1";
5
+ var version = "6.0.2";
6
6
 
7
7
  const cli = cac('electron-vite');
8
8
  function createInlineConfig(root, options) {
@@ -61,7 +61,7 @@ cli
61
61
  if (options.entry) {
62
62
  process.env.ELECTRON_ENTRY = options.entry;
63
63
  }
64
- const { createServer } = await import('./chunks/lib-CzmB3HUY.js');
64
+ const { createServer } = await import('./chunks/lib-DyA1RI3R.js');
65
65
  const inlineConfig = createInlineConfig(root, options);
66
66
  try {
67
67
  await createServer(inlineConfig, { rendererOnly: options.rendererOnly });
@@ -74,7 +74,7 @@ cli
74
74
  });
75
75
  // build
76
76
  cli.command('build [root]', 'build for production').action(async (root, options) => {
77
- const { build } = await import('./chunks/lib-B8n2vQeG.js');
77
+ const { build } = await import('./chunks/lib-DaHzt8UE.js');
78
78
  const inlineConfig = createInlineConfig(root, options);
79
79
  if (options.entry) {
80
80
  process.env.ELECTRON_ENTRY = options.entry;
@@ -94,7 +94,7 @@ cli
94
94
  .option('--noSandbox', `[boolean] forces renderer process to run un-sandboxed`)
95
95
  .option('--skipBuild', `[boolean] skip build`)
96
96
  .action(async (root, options) => {
97
- const { preview } = await import('./chunks/lib-FYrM-Sbc.js');
97
+ const { preview } = await import('./chunks/lib-ShkGlprt.js');
98
98
  const inlineConfig = createInlineConfig(root, options);
99
99
  if (options.noSandbox) {
100
100
  process.env.NO_SANDBOX = '1';
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
1
  import { createFilter } from 'vite';
2
2
  export { createLogger, defineConfig as defineViteConfig, mergeConfig } from 'vite';
3
- export { C as ConfigFactory, M as MainConfigFactory, P as PreloadConfigFactory, R as RendererConfigFactory, b as bytecodePlugin, d as defineConfig, e as externalizeDepsPlugin, l as loadConfigFromFile, a as loadEnv, r as resolveConfig } from './chunks/lib-CbKPgmtQ.js';
4
- export { createServer } from './chunks/lib-CzmB3HUY.js';
5
- export { build } from './chunks/lib-B8n2vQeG.js';
6
- export { preview } from './chunks/lib-FYrM-Sbc.js';
3
+ export { C as ConfigFactory, M as MainConfigFactory, P as PreloadConfigFactory, R as RendererConfigFactory, b as bytecodePlugin, d as defineConfig, e as externalizeDepsPlugin, l as loadConfigFromFile, a as loadEnv, r as resolveConfig } from './chunks/lib-wmKiubLV.js';
4
+ export { createServer } from './chunks/lib-DyA1RI3R.js';
5
+ export { build } from './chunks/lib-DaHzt8UE.js';
6
+ export { preview } from './chunks/lib-ShkGlprt.js';
7
7
  import { createRequire } from 'node:module';
8
8
  import 'node:path';
9
- import 'node:fs';
10
- import 'node:url';
11
9
  import 'picocolors';
12
- import 'esbuild';
10
+ import 'node:fs';
13
11
  import 'node:child_process';
14
12
  import 'node:crypto';
15
13
  import 'node:fs/promises';
16
14
  import 'magic-string';
17
15
  import '@babel/core';
16
+ import 'node:url';
17
+ import 'rolldown';
18
18
 
19
19
  async function transformWithSWC(code, id, options) {
20
20
  const { sourcemap = false, minify = false } = options;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snoirtrom/electron-vite",
3
- "version": "6.0.1",
3
+ "version": "6.0.2",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/"
6
6
  },
@@ -76,36 +76,35 @@
76
76
  "@rollup/plugin-json": "^6.1.0",
77
77
  "@rollup/plugin-node-resolve": "^16.0.3",
78
78
  "@rollup/plugin-typescript": "^12.3.0",
79
- "@swc/core": "^1.15.21",
79
+ "@swc/core": "^1.16.2",
80
80
  "@types/babel__core": "^7.20.5",
81
- "@types/node": "^22.19.15",
82
- "eslint": "^10.1.0",
81
+ "@types/node": "^22.20.4",
82
+ "eslint": "^10.11.0",
83
83
  "eslint-config-prettier": "^10.1.8",
84
- "eslint-plugin-prettier": "^5.5.5",
85
- "globals": "^17.4.0",
86
- "lint-staged": "^16.4.0",
87
- "prettier": "^3.8.1",
88
- "rollup": "^4.60.0",
89
- "rollup-plugin-dts": "^6.4.1",
84
+ "eslint-plugin-prettier": "^5.5.6",
85
+ "globals": "^17.12.0",
86
+ "lint-staged": "^17.5.1",
87
+ "prettier": "^3.9.9",
88
+ "rollup": "^4.63.5",
89
+ "rollup-plugin-dts": "^6.5.1",
90
90
  "rollup-plugin-rm": "^1.0.2",
91
- "simple-git-hooks": "^2.13.1",
91
+ "simple-git-hooks": "^2.14.0",
92
92
  "tslib": "^2.8.1",
93
- "typescript": "^5.9.3",
94
- "typescript-eslint": "^8.57.2",
95
- "vite": "^8.0.3"
93
+ "typescript": "^6.0.3",
94
+ "typescript-eslint": "^8.70.1",
95
+ "vite": "^8.3.1"
96
96
  },
97
97
  "dependencies": {
98
- "@babel/core": "^7.29.0",
99
- "@babel/plugin-transform-arrow-functions": "^7.27.1",
98
+ "@babel/core": "^7.29.7",
99
+ "@babel/plugin-transform-arrow-functions": "^7.29.7",
100
100
  "cac": "^7.0.0",
101
- "esbuild": "^0.25.11",
102
- "magic-string": "^0.30.21",
103
- "picocolors": "^1.1.1"
101
+ "magic-string": "^1.4.2",
102
+ "picocolors": "^1.1.1",
103
+ "rolldown": "~1.2.10"
104
104
  },
105
105
  "pnpm": {
106
106
  "onlyBuiltDependencies": [
107
107
  "@swc/core",
108
- "esbuild",
109
108
  "simple-git-hooks"
110
109
  ]
111
110
  }