From 88f6db2239a6d731953f0e0b185ce1becce4fe63 Mon Sep 17 00:00:00 2001 From: alex8088 <244096523@qq.com> Date: Tue, 28 Oct 2025 21:50:12 +0800 Subject: [PATCH] refactor: split electron plugin into preset and validator plugins --- src/config.ts | 108 ++++--- src/plugins/electron.ts | 669 ++++++++++++++++++++-------------------- 2 files changed, 393 insertions(+), 384 deletions(-) diff --git a/src/config.ts b/src/config.ts index 86041cb..4ad9f3c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,7 +7,7 @@ import { type UserConfig as ViteConfig, type UserConfigExport as ViteConfigExport, type ConfigEnv, - type Plugin, + type PluginOption, type LogLevel, createLogger, mergeConfig, @@ -15,7 +15,14 @@ import { } from 'vite' import { build } from 'esbuild' -import { electronMainVitePlugin, electronPreloadVitePlugin, electronRendererVitePlugin } from './plugins/electron' +import { + electronMainConfigPresetPlugin, + electronMainConfigValidatorPlugin, + electronPreloadConfigPresetPlugin, + electronPreloadConfigValidatorPlugin, + electronRendererConfigPresetPlugin, + electronRendererConfigValidatorPlugin +} from './plugins/electron' import assetPlugin from './plugins/asset' import workerPlugin from './plugins/worker' import importMetaPlugin from './plugins/importMeta' @@ -173,21 +180,24 @@ export async function resolveConfig( resetOutDir(mainViteConfig, outDir, 'main') } - mergePlugins(mainViteConfig, [ - ...electronMainVitePlugin({ root }), + const builtInMainPlugins: PluginOption[] = [ + electronMainConfigPresetPlugin({ root }), + electronMainConfigValidatorPlugin(), assetPlugin(), workerPlugin(), modulePathPlugin( mergeConfig( { - plugins: [electronMainVitePlugin({ root })[0], assetPlugin(), importMetaPlugin(), esmShimPlugin()] + plugins: [electronMainConfigPresetPlugin({ root }), assetPlugin(), importMetaPlugin(), esmShimPlugin()] }, mainViteConfig ) ), importMetaPlugin(), esmShimPlugin() - ]) + ] + + mainViteConfig.plugins = builtInMainPlugins.concat(mainViteConfig.plugins || []) loadResult.config.main = mainViteConfig loadResult.config.main.configFile = false @@ -204,29 +214,34 @@ export async function resolveConfig( if (outDir) { resetOutDir(preloadViteConfig, outDir, 'preload') } - mergePlugins(preloadViteConfig, [ - ...electronPreloadVitePlugin({ root }), + + const builtInPreloadPlugins: PluginOption[] = [ + electronPreloadConfigPresetPlugin({ root }), + electronPreloadConfigValidatorPlugin(), assetPlugin(), importMetaPlugin(), - esmShimPlugin(), - ...(preloadViteConfig.isolatedEntries - ? [ - isolateEntriesPlugin( - mergeConfig( - { - plugins: [ - electronPreloadVitePlugin({ root })[0], - assetPlugin(), - importMetaPlugin(), - esmShimPlugin() - ] - }, - preloadViteConfig - ) - ) - ] - : []) - ]) + esmShimPlugin() + ] + + if (preloadViteConfig.isolatedEntries) { + builtInPreloadPlugins.push( + isolateEntriesPlugin( + mergeConfig( + { + plugins: [ + electronPreloadConfigPresetPlugin({ root }), + assetPlugin(), + importMetaPlugin(), + esmShimPlugin() + ] + }, + preloadViteConfig + ) + ) + ) + } + + preloadViteConfig.plugins = builtInPreloadPlugins.concat(preloadViteConfig.plugins) loadResult.config.preload = preloadViteConfig loadResult.config.preload.configFile = false @@ -244,21 +259,25 @@ export async function resolveConfig( resetOutDir(rendererViteConfig, outDir, 'renderer') } - mergePlugins(rendererViteConfig, [ - ...electronRendererVitePlugin({ root }), - ...(rendererViteConfig.isolatedEntries - ? [ - isolateEntriesPlugin( - mergeConfig( - { - plugins: [electronRendererVitePlugin({ root })[0]] - }, - rendererViteConfig - ) - ) - ] - : []) - ]) + const builtInRendererPlugins: PluginOption[] = [ + electronRendererConfigPresetPlugin({ root }), + electronRendererConfigValidatorPlugin() + ] + + if (rendererViteConfig.isolatedEntries) { + builtInRendererPlugins.push( + isolateEntriesPlugin( + mergeConfig( + { + plugins: [electronRendererConfigPresetPlugin({ root })] + }, + rendererViteConfig + ) + ) + ) + } + + rendererViteConfig.plugins = builtInRendererPlugins.concat(rendererViteConfig.plugins || []) loadResult.config.renderer = rendererViteConfig loadResult.config.renderer.configFile = false @@ -295,11 +314,6 @@ function resetOutDir(config: ViteConfig, outDir: string, subOutDir: string): voi } } -function mergePlugins(config: ViteConfig, plugins: Plugin[]): void { - const userPlugins = config.plugins || [] - config.plugins = userPlugins.concat(plugins) -} - const CONFIG_FILE_NAME = 'electron.vite.config' export async function loadConfigFromFile( diff --git a/src/plugins/electron.ts b/src/plugins/electron.ts index 1ac861c..2f2a340 100644 --- a/src/plugins/electron.ts +++ b/src/plugins/electron.ts @@ -50,368 +50,363 @@ function resolveBuildOutputs( return outputs } -export function electronMainVitePlugin(options?: ElectronPluginOptions): Plugin[] { - return [ - { - name: 'vite:electron-main-preset-config', - apply: 'build', - enforce: 'pre', - config(config): void { - const root = options?.root || process.cwd() +export function electronMainConfigPresetPlugin(options?: ElectronPluginOptions): Plugin { + return { + name: 'vite:electron-main-config-preset', + apply: 'build', + enforce: 'pre', + config(config): void { + const root = options?.root || process.cwd() - const nodeTarget = getElectronNodeTarget() + const nodeTarget = getElectronNodeTarget() - const pkg = loadPackageData() || { type: 'commonjs' } + const pkg = loadPackageData() || { type: 'commonjs' } - const format = pkg.type && pkg.type === 'module' && supportESM() ? 'es' : 'cjs' + const format = pkg.type && pkg.type === 'module' && supportESM() ? 'es' : 'cjs' - const defaultConfig = { - resolve: { - browserField: false, - mainFields: ['module', 'jsnext:main', 'jsnext'], - conditions: ['node'] + const defaultConfig = { + resolve: { + browserField: false, + mainFields: ['module', 'jsnext:main', 'jsnext'], + conditions: ['node'] + }, + build: { + outDir: path.resolve(root, 'out', 'main'), + target: nodeTarget, + assetsDir: 'chunks', + rollupOptions: { + external: ['electron', /^electron\/.+/, ...builtinModules.flatMap(m => [m, `node:${m}`])], + output: {} }, - build: { - outDir: path.resolve(root, 'out', 'main'), - target: nodeTarget, - assetsDir: 'chunks', - rollupOptions: { - external: ['electron', /^electron\/.+/, ...builtinModules.flatMap(m => [m, `node:${m}`])], - output: {} - }, - reportCompressedSize: false, - minify: false - } + reportCompressedSize: false, + minify: false } - - const build = config.build || {} - const rollupOptions = build.rollupOptions || {} - if (!rollupOptions.input) { - const libOptions = build.lib - const outputOptions = rollupOptions.output - defaultConfig.build['lib'] = { - entry: findLibEntry(root, 'main'), - formats: - libOptions && libOptions.formats && libOptions.formats.length > 0 - ? [] - : [ - outputOptions && !Array.isArray(outputOptions) && outputOptions.format - ? outputOptions.format - : format - ] - } - } else { - defaultConfig.build.rollupOptions.output['format'] = format - } - - defaultConfig.build.rollupOptions.output['assetFileNames'] = path.posix.join( - build.assetsDir || defaultConfig.build.assetsDir, - '[name]-[hash].[ext]' - ) - - const buildConfig = mergeConfig(defaultConfig.build, build) - config.build = buildConfig - - config.resolve = mergeConfig(defaultConfig.resolve, config.resolve || {}) - - config.define = config.define || {} - config.define = { ...processEnvDefine(), ...config.define } - - config.envPrefix = config.envPrefix || ['MAIN_VITE_', 'VITE_'] - - config.publicDir = config.publicDir || 'resources' - // do not copy public dir - config.build.copyPublicDir = false - // module preload polyfill does not apply to nodejs (main process) - config.build.modulePreload = false - // enable ssr build - config.build.ssr = true - config.build.ssrEmitAssets = true - config.ssr = { ...config.ssr, ...{ noExternal: true } } } - }, - { - name: 'vite:electron-main-resolved-config', - apply: 'build', - enforce: 'post', - configResolved(config): void { - const build = config.build - if (!build.target) { - throw new Error('build.target option is required in the electron vite main config.') - } else { - const targets = Array.isArray(build.target) ? build.target : [build.target] - if (targets.some(t => !t.startsWith('node'))) { - throw new Error('The electron vite main config build.target option must be "node?".') - } - } + const build = config.build || {} + const rollupOptions = build.rollupOptions || {} + if (!rollupOptions.input) { const libOptions = build.lib - const rollupOptions = build.rollupOptions - - if (!(libOptions && libOptions.entry) && !rollupOptions?.input) { - throw new Error( - 'An entry point is required in the electron vite main config, ' + - 'which can be specified using "build.lib.entry" or "build.rollupOptions.input".' - ) - } - - const resolvedOutputs = resolveBuildOutputs(rollupOptions.output, libOptions) - - if (resolvedOutputs) { - const outputs = Array.isArray(resolvedOutputs) ? resolvedOutputs : [resolvedOutputs] - if (outputs.length > 1) { - throw new Error('The electron vite main config does not support multiple outputs.') - } else { - const outpout = outputs[0] - if (['es', 'cjs'].includes(outpout.format || '')) { - if (outpout.format === 'es' && !supportESM()) { - throw new Error( - 'The electron vite main config output format does not support "es", ' + - 'you can upgrade electron to the latest version or switch to "cjs" format.' - ) - } - } else { - throw new Error( - `The electron vite main config output format must be "cjs"${supportESM() ? ' or "es"' : ''}.` - ) - } - } + const outputOptions = rollupOptions.output + defaultConfig.build['lib'] = { + entry: findLibEntry(root, 'main'), + formats: + libOptions && libOptions.formats && libOptions.formats.length > 0 + ? [] + : [outputOptions && !Array.isArray(outputOptions) && outputOptions.format ? outputOptions.format : format] } + } else { + defaultConfig.build.rollupOptions.output['format'] = format } + + defaultConfig.build.rollupOptions.output['assetFileNames'] = path.posix.join( + build.assetsDir || defaultConfig.build.assetsDir, + '[name]-[hash].[ext]' + ) + + const buildConfig = mergeConfig(defaultConfig.build, build) + config.build = buildConfig + + config.resolve = mergeConfig(defaultConfig.resolve, config.resolve || {}) + + config.define = config.define || {} + config.define = { ...processEnvDefine(), ...config.define } + + config.envPrefix = config.envPrefix || ['MAIN_VITE_', 'VITE_'] + + config.publicDir = config.publicDir || 'resources' + // do not copy public dir + config.build.copyPublicDir = false + // module preload polyfill does not apply to nodejs (main process) + config.build.modulePreload = false + // enable ssr build + config.build.ssr = true + config.build.ssrEmitAssets = true + config.ssr = { ...config.ssr, ...{ noExternal: true } } } - ] + } } -export function electronPreloadVitePlugin(options?: ElectronPluginOptions): Plugin[] { - return [ - { - name: 'vite:electron-preload-preset-config', - apply: 'build', - enforce: 'pre', - config(config): void { - const root = options?.root || process.cwd() - - const nodeTarget = getElectronNodeTarget() - - const pkg = loadPackageData() || { type: 'commonjs' } - - const format = pkg.type && pkg.type === 'module' && supportESM() ? 'es' : 'cjs' - - const defaultConfig = { - ssr: { - resolve: { - conditions: ['module', 'browser', 'development|production'], - mainFields: ['browser', 'module', 'jsnext:main', 'jsnext'] - } - }, - build: { - outDir: path.resolve(root, 'out', 'preload'), - target: nodeTarget, - assetsDir: 'chunks', - rollupOptions: { - external: ['electron', /^electron\/.+/, ...builtinModules.flatMap(m => [m, `node:${m}`])], - output: {} - }, - reportCompressedSize: false, - minify: false - } +export function electronMainConfigValidatorPlugin(): Plugin { + return { + name: 'vite:electron-main-config-validator', + apply: 'build', + enforce: 'post', + configResolved(config): void { + const build = config.build + if (!build.target) { + throw new Error('build.target option is required in the electron vite main config.') + } else { + const targets = Array.isArray(build.target) ? build.target : [build.target] + if (targets.some(t => !t.startsWith('node'))) { + throw new Error('The electron vite main config build.target option must be "node?".') } - - const build = config.build || {} - const rollupOptions = build.rollupOptions || {} - if (!rollupOptions.input) { - const libOptions = build.lib - const outputOptions = rollupOptions.output - defaultConfig.build['lib'] = { - entry: findLibEntry(root, 'preload'), - formats: - libOptions && libOptions.formats && libOptions.formats.length > 0 - ? [] - : [ - outputOptions && !Array.isArray(outputOptions) && outputOptions.format - ? outputOptions.format - : format - ] - } - } else { - defaultConfig.build.rollupOptions.output['format'] = format - } - - defaultConfig.build.rollupOptions.output['assetFileNames'] = path.posix.join( - build.assetsDir || defaultConfig.build.assetsDir, - '[name]-[hash].[ext]' - ) - - const buildConfig = mergeConfig(defaultConfig.build, build) - config.build = buildConfig - - const resolvedOutputs = resolveBuildOutputs(config.build.rollupOptions!.output, config.build.lib || false) - - if (resolvedOutputs) { - const outputs = Array.isArray(resolvedOutputs) ? resolvedOutputs : [resolvedOutputs] - - if (outputs.find(({ format }) => format === 'es')) { - if (Array.isArray(config.build.rollupOptions!.output)) { - config.build.rollupOptions!.output.forEach(output => { - if (output.format === 'es') { - output['entryFileNames'] = '[name].mjs' - output['chunkFileNames'] = '[name]-[hash].mjs' - } - }) - } else { - config.build.rollupOptions!.output!['entryFileNames'] = '[name].mjs' - config.build.rollupOptions!.output!['chunkFileNames'] = '[name]-[hash].mjs' - } - } - } - - config.define = config.define || {} - config.define = { ...processEnvDefine(), ...config.define } - - config.envPrefix = config.envPrefix || ['PRELOAD_VITE_', 'VITE_'] - - config.publicDir = config.publicDir || 'resources' - // do not copy public dir - config.build.copyPublicDir = false - // module preload polyfill does not apply to nodejs (preload scripts) - config.build.modulePreload = false - // enable ssr build - config.build.ssr = true - config.build.ssrEmitAssets = true - config.ssr = mergeConfig(defaultConfig.ssr, config.ssr || {}) - config.ssr.noExternal = true } - }, - { - name: 'vite:electron-preload-resolved-config', - apply: 'build', - enforce: 'post', - configResolved(config): void { - const build = config.build - if (!build.target) { - throw new Error('build.target option is required in the electron vite preload config.') + + const libOptions = build.lib + const rollupOptions = build.rollupOptions + + if (!(libOptions && libOptions.entry) && !rollupOptions?.input) { + throw new Error( + 'An entry point is required in the electron vite main config, ' + + 'which can be specified using "build.lib.entry" or "build.rollupOptions.input".' + ) + } + + const resolvedOutputs = resolveBuildOutputs(rollupOptions.output, libOptions) + + if (resolvedOutputs) { + const outputs = Array.isArray(resolvedOutputs) ? resolvedOutputs : [resolvedOutputs] + if (outputs.length > 1) { + throw new Error('The electron vite main config does not support multiple outputs.') } else { - const targets = Array.isArray(build.target) ? build.target : [build.target] - if (targets.some(t => !t.startsWith('node'))) { - throw new Error('The electron vite preload config build.target must be "node?".') - } - } - - const libOptions = build.lib - const rollupOptions = build.rollupOptions - - if (!(libOptions && libOptions.entry) && !rollupOptions?.input) { - throw new Error( - 'An entry point is required in the electron vite preload config, ' + - 'which can be specified using "build.lib.entry" or "build.rollupOptions.input".' - ) - } - - const resolvedOutputs = resolveBuildOutputs(rollupOptions.output, libOptions) - - if (resolvedOutputs) { - const outputs = Array.isArray(resolvedOutputs) ? resolvedOutputs : [resolvedOutputs] - if (outputs.length > 1) { - throw new Error('The electron vite preload config does not support multiple outputs.') - } else { - const outpout = outputs[0] - if (['es', 'cjs'].includes(outpout.format || '')) { - if (outpout.format === 'es' && !supportESM()) { - throw new Error( - 'The electron vite preload config output format does not support "es", ' + - 'you can upgrade electron to the latest version or switch to "cjs" format.' - ) - } - } else { + const outpout = outputs[0] + if (['es', 'cjs'].includes(outpout.format || '')) { + if (outpout.format === 'es' && !supportESM()) { throw new Error( - `The electron vite preload config output format must be "cjs"${supportESM() ? ' or "es"' : ''}.` + 'The electron vite main config output format does not support "es", ' + + 'you can upgrade electron to the latest version or switch to "cjs" format.' ) } - } - } - } - } - ] -} - -export function electronRendererVitePlugin(options?: ElectronPluginOptions): Plugin[] { - return [ - { - name: 'vite:electron-renderer-preset-config', - enforce: 'pre', - config(config): void { - const root = options?.root || process.cwd() - - config.base = - config.mode === 'production' || process.env.NODE_ENV_ELECTRON_VITE === 'production' ? './' : config.base - config.root = config.root || './src/renderer' - - const chromeTarget = getElectronChromeTarget() - - const emptyOutDir = (): boolean => { - let outDir = config.build?.outDir - if (outDir) { - if (!path.isAbsolute(outDir)) { - outDir = path.resolve(root, outDir) - } - const resolvedRoot = normalizePath(path.resolve(root)) - return normalizePath(outDir).startsWith(resolvedRoot + '/') - } - return true - } - - const defaultConfig = { - build: { - outDir: path.resolve(root, 'out', 'renderer'), - target: chromeTarget, - modulePreload: { polyfill: false }, - rollupOptions: { - input: findInput(root) - }, - reportCompressedSize: false, - minify: false, - emptyOutDir: emptyOutDir() - } - } - - if (config.build?.outDir) { - config.build.outDir = path.resolve(root, config.build.outDir) - } - - const buildConfig = mergeConfig(defaultConfig.build, config.build || {}) - config.build = buildConfig - - config.envDir = config.envDir || path.resolve(root) - - config.envPrefix = config.envPrefix || ['RENDERER_VITE_', 'VITE_'] - } - }, - { - name: 'vite:electron-renderer-resolved-config', - enforce: 'post', - configResolved(config): void { - if (config.base !== './' && config.base !== '/') { - config.logger.warn(colors.yellow('(!) Should not set "base" option for the electron vite renderer config.')) - } - - const build = config.build - if (!build.target) { - throw new Error('build.target option is required in the electron vite renderer config.') - } else { - const targets = Array.isArray(build.target) ? build.target : [build.target] - if (targets.some(t => !t.startsWith('chrome') && !/^es((202\d{1})|next)$/.test(t))) { - config.logger.warn( - 'The electron vite renderer config build.target is not "chrome?" or "es?". This could be a mistake.' + } else { + throw new Error( + `The electron vite main config output format must be "cjs"${supportESM() ? ' or "es"' : ''}.` ) } } + } + } + } +} - const rollupOptions = build.rollupOptions - if (!rollupOptions.input) { - config.logger.warn(colors.yellow(`index.html file is not found in ${colors.dim('/src/renderer')} directory.`)) - throw new Error('build.rollupOptions.input option is required in the electron vite renderer config.') +export function electronPreloadConfigPresetPlugin(options?: ElectronPluginOptions): Plugin { + return { + name: 'vite:electron-preload-config-preset', + apply: 'build', + enforce: 'pre', + config(config): void { + const root = options?.root || process.cwd() + + const nodeTarget = getElectronNodeTarget() + + const pkg = loadPackageData() || { type: 'commonjs' } + + const format = pkg.type && pkg.type === 'module' && supportESM() ? 'es' : 'cjs' + + const defaultConfig = { + ssr: { + resolve: { + conditions: ['module', 'browser', 'development|production'], + mainFields: ['browser', 'module', 'jsnext:main', 'jsnext'] + } + }, + build: { + outDir: path.resolve(root, 'out', 'preload'), + target: nodeTarget, + assetsDir: 'chunks', + rollupOptions: { + external: ['electron', /^electron\/.+/, ...builtinModules.flatMap(m => [m, `node:${m}`])], + output: {} + }, + reportCompressedSize: false, + minify: false + } + } + + const build = config.build || {} + const rollupOptions = build.rollupOptions || {} + if (!rollupOptions.input) { + const libOptions = build.lib + const outputOptions = rollupOptions.output + defaultConfig.build['lib'] = { + entry: findLibEntry(root, 'preload'), + formats: + libOptions && libOptions.formats && libOptions.formats.length > 0 + ? [] + : [outputOptions && !Array.isArray(outputOptions) && outputOptions.format ? outputOptions.format : format] + } + } else { + defaultConfig.build.rollupOptions.output['format'] = format + } + + defaultConfig.build.rollupOptions.output['assetFileNames'] = path.posix.join( + build.assetsDir || defaultConfig.build.assetsDir, + '[name]-[hash].[ext]' + ) + + const buildConfig = mergeConfig(defaultConfig.build, build) + config.build = buildConfig + + const resolvedOutputs = resolveBuildOutputs(config.build.rollupOptions!.output, config.build.lib || false) + + if (resolvedOutputs) { + const outputs = Array.isArray(resolvedOutputs) ? resolvedOutputs : [resolvedOutputs] + + if (outputs.find(({ format }) => format === 'es')) { + if (Array.isArray(config.build.rollupOptions!.output)) { + config.build.rollupOptions!.output.forEach(output => { + if (output.format === 'es') { + output['entryFileNames'] = '[name].mjs' + output['chunkFileNames'] = '[name]-[hash].mjs' + } + }) + } else { + config.build.rollupOptions!.output!['entryFileNames'] = '[name].mjs' + config.build.rollupOptions!.output!['chunkFileNames'] = '[name]-[hash].mjs' + } + } + } + + config.define = config.define || {} + config.define = { ...processEnvDefine(), ...config.define } + + config.envPrefix = config.envPrefix || ['PRELOAD_VITE_', 'VITE_'] + + config.publicDir = config.publicDir || 'resources' + // do not copy public dir + config.build.copyPublicDir = false + // module preload polyfill does not apply to nodejs (preload scripts) + config.build.modulePreload = false + // enable ssr build + config.build.ssr = true + config.build.ssrEmitAssets = true + config.ssr = mergeConfig(defaultConfig.ssr, config.ssr || {}) + config.ssr.noExternal = true + } + } +} + +export function electronPreloadConfigValidatorPlugin(): Plugin { + return { + name: 'vite:electron-preload-config-validator', + apply: 'build', + enforce: 'post', + configResolved(config): void { + const build = config.build + if (!build.target) { + throw new Error('build.target option is required in the electron vite preload config.') + } else { + const targets = Array.isArray(build.target) ? build.target : [build.target] + if (targets.some(t => !t.startsWith('node'))) { + throw new Error('The electron vite preload config build.target must be "node?".') + } + } + + const libOptions = build.lib + const rollupOptions = build.rollupOptions + + if (!(libOptions && libOptions.entry) && !rollupOptions?.input) { + throw new Error( + 'An entry point is required in the electron vite preload config, ' + + 'which can be specified using "build.lib.entry" or "build.rollupOptions.input".' + ) + } + + const resolvedOutputs = resolveBuildOutputs(rollupOptions.output, libOptions) + + if (resolvedOutputs) { + const outputs = Array.isArray(resolvedOutputs) ? resolvedOutputs : [resolvedOutputs] + if (outputs.length > 1) { + throw new Error('The electron vite preload config does not support multiple outputs.') + } else { + const outpout = outputs[0] + if (['es', 'cjs'].includes(outpout.format || '')) { + if (outpout.format === 'es' && !supportESM()) { + throw new Error( + 'The electron vite preload config output format does not support "es", ' + + 'you can upgrade electron to the latest version or switch to "cjs" format.' + ) + } + } else { + throw new Error( + `The electron vite preload config output format must be "cjs"${supportESM() ? ' or "es"' : ''}.` + ) + } } } } - ] + } +} + +export function electronRendererConfigPresetPlugin(options?: ElectronPluginOptions): Plugin { + return { + name: 'vite:electron-renderer-config-preset', + enforce: 'pre', + config(config): void { + const root = options?.root || process.cwd() + + config.base = + config.mode === 'production' || process.env.NODE_ENV_ELECTRON_VITE === 'production' ? './' : config.base + config.root = config.root || './src/renderer' + + const chromeTarget = getElectronChromeTarget() + + const emptyOutDir = (): boolean => { + let outDir = config.build?.outDir + if (outDir) { + if (!path.isAbsolute(outDir)) { + outDir = path.resolve(root, outDir) + } + const resolvedRoot = normalizePath(path.resolve(root)) + return normalizePath(outDir).startsWith(resolvedRoot + '/') + } + return true + } + + const defaultConfig = { + build: { + outDir: path.resolve(root, 'out', 'renderer'), + target: chromeTarget, + modulePreload: { polyfill: false }, + rollupOptions: { + input: findInput(root) + }, + reportCompressedSize: false, + minify: false, + emptyOutDir: emptyOutDir() + } + } + + if (config.build?.outDir) { + config.build.outDir = path.resolve(root, config.build.outDir) + } + + const buildConfig = mergeConfig(defaultConfig.build, config.build || {}) + config.build = buildConfig + + config.envDir = config.envDir || path.resolve(root) + + config.envPrefix = config.envPrefix || ['RENDERER_VITE_', 'VITE_'] + } + } +} + +export function electronRendererConfigValidatorPlugin(): Plugin { + return { + name: 'vite:electron-renderer-config-validator', + enforce: 'post', + configResolved(config): void { + if (config.base !== './' && config.base !== '/') { + config.logger.warn(colors.yellow('(!) Should not set "base" option for the electron vite renderer config.')) + } + + const build = config.build + if (!build.target) { + throw new Error('build.target option is required in the electron vite renderer config.') + } else { + const targets = Array.isArray(build.target) ? build.target : [build.target] + if (targets.some(t => !t.startsWith('chrome') && !/^es((202\d{1})|next)$/.test(t))) { + config.logger.warn( + 'The electron vite renderer config build.target is not "chrome?" or "es?". This could be a mistake.' + ) + } + } + + const rollupOptions = build.rollupOptions + if (!rollupOptions.input) { + config.logger.warn(colors.yellow(`index.html file is not found in ${colors.dim('/src/renderer')} directory.`)) + throw new Error('build.rollupOptions.input option is required in the electron vite renderer config.') + } + } + } }