refactor: split electron plugin into preset and validator plugins

This commit is contained in:
alex8088 2025-10-28 21:50:12 +08:00
parent 0a79da03db
commit 88f6db2239
2 changed files with 393 additions and 384 deletions

View File

@ -7,7 +7,7 @@ import {
type UserConfig as ViteConfig, type UserConfig as ViteConfig,
type UserConfigExport as ViteConfigExport, type UserConfigExport as ViteConfigExport,
type ConfigEnv, type ConfigEnv,
type Plugin, type PluginOption,
type LogLevel, type LogLevel,
createLogger, createLogger,
mergeConfig, mergeConfig,
@ -15,7 +15,14 @@ import {
} from 'vite' } from 'vite'
import { build } from 'esbuild' 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 assetPlugin from './plugins/asset'
import workerPlugin from './plugins/worker' import workerPlugin from './plugins/worker'
import importMetaPlugin from './plugins/importMeta' import importMetaPlugin from './plugins/importMeta'
@ -173,21 +180,24 @@ export async function resolveConfig(
resetOutDir(mainViteConfig, outDir, 'main') resetOutDir(mainViteConfig, outDir, 'main')
} }
mergePlugins(mainViteConfig, [ const builtInMainPlugins: PluginOption[] = [
...electronMainVitePlugin({ root }), electronMainConfigPresetPlugin({ root }),
electronMainConfigValidatorPlugin(),
assetPlugin(), assetPlugin(),
workerPlugin(), workerPlugin(),
modulePathPlugin( modulePathPlugin(
mergeConfig( mergeConfig(
{ {
plugins: [electronMainVitePlugin({ root })[0], assetPlugin(), importMetaPlugin(), esmShimPlugin()] plugins: [electronMainConfigPresetPlugin({ root }), assetPlugin(), importMetaPlugin(), esmShimPlugin()]
}, },
mainViteConfig mainViteConfig
) )
), ),
importMetaPlugin(), importMetaPlugin(),
esmShimPlugin() esmShimPlugin()
]) ]
mainViteConfig.plugins = builtInMainPlugins.concat(mainViteConfig.plugins || [])
loadResult.config.main = mainViteConfig loadResult.config.main = mainViteConfig
loadResult.config.main.configFile = false loadResult.config.main.configFile = false
@ -204,29 +214,34 @@ export async function resolveConfig(
if (outDir) { if (outDir) {
resetOutDir(preloadViteConfig, outDir, 'preload') resetOutDir(preloadViteConfig, outDir, 'preload')
} }
mergePlugins(preloadViteConfig, [
...electronPreloadVitePlugin({ root }), const builtInPreloadPlugins: PluginOption[] = [
electronPreloadConfigPresetPlugin({ root }),
electronPreloadConfigValidatorPlugin(),
assetPlugin(), assetPlugin(),
importMetaPlugin(), importMetaPlugin(),
esmShimPlugin(), esmShimPlugin()
...(preloadViteConfig.isolatedEntries ]
? [
isolateEntriesPlugin( if (preloadViteConfig.isolatedEntries) {
mergeConfig( builtInPreloadPlugins.push(
{ isolateEntriesPlugin(
plugins: [ mergeConfig(
electronPreloadVitePlugin({ root })[0], {
assetPlugin(), plugins: [
importMetaPlugin(), electronPreloadConfigPresetPlugin({ root }),
esmShimPlugin() assetPlugin(),
] importMetaPlugin(),
}, esmShimPlugin()
preloadViteConfig ]
) },
) preloadViteConfig
] )
: []) )
]) )
}
preloadViteConfig.plugins = builtInPreloadPlugins.concat(preloadViteConfig.plugins)
loadResult.config.preload = preloadViteConfig loadResult.config.preload = preloadViteConfig
loadResult.config.preload.configFile = false loadResult.config.preload.configFile = false
@ -244,21 +259,25 @@ export async function resolveConfig(
resetOutDir(rendererViteConfig, outDir, 'renderer') resetOutDir(rendererViteConfig, outDir, 'renderer')
} }
mergePlugins(rendererViteConfig, [ const builtInRendererPlugins: PluginOption[] = [
...electronRendererVitePlugin({ root }), electronRendererConfigPresetPlugin({ root }),
...(rendererViteConfig.isolatedEntries electronRendererConfigValidatorPlugin()
? [ ]
isolateEntriesPlugin(
mergeConfig( if (rendererViteConfig.isolatedEntries) {
{ builtInRendererPlugins.push(
plugins: [electronRendererVitePlugin({ root })[0]] isolateEntriesPlugin(
}, mergeConfig(
rendererViteConfig {
) plugins: [electronRendererConfigPresetPlugin({ root })]
) },
] rendererViteConfig
: []) )
]) )
)
}
rendererViteConfig.plugins = builtInRendererPlugins.concat(rendererViteConfig.plugins || [])
loadResult.config.renderer = rendererViteConfig loadResult.config.renderer = rendererViteConfig
loadResult.config.renderer.configFile = false 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' const CONFIG_FILE_NAME = 'electron.vite.config'
export async function loadConfigFromFile( export async function loadConfigFromFile(

View File

@ -50,368 +50,363 @@ function resolveBuildOutputs(
return outputs return outputs
} }
export function electronMainVitePlugin(options?: ElectronPluginOptions): Plugin[] { export function electronMainConfigPresetPlugin(options?: ElectronPluginOptions): Plugin {
return [ return {
{ name: 'vite:electron-main-config-preset',
name: 'vite:electron-main-preset-config', apply: 'build',
apply: 'build', enforce: 'pre',
enforce: 'pre', config(config): void {
config(config): void { const root = options?.root || process.cwd()
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 = { const defaultConfig = {
resolve: { resolve: {
browserField: false, browserField: false,
mainFields: ['module', 'jsnext:main', 'jsnext'], mainFields: ['module', 'jsnext:main', 'jsnext'],
conditions: ['node'] 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: { reportCompressedSize: false,
outDir: path.resolve(root, 'out', 'main'), minify: false
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, '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 libOptions = build.lib
const rollupOptions = build.rollupOptions const outputOptions = rollupOptions.output
defaultConfig.build['lib'] = {
if (!(libOptions && libOptions.entry) && !rollupOptions?.input) { entry: findLibEntry(root, 'main'),
throw new Error( formats:
'An entry point is required in the electron vite main config, ' + libOptions && libOptions.formats && libOptions.formats.length > 0
'which can be specified using "build.lib.entry" or "build.rollupOptions.input".' ? []
) : [outputOptions && !Array.isArray(outputOptions) && outputOptions.format ? outputOptions.format : format]
}
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"' : ''}.`
)
}
}
} }
} 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[] { export function electronMainConfigValidatorPlugin(): Plugin {
return [ return {
{ name: 'vite:electron-main-config-validator',
name: 'vite:electron-preload-preset-config', apply: 'build',
apply: 'build', enforce: 'post',
enforce: 'pre', configResolved(config): void {
config(config): void { const build = config.build
const root = options?.root || process.cwd() if (!build.target) {
throw new Error('build.target option is required in the electron vite main config.')
const nodeTarget = getElectronNodeTarget() } else {
const targets = Array.isArray(build.target) ? build.target : [build.target]
const pkg = loadPackageData() || { type: 'commonjs' } if (targets.some(t => !t.startsWith('node'))) {
throw new Error('The electron vite main config build.target option must be "node?".')
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
} }
},
{ const libOptions = build.lib
name: 'vite:electron-preload-resolved-config', const rollupOptions = build.rollupOptions
apply: 'build',
enforce: 'post', if (!(libOptions && libOptions.entry) && !rollupOptions?.input) {
configResolved(config): void { throw new Error(
const build = config.build 'An entry point is required in the electron vite main config, ' +
if (!build.target) { 'which can be specified using "build.lib.entry" or "build.rollupOptions.input".'
throw new Error('build.target option is required in the electron vite preload config.') )
}
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 { } else {
const targets = Array.isArray(build.target) ? build.target : [build.target] const outpout = outputs[0]
if (targets.some(t => !t.startsWith('node'))) { if (['es', 'cjs'].includes(outpout.format || '')) {
throw new Error('The electron vite preload config build.target must be "node?".') if (outpout.format === 'es' && !supportESM()) {
}
}
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( 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.'
) )
} }
} } else {
} throw new Error(
} `The electron vite main config output format must be "cjs"${supportESM() ? ' or "es"' : ''}.`
}
]
}
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.'
) )
} }
} }
}
}
}
}
const rollupOptions = build.rollupOptions export function electronPreloadConfigPresetPlugin(options?: ElectronPluginOptions): Plugin {
if (!rollupOptions.input) { return {
config.logger.warn(colors.yellow(`index.html file is not found in ${colors.dim('/src/renderer')} directory.`)) name: 'vite:electron-preload-config-preset',
throw new Error('build.rollupOptions.input option is required in the electron vite renderer 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
}
}
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.')
}
}
}
} }