From 00f2bb1933978036f91c2f2a450c1d9c42e14dce Mon Sep 17 00:00:00 2001 From: George Xu Date: Wed, 30 Nov 2022 15:34:29 -0800 Subject: [PATCH 01/18] compile 4 webpackRendererConfigs instead of N. Co-authored-by: Samuel Attard Co-authored-by: Keeley Hammond --- packages/plugin/webpack/src/WebpackConfig.ts | 130 ++++++++++++++++++- packages/plugin/webpack/src/WebpackPlugin.ts | 2 +- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index f95ace427f..f028e91ee6 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -20,6 +20,13 @@ export type ConfigurationFactory = ( args: Record ) => Configuration | Promise; +enum RendererTarget { + Web = 'web', + ElectronRenderer = 'electron-renderer', + ElectronPreload = 'electron-preload', + SandboxedPreload = 'web', +} + export default class WebpackConfigGenerator { private isProd: boolean; @@ -70,7 +77,7 @@ export default class WebpackConfigGenerator { } rendererTarget(entryPoint: WebpackPluginEntryPoint): string { - return entryPoint.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration ? 'electron-renderer' : 'web'; + return entryPoint.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration ? RendererTarget.ElectronRenderer : RendererTarget.Web; } rendererEntryPoint(entryPoint: WebpackPluginEntryPoint, inRendererDir: boolean, basename: string): string { @@ -178,7 +185,7 @@ export default class WebpackConfigGenerator { entry: prefixedEntries.concat([entryPoint.preload.js]), output: { path: path.resolve(this.webpackDir, 'renderer', entryPoint.name), - filename: 'preload.js', + filename: 'preload.j s', }, node: { __dirname: false, @@ -190,7 +197,7 @@ export default class WebpackConfigGenerator { ); } - async getRendererConfig(entryPoints: WebpackPluginEntryPoint[]): Promise { + async getRendererConfig2(entryPoints: WebpackPluginEntryPoint[]): Promise { const rendererConfig = await this.resolveConfig(this.pluginConfig.renderer.config); return entryPoints.map((entryPoint) => { @@ -273,4 +280,121 @@ export default class WebpackConfigGenerator { } }); } + + async getRendererConfig(entryPoints: WebpackPluginEntryPoint[]): Promise { + const targets = { + web: [] as (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPoint)[], + electronRenderer: [] as (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPoint)[], + electronPreload: [] as (WebpackPluginEntryPointPreloadOnly | WebpackPluginEntryPointLocalWindow)[], + sandboxedPreload: [] as (WebpackPluginEntryPointPreloadOnly | WebpackPluginEntryPointLocalWindow)[], + }; + for (const entry of entryPoints) { + if (entry.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration) { + // Has node + if (isPreloadOnly(entry)) { + targets.electronPreload.push(entry); + } else { + targets.electronRenderer.push(entry); + if (isLocalWindow(entry) && entry.preload) { + targets.electronPreload.push(entry); + } + } + } else { + // No node + if (isPreloadOnly(entry)) { + targets.sandboxedPreload.push(entry); + } else { + targets.web.push(entry); + if (isLocalWindow(entry) && entry.preload) { + targets.sandboxedPreload.push(entry); + } + } + } + } + console.log('targets', targets); + return [ + await this.buildRendererConfig(targets.web, RendererTarget.Web), + await this.buildRendererConfig(targets.electronRenderer, RendererTarget.ElectronRenderer), + await this.buildRendererConfig(targets.electronPreload, RendererTarget.ElectronPreload), + await this.buildRendererConfig(targets.sandboxedPreload, RendererTarget.SandboxedPreload), + ].filter(function isNotNull(item: T | null): item is T { + return !!item; + }); + } + + buildRendererBaseConfig(target: RendererTarget): webpack.Configuration { + return { + target, + devtool: this.rendererSourceMapOption, + mode: this.mode, + output: { + path: path.resolve(this.webpackDir, 'renderer'), + filename: '[name]/index.js', + globalObject: 'self', + ...(this.isProd ? {} : { publicPath: '/' }), + }, + node: { + __dirname: false, + __filename: false, + }, + plugins: [new AssetRelocatorPatch(this.isProd, !!this.pluginConfig.renderer.nodeIntegration)], + }; + } + + async buildRendererConfig(entryPoints: WebpackPluginEntryPoint[], target: RendererTarget): Promise { + const entry: webpack.Entry = {}; + + if (entryPoints.length === 0) { + return null; + } + const baseConfig: webpack.Configuration = this.buildRendererBaseConfig(target); + const rendererConfig = await this.resolveConfig(this.pluginConfig.renderer.config); + + if (target === RendererTarget.Web || target === RendererTarget.ElectronRenderer) { + for (const entryPoint of entryPoints) { + entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([isPreloadOnly(entryPoint) ? entryPoint.preload.js : entryPoint.js]); + } + const output = { + path: path.resolve(this.webpackDir, 'renderer'), + filename: '[name]/index.js', + globalObject: 'self', + ...(this.isProd ? {} : { publicPath: '/' }), + }; + const plugins: webpack.WebpackPluginInstance[] = []; + for (const entryPoint of entryPoints) { + if (isLocalWindow(entryPoint)) { + plugins.push( + new HtmlWebpackPlugin({ + title: entryPoint.name, + template: entryPoint.html, + filename: `${entryPoint.name}/index.html`, + chunks: [entryPoint.name].concat(entryPoint.additionalChunks || []), + }) as WebpackPluginInstance + ); + } + } + return webpackMerge(baseConfig, { entry, output, plugins }, rendererConfig || {}); + } else if (target === RendererTarget.ElectronPreload || target === RendererTarget.SandboxedPreload) { + for (const entryPoint of entryPoints) { + entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([isPreloadOnly(entryPoint) ? entryPoint.preload.js : entryPoint.js]); + } + const config: Configuration = { + target, + entry, + output: { + path: path.resolve(this.webpackDir, 'renderer'), + filename: 'preload.js', + globalObject: 'self', + ...(this.isProd ? {} : { publicPath: '/' }), + }, + plugins: + target === RendererTarget.ElectronPreload + ? [] + : [new webpack.ExternalsPlugin('commonjs2', ['electron', 'electron/renderer', 'electron/common', 'events', 'timers', 'url'])], + }; + return webpackMerge(baseConfig, config, rendererConfig); + } else { + throw new Error('Invalid renderer entry point detected.'); + } + } } diff --git a/packages/plugin/webpack/src/WebpackPlugin.ts b/packages/plugin/webpack/src/WebpackPlugin.ts index 58d547ad20..9a79fab6a1 100644 --- a/packages/plugin/webpack/src/WebpackPlugin.ts +++ b/packages/plugin/webpack/src/WebpackPlugin.ts @@ -301,7 +301,7 @@ the generated files). Instead, it is ${JSON.stringify(pj.main)}`); const pluginLogs = new ElectronForgeLoggingPlugin(tab); const config = await this.configGenerator.getRendererConfig(this.config.renderer.entryPoints); - + console.log('renderer config: ', config); if (config.length === 0) { return; } From 7abe49902bf0bd97d6514f8f801c24bcdd3717d6 Mon Sep 17 00:00:00 2001 From: George Xu Date: Wed, 30 Nov 2022 17:57:38 -0800 Subject: [PATCH 02/18] modify enum --- packages/plugin/webpack/src/WebpackConfig.ts | 145 +++---------------- packages/plugin/webpack/src/WebpackPlugin.ts | 86 ++++++----- 2 files changed, 62 insertions(+), 169 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index f028e91ee6..770bccb5bc 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -21,10 +21,24 @@ export type ConfigurationFactory = ( ) => Configuration | Promise; enum RendererTarget { - Web = 'web', - ElectronRenderer = 'electron-renderer', - ElectronPreload = 'electron-preload', - SandboxedPreload = 'web', + Web, + ElectronRenderer, + ElectronPreload, + SandboxedPreload, +} + +function rendererTargetToWebpackTarget(target: RendererTarget): string { + switch (target) { + case RendererTarget.Web: + case RendererTarget.SandboxedPreload: + return 'web'; + case RendererTarget.ElectronPreload: + return 'electron-preload'; + case RendererTarget.ElectronRenderer: + return 'electron-renderer'; + default: + return ''; + } } export default class WebpackConfigGenerator { @@ -76,10 +90,6 @@ export default class WebpackConfigGenerator { return this.isProd ? 'source-map' : 'eval-source-map'; } - rendererTarget(entryPoint: WebpackPluginEntryPoint): string { - return entryPoint.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration ? RendererTarget.ElectronRenderer : RendererTarget.Web; - } - rendererEntryPoint(entryPoint: WebpackPluginEntryPoint, inRendererDir: boolean, basename: string): string { if (this.isProd) { return `\`file://$\{require('path').resolve(__dirname, '..', '${inRendererDir ? 'renderer' : '.'}', '${entryPoint.name}', '${basename}')}\``; @@ -170,117 +180,6 @@ export default class WebpackConfigGenerator { ); } - async getPreloadConfigForEntryPoint(entryPoint: WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPointPreloadOnly): Promise { - if (!entryPoint.preload) { - return {}; - } - - const rendererConfig = await this.resolveConfig(entryPoint.preload.config || this.pluginConfig.renderer.config); - const prefixedEntries = entryPoint.prefixedEntries || []; - - return webpackMerge( - { - devtool: this.rendererSourceMapOption, - mode: this.mode, - entry: prefixedEntries.concat([entryPoint.preload.js]), - output: { - path: path.resolve(this.webpackDir, 'renderer', entryPoint.name), - filename: 'preload.j s', - }, - node: { - __dirname: false, - __filename: false, - }, - }, - rendererConfig || {}, - { target: 'electron-preload' } - ); - } - - async getRendererConfig2(entryPoints: WebpackPluginEntryPoint[]): Promise { - const rendererConfig = await this.resolveConfig(this.pluginConfig.renderer.config); - - return entryPoints.map((entryPoint) => { - const baseConfig: webpack.Configuration = { - target: this.rendererTarget(entryPoint), - devtool: this.rendererSourceMapOption, - mode: this.mode, - output: { - path: path.resolve(this.webpackDir, 'renderer'), - filename: '[name]/index.js', - globalObject: 'self', - ...(this.isProd ? {} : { publicPath: '/' }), - }, - node: { - __dirname: false, - __filename: false, - }, - plugins: [new AssetRelocatorPatch(this.isProd, !!this.pluginConfig.renderer.nodeIntegration)], - }; - - if (isLocalWindow(entryPoint)) { - return webpackMerge( - baseConfig, - { - entry: { - [entryPoint.name]: (entryPoint.prefixedEntries || []).concat([entryPoint.js]), - }, - output: { - path: path.resolve(this.webpackDir, 'renderer'), - filename: '[name]/index.js', - globalObject: 'self', - ...(this.isProd ? {} : { publicPath: '/' }), - }, - plugins: [ - new HtmlWebpackPlugin({ - title: entryPoint.name, - template: entryPoint.html, - filename: `${entryPoint.name}/index.html`, - chunks: [entryPoint.name].concat(entryPoint.additionalChunks || []), - }) as WebpackPluginInstance, - ], - }, - rendererConfig || {} - ); - } else if (isNoWindow(entryPoint)) { - return webpackMerge( - baseConfig, - { - entry: { - [entryPoint.name]: (entryPoint.prefixedEntries || []).concat([entryPoint.js]), - }, - output: { - path: path.resolve(this.webpackDir, 'renderer'), - filename: '[name]/index.js', - globalObject: 'self', - ...(this.isProd ? {} : { publicPath: '/' }), - }, - }, - rendererConfig || {} - ); - } else if (isPreloadOnly(entryPoint)) { - return webpackMerge( - baseConfig, - { - target: 'electron-preload', - entry: { - [entryPoint.name]: (entryPoint.prefixedEntries || []).concat([entryPoint.preload.js]), - }, - output: { - path: path.resolve(this.webpackDir, 'renderer'), - filename: 'preload.js', - globalObject: 'self', - ...(this.isProd ? {} : { publicPath: '/' }), - }, - }, - rendererConfig || {} - ); - } else { - throw new Error('Invalid renderer entry point detected.'); - } - }); - } - async getRendererConfig(entryPoints: WebpackPluginEntryPoint[]): Promise { const targets = { web: [] as (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPoint)[], @@ -290,7 +189,6 @@ export default class WebpackConfigGenerator { }; for (const entry of entryPoints) { if (entry.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration) { - // Has node if (isPreloadOnly(entry)) { targets.electronPreload.push(entry); } else { @@ -300,7 +198,6 @@ export default class WebpackConfigGenerator { } } } else { - // No node if (isPreloadOnly(entry)) { targets.sandboxedPreload.push(entry); } else { @@ -311,7 +208,7 @@ export default class WebpackConfigGenerator { } } } - console.log('targets', targets); + return [ await this.buildRendererConfig(targets.web, RendererTarget.Web), await this.buildRendererConfig(targets.electronRenderer, RendererTarget.ElectronRenderer), @@ -324,7 +221,7 @@ export default class WebpackConfigGenerator { buildRendererBaseConfig(target: RendererTarget): webpack.Configuration { return { - target, + target: rendererTargetToWebpackTarget(target), devtool: this.rendererSourceMapOption, mode: this.mode, output: { @@ -379,7 +276,7 @@ export default class WebpackConfigGenerator { entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([isPreloadOnly(entryPoint) ? entryPoint.preload.js : entryPoint.js]); } const config: Configuration = { - target, + target: rendererTargetToWebpackTarget(target), entry, output: { path: path.resolve(this.webpackDir, 'renderer'), diff --git a/packages/plugin/webpack/src/WebpackPlugin.ts b/packages/plugin/webpack/src/WebpackPlugin.ts index 9a79fab6a1..660eed05c8 100644 --- a/packages/plugin/webpack/src/WebpackPlugin.ts +++ b/packages/plugin/webpack/src/WebpackPlugin.ts @@ -15,7 +15,6 @@ import { merge } from 'webpack-merge'; import { WebpackPluginConfig } from './Config'; import ElectronForgeLoggingPlugin from './util/ElectronForgeLogging'; import once from './util/once'; -import { isLocalWindow, isPreloadOnly } from './util/rendererTypeUtils'; import WebpackConfigGenerator from './WebpackConfig'; const d = debug('electron-forge:plugin:webpack'); @@ -282,24 +281,21 @@ the generated files). Instead, it is ${JSON.stringify(pj.main)}`); throw new Error(`Compilation errors in the renderer: ${stats.toString()}`); } - for (const entryPoint of this.config.renderer.entryPoints) { - if ((isLocalWindow(entryPoint) && !!entryPoint.preload) || isPreloadOnly(entryPoint)) { - const stats = await this.runWebpack( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - [await this.configGenerator.getPreloadConfigForEntryPoint(entryPoint)] - ); - - if (stats?.hasErrors()) { - throw new Error(`Compilation errors in the preload (${entryPoint.name}): ${stats.toString()}`); - } - } - } + // for (const entryPoint of this.config.renderer.entryPoints) { + // if ((isLocalWindow(entryPoint) && !!entryPoint.preload) || isPreloadOnly(entryPoint)) { + // const stats = await this.runWebpack( + // // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + // [await this.configGenerator.getPreloadConfigForEntryPoint(entryPoint)] + // ); + + // if (stats?.hasErrors()) { + // throw new Error(`Compilation errors in the preload (${entryPoint.name}): ${stats.toString()}`); + // } + // } + // } }; launchRendererDevServers = async (logger: Logger): Promise => { - const tab = logger.createTab('Renderers'); - const pluginLogs = new ElectronForgeLoggingPlugin(tab); - const config = await this.configGenerator.getRendererConfig(this.config.renderer.entryPoints); console.log('renderer config: ', config); if (config.length === 0) { @@ -308,7 +304,7 @@ the generated files). Instead, it is ${JSON.stringify(pj.main)}`); for (const entryConfig of config) { if (!entryConfig.plugins) entryConfig.plugins = []; - entryConfig.plugins.push(pluginLogs); + entryConfig.plugins.push(new ElectronForgeLoggingPlugin(logger.createTab(`Renderer Target Bundle (${entryConfig.target})`))); entryConfig.infrastructureLogging = { level: 'none', @@ -321,34 +317,34 @@ the generated files). Instead, it is ${JSON.stringify(pj.main)}`); await webpackDevServer.start(); this.servers.push(webpackDevServer.server!); - for (const entryPoint of this.config.renderer.entryPoints) { - if ((isLocalWindow(entryPoint) && !!entryPoint.preload) || isPreloadOnly(entryPoint)) { - const config = await this.configGenerator.getPreloadConfigForEntryPoint(entryPoint); - config.infrastructureLogging = { - level: 'none', - }; - config.stats = 'none'; - await new Promise((resolve, reject) => { - const tab = logger.createTab(`${entryPoint.name} - Preload`); - const [onceResolve, onceReject] = once(resolve, reject); - - this.watchers.push( - webpack(config).watch({}, (err, stats) => { - if (stats) { - tab.log( - stats.toString({ - colors: true, - }) - ); - } - - if (err) return onceReject(err); - return onceResolve(undefined); - }) - ); - }); - } - } + // for (const entryPoint of this.config.renderer.entryPoints) { + // if ((isLocalWindow(entryPoint) && !!entryPoint.preload) || isPreloadOnly(entryPoint)) { + // const config = await this.configGenerator.getPreloadConfigForEntryPoint(entryPoint); + // config.infrastructureLogging = { + // level: 'none', + // }; + // config.stats = 'none'; + // await new Promise((resolve, reject) => { + // const tab = logger.createTab(`${entryPoint.name} - Preload`); + // const [onceResolve, onceReject] = once(resolve, reject); + + // this.watchers.push( + // webpack(config).watch({}, (err, stats) => { + // if (stats) { + // tab.log( + // stats.toString({ + // colors: true, + // }) + // ); + // } + + // if (err) return onceReject(err); + // return onceResolve(undefined); + // }) + // ); + // }); + // } + // } }; devServerOptions(): WebpackDevServer.Configuration { From 9830b8646cbfe857d9649ed2b673b6a04ca6e94d Mon Sep 17 00:00:00 2001 From: George Xu Date: Wed, 30 Nov 2022 18:11:29 -0800 Subject: [PATCH 03/18] promise all --- packages/plugin/webpack/src/WebpackConfig.ts | 34 +++++++++++--------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index 770bccb5bc..577cdde483 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -181,7 +181,7 @@ export default class WebpackConfigGenerator { } async getRendererConfig(entryPoints: WebpackPluginEntryPoint[]): Promise { - const targets = { + const entryPointsForTarget = { web: [] as (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPoint)[], electronRenderer: [] as (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPoint)[], electronPreload: [] as (WebpackPluginEntryPointPreloadOnly | WebpackPluginEntryPointLocalWindow)[], @@ -190,33 +190,37 @@ export default class WebpackConfigGenerator { for (const entry of entryPoints) { if (entry.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration) { if (isPreloadOnly(entry)) { - targets.electronPreload.push(entry); + entryPointsForTarget.electronPreload.push(entry); } else { - targets.electronRenderer.push(entry); + entryPointsForTarget.electronRenderer.push(entry); if (isLocalWindow(entry) && entry.preload) { - targets.electronPreload.push(entry); + entryPointsForTarget.electronPreload.push(entry); } } } else { if (isPreloadOnly(entry)) { - targets.sandboxedPreload.push(entry); + entryPointsForTarget.sandboxedPreload.push(entry); } else { - targets.web.push(entry); + entryPointsForTarget.web.push(entry); if (isLocalWindow(entry) && entry.preload) { - targets.sandboxedPreload.push(entry); + entryPointsForTarget.sandboxedPreload.push(entry); } } } } - - return [ - await this.buildRendererConfig(targets.web, RendererTarget.Web), - await this.buildRendererConfig(targets.electronRenderer, RendererTarget.ElectronRenderer), - await this.buildRendererConfig(targets.electronPreload, RendererTarget.ElectronPreload), - await this.buildRendererConfig(targets.sandboxedPreload, RendererTarget.SandboxedPreload), - ].filter(function isNotNull(item: T | null): item is T { - return !!item; + const rendererConfigPromises = [ + this.buildRendererConfig(entryPointsForTarget.web, RendererTarget.Web), + this.buildRendererConfig(entryPointsForTarget.electronRenderer, RendererTarget.ElectronRenderer), + this.buildRendererConfig(entryPointsForTarget.electronPreload, RendererTarget.ElectronPreload), + this.buildRendererConfig(entryPointsForTarget.sandboxedPreload, RendererTarget.SandboxedPreload), + ]; + + const rendererConfig = await Promise.all(rendererConfigPromises).then((res) => { + return res.filter(function isNotNull(item: T | null): item is T { + return !!item; + }); }); + return rendererConfig; } buildRendererBaseConfig(target: RendererTarget): webpack.Configuration { From d5eaaff83ca009b8b086006f2c77165de94f4d20 Mon Sep 17 00:00:00 2001 From: George Xu Date: Wed, 30 Nov 2022 23:50:27 -0800 Subject: [PATCH 04/18] refactor --- packages/plugin/webpack/src/WebpackConfig.ts | 41 +++++++++--------- packages/plugin/webpack/src/WebpackPlugin.ts | 43 ------------------- .../webpack/src/util/rendererTypeUtils.ts | 27 ++++++++++++ 3 files changed, 48 insertions(+), 63 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index 577cdde483..86e096e7a5 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -8,7 +8,7 @@ import { merge as webpackMerge } from 'webpack-merge'; import { WebpackPluginConfig, WebpackPluginEntryPoint, WebpackPluginEntryPointLocalWindow, WebpackPluginEntryPointPreloadOnly } from './Config'; import AssetRelocatorPatch from './util/AssetRelocatorPatch'; import processConfig from './util/processConfig'; -import { isLocalWindow, isNoWindow, isPreloadOnly } from './util/rendererTypeUtils'; +import { isLocalWindow, isLocalWindowEntries, isNoWindow, isNoWindowEntries, isPreloadOnly, isPreloadOnlyEntries } from './util/rendererTypeUtils'; type EntryType = string | string[] | Record; type WebpackMode = 'production' | 'development'; @@ -26,6 +26,9 @@ enum RendererTarget { ElectronPreload, SandboxedPreload, } +function isNotNull(item: T | null): item is T { + return !!item; +} function rendererTargetToWebpackTarget(target: RendererTarget): string { switch (target) { @@ -36,8 +39,6 @@ function rendererTargetToWebpackTarget(target: RendererTarget): string { return 'electron-preload'; case RendererTarget.ElectronRenderer: return 'electron-renderer'; - default: - return ''; } } @@ -184,8 +185,8 @@ export default class WebpackConfigGenerator { const entryPointsForTarget = { web: [] as (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPoint)[], electronRenderer: [] as (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPoint)[], - electronPreload: [] as (WebpackPluginEntryPointPreloadOnly | WebpackPluginEntryPointLocalWindow)[], - sandboxedPreload: [] as (WebpackPluginEntryPointPreloadOnly | WebpackPluginEntryPointLocalWindow)[], + electronPreload: [] as WebpackPluginEntryPointPreloadOnly[], + sandboxedPreload: [] as WebpackPluginEntryPointPreloadOnly[], }; for (const entry of entryPoints) { if (entry.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration) { @@ -208,19 +209,14 @@ export default class WebpackConfigGenerator { } } } - const rendererConfigPromises = [ + const rendererConfig = await Promise.all([ this.buildRendererConfig(entryPointsForTarget.web, RendererTarget.Web), this.buildRendererConfig(entryPointsForTarget.electronRenderer, RendererTarget.ElectronRenderer), this.buildRendererConfig(entryPointsForTarget.electronPreload, RendererTarget.ElectronPreload), this.buildRendererConfig(entryPointsForTarget.sandboxedPreload, RendererTarget.SandboxedPreload), - ]; - - const rendererConfig = await Promise.all(rendererConfigPromises).then((res) => { - return res.filter(function isNotNull(item: T | null): item is T { - return !!item; - }); - }); - return rendererConfig; + ]); + + return rendererConfig.filter(isNotNull); } buildRendererBaseConfig(target: RendererTarget): webpack.Configuration { @@ -238,22 +234,24 @@ export default class WebpackConfigGenerator { __dirname: false, __filename: false, }, - plugins: [new AssetRelocatorPatch(this.isProd, !!this.pluginConfig.renderer.nodeIntegration)], + plugins: [new AssetRelocatorPatch(this.isProd, target === RendererTarget.ElectronRenderer || target === RendererTarget.ElectronPreload)], }; } async buildRendererConfig(entryPoints: WebpackPluginEntryPoint[], target: RendererTarget): Promise { - const entry: webpack.Entry = {}; - if (entryPoints.length === 0) { return null; } + const entry: webpack.Entry = {}; const baseConfig: webpack.Configuration = this.buildRendererBaseConfig(target); const rendererConfig = await this.resolveConfig(this.pluginConfig.renderer.config); if (target === RendererTarget.Web || target === RendererTarget.ElectronRenderer) { + if (!isLocalWindowEntries(entryPoints) && !isNoWindowEntries(entryPoints)) { + throw new Error('Invalid renderer entry point detected.'); + } for (const entryPoint of entryPoints) { - entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([isPreloadOnly(entryPoint) ? entryPoint.preload.js : entryPoint.js]); + entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([entryPoint.js]); } const output = { path: path.resolve(this.webpackDir, 'renderer'), @@ -276,15 +274,18 @@ export default class WebpackConfigGenerator { } return webpackMerge(baseConfig, { entry, output, plugins }, rendererConfig || {}); } else if (target === RendererTarget.ElectronPreload || target === RendererTarget.SandboxedPreload) { + if (!isPreloadOnlyEntries(entryPoints)) { + throw new Error('Invalid renderer entry point detected.'); + } for (const entryPoint of entryPoints) { - entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([isPreloadOnly(entryPoint) ? entryPoint.preload.js : entryPoint.js]); + entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([entryPoint.preload.js]); } const config: Configuration = { target: rendererTargetToWebpackTarget(target), entry, output: { path: path.resolve(this.webpackDir, 'renderer'), - filename: 'preload.js', + filename: '[name]/preload.js', globalObject: 'self', ...(this.isProd ? {} : { publicPath: '/' }), }, diff --git a/packages/plugin/webpack/src/WebpackPlugin.ts b/packages/plugin/webpack/src/WebpackPlugin.ts index 660eed05c8..f07d454442 100644 --- a/packages/plugin/webpack/src/WebpackPlugin.ts +++ b/packages/plugin/webpack/src/WebpackPlugin.ts @@ -280,24 +280,10 @@ the generated files). Instead, it is ${JSON.stringify(pj.main)}`); if (!watch && stats?.hasErrors()) { throw new Error(`Compilation errors in the renderer: ${stats.toString()}`); } - - // for (const entryPoint of this.config.renderer.entryPoints) { - // if ((isLocalWindow(entryPoint) && !!entryPoint.preload) || isPreloadOnly(entryPoint)) { - // const stats = await this.runWebpack( - // // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - // [await this.configGenerator.getPreloadConfigForEntryPoint(entryPoint)] - // ); - - // if (stats?.hasErrors()) { - // throw new Error(`Compilation errors in the preload (${entryPoint.name}): ${stats.toString()}`); - // } - // } - // } }; launchRendererDevServers = async (logger: Logger): Promise => { const config = await this.configGenerator.getRendererConfig(this.config.renderer.entryPoints); - console.log('renderer config: ', config); if (config.length === 0) { return; } @@ -316,35 +302,6 @@ the generated files). Instead, it is ${JSON.stringify(pj.main)}`); const webpackDevServer = new WebpackDevServer(this.devServerOptions(), compiler); await webpackDevServer.start(); this.servers.push(webpackDevServer.server!); - - // for (const entryPoint of this.config.renderer.entryPoints) { - // if ((isLocalWindow(entryPoint) && !!entryPoint.preload) || isPreloadOnly(entryPoint)) { - // const config = await this.configGenerator.getPreloadConfigForEntryPoint(entryPoint); - // config.infrastructureLogging = { - // level: 'none', - // }; - // config.stats = 'none'; - // await new Promise((resolve, reject) => { - // const tab = logger.createTab(`${entryPoint.name} - Preload`); - // const [onceResolve, onceReject] = once(resolve, reject); - - // this.watchers.push( - // webpack(config).watch({}, (err, stats) => { - // if (stats) { - // tab.log( - // stats.toString({ - // colors: true, - // }) - // ); - // } - - // if (err) return onceReject(err); - // return onceResolve(undefined); - // }) - // ); - // }); - // } - // } }; devServerOptions(): WebpackDevServer.Configuration { diff --git a/packages/plugin/webpack/src/util/rendererTypeUtils.ts b/packages/plugin/webpack/src/util/rendererTypeUtils.ts index 2b9d0ff008..4923a90199 100644 --- a/packages/plugin/webpack/src/util/rendererTypeUtils.ts +++ b/packages/plugin/webpack/src/util/rendererTypeUtils.ts @@ -15,3 +15,30 @@ export const isPreloadOnly = (entry: WebpackPluginEntryPoint): entry is WebpackP export const isNoWindow = (entry: WebpackPluginEntryPoint): entry is WebpackPluginEntryPointNoWindow => { return !(entry as any).html && !!(entry as any).js; }; + +export const isLocalWindowEntries = (entries: WebpackPluginEntryPoint[]): entries is WebpackPluginEntryPointLocalWindow[] => { + for (const entry of entries) { + if (!isLocalWindow(entry)) { + return false; + } + } + return true; +}; + +export const isNoWindowEntries = (entries: WebpackPluginEntryPoint[]): entries is WebpackPluginEntryPointNoWindow[] => { + for (const entry of entries) { + if (!isNoWindow(entry)) { + return false; + } + } + return true; +}; + +export const isPreloadOnlyEntries = (entries: WebpackPluginEntryPoint[]): entries is WebpackPluginEntryPointPreloadOnly[] => { + for (const entry of entries) { + if (!isPreloadOnly(entry)) { + return false; + } + } + return true; +}; From ea38eb862cdfd601ccad41b3667e7c19ee939867 Mon Sep 17 00:00:00 2001 From: George Xu Date: Thu, 1 Dec 2022 12:36:56 -0800 Subject: [PATCH 05/18] fix typing --- packages/plugin/webpack/src/WebpackConfig.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index 86e096e7a5..ab314d7233 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -195,7 +195,7 @@ export default class WebpackConfigGenerator { } else { entryPointsForTarget.electronRenderer.push(entry); if (isLocalWindow(entry) && entry.preload) { - entryPointsForTarget.electronPreload.push(entry); + entryPointsForTarget.electronPreload.push({ ...entry, preload: entry.preload }); } } } else { @@ -204,7 +204,7 @@ export default class WebpackConfigGenerator { } else { entryPointsForTarget.web.push(entry); if (isLocalWindow(entry) && entry.preload) { - entryPointsForTarget.sandboxedPreload.push(entry); + entryPointsForTarget.sandboxedPreload.push({ ...entry, preload: entry.preload }); } } } From f84016c0c6f5d82248af497dbcf49979a3263816 Mon Sep 17 00:00:00 2001 From: George Xu Date: Thu, 1 Dec 2022 16:29:13 -0800 Subject: [PATCH 06/18] remove some tests + more --- packages/plugin/webpack/package.json | 2 +- packages/plugin/webpack/src/WebpackConfig.ts | 29 ++-- .../webpack/src/util/rendererTypeUtils.ts | 6 +- .../webpack/test/AssetRelocatorPatch_spec.ts | 9 +- .../plugin/webpack/test/WebpackConfig_spec.ts | 158 +----------------- 5 files changed, 24 insertions(+), 180 deletions(-) diff --git a/packages/plugin/webpack/package.json b/packages/plugin/webpack/package.json index 2f524e16b9..679b2540f6 100644 --- a/packages/plugin/webpack/package.json +++ b/packages/plugin/webpack/package.json @@ -8,7 +8,7 @@ "main": "dist/WebpackPlugin.js", "typings": "dist/WebpackPlugin.d.ts", "scripts": { - "test": "xvfb-maybe mocha --config ../../../.mocharc.js test/**/*_spec.ts" + "test": "xvfb-maybe mocha --config ../../../.mocharc.js test/**/*_spec.ts test/*_spec.ts" }, "devDependencies": { "@malept/cross-spawn-promise": "^2.0.0", diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index ab314d7233..4d4b7f0476 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -188,24 +188,17 @@ export default class WebpackConfigGenerator { electronPreload: [] as WebpackPluginEntryPointPreloadOnly[], sandboxedPreload: [] as WebpackPluginEntryPointPreloadOnly[], }; + for (const entry of entryPoints) { - if (entry.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration) { - if (isPreloadOnly(entry)) { - entryPointsForTarget.electronPreload.push(entry); - } else { - entryPointsForTarget.electronRenderer.push(entry); - if (isLocalWindow(entry) && entry.preload) { - entryPointsForTarget.electronPreload.push({ ...entry, preload: entry.preload }); - } - } + const target = entry.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration ? 'electronRenderer' : 'web'; + const preloadTarget = entry.nodeIntegration ?? this.pluginConfig.renderer.nodeIntegration ? 'electronPreload' : 'sandboxedPreload'; + + if (isPreloadOnly(entry)) { + entryPointsForTarget[preloadTarget].push(entry); } else { - if (isPreloadOnly(entry)) { - entryPointsForTarget.sandboxedPreload.push(entry); - } else { - entryPointsForTarget.web.push(entry); - if (isLocalWindow(entry) && entry.preload) { - entryPointsForTarget.sandboxedPreload.push({ ...entry, preload: entry.preload }); - } + entryPointsForTarget[target].push(entry); + if (isLocalWindow(entry) && entry.preload) { + entryPointsForTarget[preloadTarget].push({ ...entry, preload: entry.preload }); } } } @@ -285,7 +278,7 @@ export default class WebpackConfigGenerator { entry, output: { path: path.resolve(this.webpackDir, 'renderer'), - filename: '[name]/preload.js', + filename: 'preload.js', globalObject: 'self', ...(this.isProd ? {} : { publicPath: '/' }), }, @@ -294,7 +287,7 @@ export default class WebpackConfigGenerator { ? [] : [new webpack.ExternalsPlugin('commonjs2', ['electron', 'electron/renderer', 'electron/common', 'events', 'timers', 'url'])], }; - return webpackMerge(baseConfig, config, rendererConfig); + return webpackMerge(baseConfig, config, rendererConfig || {}); } else { throw new Error('Invalid renderer entry point detected.'); } diff --git a/packages/plugin/webpack/src/util/rendererTypeUtils.ts b/packages/plugin/webpack/src/util/rendererTypeUtils.ts index 4923a90199..1162e2974f 100644 --- a/packages/plugin/webpack/src/util/rendererTypeUtils.ts +++ b/packages/plugin/webpack/src/util/rendererTypeUtils.ts @@ -16,6 +16,10 @@ export const isNoWindow = (entry: WebpackPluginEntryPoint): entry is WebpackPlug return !(entry as any).html && !!(entry as any).js; }; +export const hasPreloadScript = (entry: WebpackPluginEntryPoint): entry is WebpackPluginEntryPointPreloadOnly => { + return !!(entry as any).preload; +}; + export const isLocalWindowEntries = (entries: WebpackPluginEntryPoint[]): entries is WebpackPluginEntryPointLocalWindow[] => { for (const entry of entries) { if (!isLocalWindow(entry)) { @@ -36,7 +40,7 @@ export const isNoWindowEntries = (entries: WebpackPluginEntryPoint[]): entries i export const isPreloadOnlyEntries = (entries: WebpackPluginEntryPoint[]): entries is WebpackPluginEntryPointPreloadOnly[] => { for (const entry of entries) { - if (!isPreloadOnly(entry)) { + if (!hasPreloadScript(entry)) { return false; } } diff --git a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts index 7b70a5cf9e..5946dd2c7c 100644 --- a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts +++ b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts @@ -145,9 +145,8 @@ describe('AssetRelocatorPatch', () => { }); it('builds preload', async () => { - const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; - const preloadConfig = await generator.getPreloadConfigForEntryPoint(entryPoint); - await asyncWebpack(preloadConfig); + const preloadConfig = await generator.getRendererConfig(config.renderer.entryPoints); + await asyncWebpack(preloadConfig[0]); await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: path.join(rendererOut, 'main_window'), @@ -199,8 +198,8 @@ describe('AssetRelocatorPatch', () => { it('builds preload', async () => { const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; - const preloadConfig = await generator.getPreloadConfigForEntryPoint(entryPoint); - await asyncWebpack(preloadConfig); + const preloadConfig = await generator.getRendererConfig([entryPoint]); + await asyncWebpack(preloadConfig[0]); await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: path.join(rendererOut, 'main_window'), diff --git a/packages/plugin/webpack/test/WebpackConfig_spec.ts b/packages/plugin/webpack/test/WebpackConfig_spec.ts index 86766e9892..590f67af01 100644 --- a/packages/plugin/webpack/test/WebpackConfig_spec.ts +++ b/packages/plugin/webpack/test/WebpackConfig_spec.ts @@ -3,7 +3,7 @@ import path from 'path'; import { expect } from 'chai'; import { Compiler, Configuration, Entry, WebpackPluginInstance } from 'webpack'; -import { WebpackConfiguration, WebpackPluginConfig, WebpackPluginEntryPoint, WebpackPluginEntryPointLocalWindow } from '../src/Config'; +import { WebpackConfiguration, WebpackPluginConfig, WebpackPluginEntryPoint } from '../src/Config'; import AssetRelocatorPatch from '../src/util/AssetRelocatorPatch'; import WebpackConfigGenerator, { ConfigurationFactory } from '../src/WebpackConfig'; @@ -27,51 +27,6 @@ const sampleWebpackConfig = { }; describe('WebpackConfigGenerator', () => { - describe('rendererTarget', () => { - it('is web if undefined', () => { - const config = { - renderer: { - entryPoints: [{ name: 'foo', js: 'foo/index.js' }], - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, '/', false, 3000); - expect(generator.rendererTarget(config.renderer.entryPoints[0])).to.equal('web'); - }); - - it('is web if false', () => { - const config = { - renderer: { - entryPoints: [{ name: 'foo', js: 'foo/index.js' }], - nodeIntegration: false, - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, '/', false, 3000); - expect(generator.rendererTarget(config.renderer.entryPoints[0])).to.equal('web'); - }); - - it('is electron-renderer if true', () => { - const config = { - renderer: { - entryPoints: [{ name: 'foo', js: 'foo/index.js' }], - nodeIntegration: true, - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, '/', false, 3000); - expect(generator.rendererTarget(config.renderer.entryPoints[0])).to.equal('electron-renderer'); - }); - - it('is web if entry nodeIntegration is false', () => { - const config = { - renderer: { - entryPoints: [{ name: 'foo', js: 'foo/index.js', nodeIntegration: false }], - nodeIntegration: true, - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, '/', false, 3000); - expect(generator.rendererTarget(config.renderer.entryPoints[0])).to.equal('web'); - }); - }); - describe('getDefines', () => { it('throws an error if renderer.entryPoints does not exist', () => { const config = { @@ -308,113 +263,6 @@ describe('WebpackConfigGenerator', () => { }); }); - describe('getPreloadConfigForEntryPoint', () => { - it('generates a development config', async () => { - const config = { - renderer: { - entryPoints: [ - { - name: 'main', - preload: { - js: 'preloadScript.js', - }, - }, - ], - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, mockProjectDir, false, 3000); - const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; - const webpackConfig = await generator.getPreloadConfigForEntryPoint(entryPoint); - expect(webpackConfig.target).to.equal('electron-preload'); - expect(webpackConfig.mode).to.equal('development'); - expect(webpackConfig.entry).to.deep.equal(['preloadScript.js']); - expect(webpackConfig.output).to.deep.equal({ - path: path.join(mockProjectDir, '.webpack', 'renderer', 'main'), - filename: 'preload.js', - }); - expect(hasAssetRelocatorPatchPlugin(webpackConfig.plugins)).to.equal(false); - }); - - it('generates a production config', async () => { - const config = { - renderer: { - entryPoints: [ - { - name: 'main', - preload: { - js: 'preload.js', - }, - }, - ], - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); - const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; - const webpackConfig = await generator.getPreloadConfigForEntryPoint(entryPoint); - expect(webpackConfig.target).to.equal('electron-preload'); - expect(webpackConfig.mode).to.equal('production'); - expect(webpackConfig.entry).to.deep.equal(['preload.js']); - expect(webpackConfig.output).to.deep.equal({ - path: path.join(mockProjectDir, '.webpack', 'renderer', 'main'), - filename: 'preload.js', - }); - expect(hasAssetRelocatorPatchPlugin(webpackConfig.plugins)).to.equal(false); - }); - it('prevents the preload target from being overridden', async () => { - const config = { - renderer: { - config: { - target: 'web', - }, - entryPoints: [ - { - name: 'main', - preload: { - js: 'preload.js', - }, - }, - ], - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); - const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; - const webpackConfig = await generator.getPreloadConfigForEntryPoint(entryPoint); - expect(webpackConfig.target).to.equal('electron-preload'); - }); - - it('allows you to specify a preload webpack config', async () => { - const config = { - renderer: { - config: { - name: 'renderer', - target: 'web', - entry: 'renderer', - }, - entryPoints: [ - { - name: 'main', - preload: { - js: 'preload.js', - config: { - name: 'preload', - target: 'electron-preload', - entry: 'preload', - }, - }, - }, - ], - }, - } as WebpackPluginConfig; - const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); - const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; - const preloadWebpackConfig = await generator.getPreloadConfigForEntryPoint(entryPoint); - const rendererWebpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); - // Our preload config plugins is an empty list while our renderer config plugins has a member - expect(preloadWebpackConfig.name).to.equal('preload'); - expect(rendererWebpackConfig[0].name).to.equal('renderer'); - }); - }); - describe('getRendererConfig', () => { it('generates a development config', async () => { const config = { @@ -483,7 +331,7 @@ describe('WebpackConfigGenerator', () => { } as WebpackPluginConfig; const generator = new WebpackConfigGenerator(config, mockProjectDir, false, 3000); const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); - expect(webpackConfig[0].target).to.equal('electron-preload'); + expect(webpackConfig[0].target).to.equal('web'); expect(webpackConfig[0].entry).to.deep.equal({ main: ['rendererScript.js'], }); @@ -535,7 +383,7 @@ describe('WebpackConfigGenerator', () => { } as WebpackPluginConfig; const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); - expect(webpackConfig[0].target).to.deep.equal('electron-preload'); + expect(webpackConfig[0].target).to.deep.equal('web'); expect(webpackConfig[0].mode).to.equal('production'); expect(webpackConfig[0].entry).to.deep.equal({ main: ['rendererScript.js'], From 4de6f9a40b0332a869e54d1dc3cf415acf1ad9ca Mon Sep 17 00:00:00 2001 From: George Xu Date: Thu, 1 Dec 2022 16:59:04 -0800 Subject: [PATCH 07/18] fix bug --- packages/plugin/webpack/src/WebpackConfig.ts | 4 ++-- .../plugin/webpack/src/util/rendererTypeUtils.ts | 15 ++++----------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index 4d4b7f0476..ae174f4f93 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -8,7 +8,7 @@ import { merge as webpackMerge } from 'webpack-merge'; import { WebpackPluginConfig, WebpackPluginEntryPoint, WebpackPluginEntryPointLocalWindow, WebpackPluginEntryPointPreloadOnly } from './Config'; import AssetRelocatorPatch from './util/AssetRelocatorPatch'; import processConfig from './util/processConfig'; -import { isLocalWindow, isLocalWindowEntries, isNoWindow, isNoWindowEntries, isPreloadOnly, isPreloadOnlyEntries } from './util/rendererTypeUtils'; +import { isLocalOrNoWindowEntries, isLocalWindow, isNoWindow, isPreloadOnly, isPreloadOnlyEntries } from './util/rendererTypeUtils'; type EntryType = string | string[] | Record; type WebpackMode = 'production' | 'development'; @@ -240,7 +240,7 @@ export default class WebpackConfigGenerator { const rendererConfig = await this.resolveConfig(this.pluginConfig.renderer.config); if (target === RendererTarget.Web || target === RendererTarget.ElectronRenderer) { - if (!isLocalWindowEntries(entryPoints) && !isNoWindowEntries(entryPoints)) { + if (!isLocalOrNoWindowEntries(entryPoints)) { throw new Error('Invalid renderer entry point detected.'); } for (const entryPoint of entryPoints) { diff --git a/packages/plugin/webpack/src/util/rendererTypeUtils.ts b/packages/plugin/webpack/src/util/rendererTypeUtils.ts index 1162e2974f..88928ca0cb 100644 --- a/packages/plugin/webpack/src/util/rendererTypeUtils.ts +++ b/packages/plugin/webpack/src/util/rendererTypeUtils.ts @@ -20,18 +20,11 @@ export const hasPreloadScript = (entry: WebpackPluginEntryPoint): entry is Webpa return !!(entry as any).preload; }; -export const isLocalWindowEntries = (entries: WebpackPluginEntryPoint[]): entries is WebpackPluginEntryPointLocalWindow[] => { +export const isLocalOrNoWindowEntries = ( + entries: WebpackPluginEntryPoint[] +): entries is (WebpackPluginEntryPointLocalWindow | WebpackPluginEntryPointNoWindow)[] => { for (const entry of entries) { - if (!isLocalWindow(entry)) { - return false; - } - } - return true; -}; - -export const isNoWindowEntries = (entries: WebpackPluginEntryPoint[]): entries is WebpackPluginEntryPointNoWindow[] => { - for (const entry of entries) { - if (!isNoWindow(entry)) { + if (!isLocalWindow(entry) && !isNoWindow(entry)) { return false; } } From 3499dad0791d83fabc4cae44421a2dc0b17c0182 Mon Sep 17 00:00:00 2001 From: George Xu Date: Thu, 1 Dec 2022 18:02:15 -0800 Subject: [PATCH 08/18] add [name]/preload.js --- packages/plugin/webpack/src/WebpackConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index ae174f4f93..7456435bb2 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -278,7 +278,7 @@ export default class WebpackConfigGenerator { entry, output: { path: path.resolve(this.webpackDir, 'renderer'), - filename: 'preload.js', + filename: '[name]/preload.js', globalObject: 'self', ...(this.isProd ? {} : { publicPath: '/' }), }, From ddeea5b19826a2b59e5867c1aec9ee145be7aa0e Mon Sep 17 00:00:00 2001 From: George Xu Date: Mon, 5 Dec 2022 10:18:38 -0800 Subject: [PATCH 09/18] fix some test --- packages/plugin/webpack/test/WebpackConfig_spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/plugin/webpack/test/WebpackConfig_spec.ts b/packages/plugin/webpack/test/WebpackConfig_spec.ts index 590f67af01..595df537df 100644 --- a/packages/plugin/webpack/test/WebpackConfig_spec.ts +++ b/packages/plugin/webpack/test/WebpackConfig_spec.ts @@ -336,7 +336,7 @@ describe('WebpackConfigGenerator', () => { main: ['rendererScript.js'], }); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - expect(webpackConfig[0].plugins!.length).to.equal(1); + expect(webpackConfig[0].plugins!.length).to.equal(2); expect(hasAssetRelocatorPatchPlugin(webpackConfig[0].plugins)).to.equal(true); }); @@ -390,11 +390,11 @@ describe('WebpackConfigGenerator', () => { }); expect(webpackConfig[0].output).to.deep.equal({ path: path.join(mockProjectDir, '.webpack', 'renderer'), - filename: 'preload.js', + filename: '[name]/preload.js', globalObject: 'self', }); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - expect(webpackConfig[0].plugins!.length).to.equal(1); + expect(webpackConfig[0].plugins!.length).to.equal(2); expect(hasAssetRelocatorPatchPlugin(webpackConfig[0].plugins)).to.equal(true); }); From 2af3ea2d5401cd461b89257db92dc96ac6e909f7 Mon Sep 17 00:00:00 2001 From: George Xu Date: Mon, 5 Dec 2022 16:11:11 -0800 Subject: [PATCH 10/18] alter preload tests --- packages/plugin/webpack/src/WebpackConfig.ts | 4 ++-- packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index 7456435bb2..130484ec0b 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -265,7 +265,7 @@ export default class WebpackConfigGenerator { ); } } - return webpackMerge(baseConfig, { entry, output, plugins }, rendererConfig || {}); + return webpackMerge(baseConfig, rendererConfig || {}, { entry, output, plugins }); } else if (target === RendererTarget.ElectronPreload || target === RendererTarget.SandboxedPreload) { if (!isPreloadOnlyEntries(entryPoints)) { throw new Error('Invalid renderer entry point detected.'); @@ -287,7 +287,7 @@ export default class WebpackConfigGenerator { ? [] : [new webpack.ExternalsPlugin('commonjs2', ['electron', 'electron/renderer', 'electron/common', 'events', 'timers', 'url'])], }; - return webpackMerge(baseConfig, config, rendererConfig || {}); + return webpackMerge(baseConfig, rendererConfig || {}, config); } else { throw new Error('Invalid renderer entry point detected.'); } diff --git a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts index 5946dd2c7c..9ab6695bc6 100644 --- a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts +++ b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts @@ -146,7 +146,7 @@ describe('AssetRelocatorPatch', () => { it('builds preload', async () => { const preloadConfig = await generator.getRendererConfig(config.renderer.entryPoints); - await asyncWebpack(preloadConfig[0]); + await asyncWebpack(preloadConfig[1]); await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: path.join(rendererOut, 'main_window'), @@ -199,12 +199,12 @@ describe('AssetRelocatorPatch', () => { it('builds preload', async () => { const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; const preloadConfig = await generator.getRendererConfig([entryPoint]); - await asyncWebpack(preloadConfig[0]); + await asyncWebpack(preloadConfig[1]); await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: path.join(rendererOut, 'main_window'), jsPath: path.join(rendererOut, 'main_window/preload.js'), - nativeModulesString: '.ab=__dirname+"/native_modules/"', + nativeModulesString: 't.ab=require("path").resolve(require("path").dirname(__filename),"..")+"/native_modules/"', nativePathString: `.ab+"${nativePathSuffix}"`, }); }); From 8b1fe062ec7bc63f30c56fcb7b7a05c75c952adb Mon Sep 17 00:00:00 2001 From: George Xu Date: Thu, 22 Dec 2022 15:57:24 -0800 Subject: [PATCH 11/18] packages now use asset relocator patch --- packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts index 9ab6695bc6..dfd14e1377 100644 --- a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts +++ b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts @@ -151,7 +151,7 @@ describe('AssetRelocatorPatch', () => { await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: path.join(rendererOut, 'main_window'), jsPath: path.join(rendererOut, 'main_window/preload.js'), - nativeModulesString: '__webpack_require__.ab = __dirname + "/native_modules/"', + nativeModulesString: `__webpack_require__.ab = ${JSON.stringify(rendererOut)} + "/native_modules/"`, nativePathString: `require(__webpack_require__.ab + \\"${nativePathSuffix}\\")`, }); }); @@ -204,7 +204,7 @@ describe('AssetRelocatorPatch', () => { await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: path.join(rendererOut, 'main_window'), jsPath: path.join(rendererOut, 'main_window/preload.js'), - nativeModulesString: 't.ab=require("path").resolve(require("path").dirname(__filename),"..")+"/native_modules/"', + nativeModulesString: '.ab=require("path").resolve(require("path").dirname(__filename),"..")+"/native_modules/"', nativePathString: `.ab+"${nativePathSuffix}"`, }); }); From d7a14fd0ceee93a03a8bb2328b0830386467213f Mon Sep 17 00:00:00 2001 From: George Xu Date: Mon, 30 Jan 2023 16:08:13 -0800 Subject: [PATCH 12/18] fix test --- packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts index dfd14e1377..79101fcb7b 100644 --- a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts +++ b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts @@ -149,7 +149,7 @@ describe('AssetRelocatorPatch', () => { await asyncWebpack(preloadConfig[1]); await expectOutputFileToHaveTheCorrectNativeModulePath({ - outDir: path.join(rendererOut, 'main_window'), + outDir: rendererOut, jsPath: path.join(rendererOut, 'main_window/preload.js'), nativeModulesString: `__webpack_require__.ab = ${JSON.stringify(rendererOut)} + "/native_modules/"`, nativePathString: `require(__webpack_require__.ab + \\"${nativePathSuffix}\\")`, @@ -202,7 +202,7 @@ describe('AssetRelocatorPatch', () => { await asyncWebpack(preloadConfig[1]); await expectOutputFileToHaveTheCorrectNativeModulePath({ - outDir: path.join(rendererOut, 'main_window'), + outDir: rendererOut, jsPath: path.join(rendererOut, 'main_window/preload.js'), nativeModulesString: '.ab=require("path").resolve(require("path").dirname(__filename),"..")+"/native_modules/"', nativePathString: `.ab+"${nativePathSuffix}"`, From 53070890ae0d9614ba1d82c964db8dc7732accde Mon Sep 17 00:00:00 2001 From: George Xu Date: Wed, 1 Feb 2023 16:46:48 -0800 Subject: [PATCH 13/18] add additional config per entrypoint config --- packages/plugin/webpack/src/WebpackConfig.ts | 140 +++++++++++------- .../plugin/webpack/test/WebpackConfig_spec.ts | 27 ++++ 2 files changed, 115 insertions(+), 52 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index 130484ec0b..9557d9a90c 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -202,14 +202,17 @@ export default class WebpackConfigGenerator { } } } - const rendererConfig = await Promise.all([ - this.buildRendererConfig(entryPointsForTarget.web, RendererTarget.Web), - this.buildRendererConfig(entryPointsForTarget.electronRenderer, RendererTarget.ElectronRenderer), - this.buildRendererConfig(entryPointsForTarget.electronPreload, RendererTarget.ElectronPreload), - this.buildRendererConfig(entryPointsForTarget.sandboxedPreload, RendererTarget.SandboxedPreload), - ]); - - return rendererConfig.filter(isNotNull); + const rendererConfigs = await Promise.all( + ( + await this.buildRendererConfigs(entryPointsForTarget.web, RendererTarget.Web) + ).concat( + await this.buildRendererConfigs(entryPointsForTarget.electronRenderer, RendererTarget.ElectronRenderer), + await this.buildRendererConfigs(entryPointsForTarget.electronPreload, RendererTarget.ElectronPreload), + await this.buildRendererConfigs(entryPointsForTarget.sandboxedPreload, RendererTarget.SandboxedPreload) + ) + ); + + return rendererConfigs.filter(isNotNull); } buildRendererBaseConfig(target: RendererTarget): webpack.Configuration { @@ -231,63 +234,96 @@ export default class WebpackConfigGenerator { }; } - async buildRendererConfig(entryPoints: WebpackPluginEntryPoint[], target: RendererTarget): Promise { - if (entryPoints.length === 0) { - return null; + async buildRendererConfigForWebOrRendererTarget( + entryPoints: WebpackPluginEntryPoint[], + target: RendererTarget.Web | RendererTarget.ElectronRenderer + ): Promise { + if (!isLocalOrNoWindowEntries(entryPoints)) { + throw new Error('Invalid renderer entry point detected.'); } + const entry: webpack.Entry = {}; const baseConfig: webpack.Configuration = this.buildRendererBaseConfig(target); const rendererConfig = await this.resolveConfig(this.pluginConfig.renderer.config); - if (target === RendererTarget.Web || target === RendererTarget.ElectronRenderer) { - if (!isLocalOrNoWindowEntries(entryPoints)) { - throw new Error('Invalid renderer entry point detected.'); - } - for (const entryPoint of entryPoints) { - entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([entryPoint.js]); + const output = { + path: path.resolve(this.webpackDir, 'renderer'), + filename: '[name]/index.js', + globalObject: 'self', + ...(this.isProd ? {} : { publicPath: '/' }), + }; + const plugins: webpack.WebpackPluginInstance[] = []; + + for (const entryPoint of entryPoints) { + entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([entryPoint.js]); + + if (isLocalWindow(entryPoint)) { + plugins.push( + new HtmlWebpackPlugin({ + title: entryPoint.name, + template: entryPoint.html, + filename: `${entryPoint.name}/index.html`, + chunks: [entryPoint.name].concat(entryPoint.additionalChunks || []), + }) as WebpackPluginInstance + ); } - const output = { + } + return webpackMerge(baseConfig, rendererConfig || {}, { entry, output, plugins }); + } + + async buildRendererConfigForPreloadOrSandboxedPreloadTarget( + entryPoints: WebpackPluginEntryPointPreloadOnly[], + target: RendererTarget.ElectronPreload | RendererTarget.SandboxedPreload + ): Promise { + if (entryPoints.length === 0) { + return null; + } + const entry: webpack.Entry = {}; + const baseConfig: webpack.Configuration = this.buildRendererBaseConfig(target); + const rendererConfig = await this.resolveConfig(entryPoints[0].preload?.config || this.pluginConfig.renderer.config); + + for (const entryPoint of entryPoints) { + entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([entryPoint.preload.js]); + } + const config: Configuration = { + target: rendererTargetToWebpackTarget(target), + entry, + output: { path: path.resolve(this.webpackDir, 'renderer'), - filename: '[name]/index.js', + filename: '[name]/preload.js', globalObject: 'self', ...(this.isProd ? {} : { publicPath: '/' }), - }; - const plugins: webpack.WebpackPluginInstance[] = []; - for (const entryPoint of entryPoints) { - if (isLocalWindow(entryPoint)) { - plugins.push( - new HtmlWebpackPlugin({ - title: entryPoint.name, - template: entryPoint.html, - filename: `${entryPoint.name}/index.html`, - chunks: [entryPoint.name].concat(entryPoint.additionalChunks || []), - }) as WebpackPluginInstance - ); - } - } - return webpackMerge(baseConfig, rendererConfig || {}, { entry, output, plugins }); + }, + plugins: + target === RendererTarget.ElectronPreload + ? [] + : [new webpack.ExternalsPlugin('commonjs2', ['electron', 'electron/renderer', 'electron/common', 'events', 'timers', 'url'])], + }; + return webpackMerge(baseConfig, rendererConfig || {}, config); + } + + async buildRendererConfigs(entryPoints: WebpackPluginEntryPoint[], target: RendererTarget): Promise[]> { + if (entryPoints.length === 0) { + return []; + } + const rendererConfigs = []; + if (target === RendererTarget.Web || target === RendererTarget.ElectronRenderer) { + rendererConfigs.push(this.buildRendererConfigForWebOrRendererTarget(entryPoints, target)); + return rendererConfigs; } else if (target === RendererTarget.ElectronPreload || target === RendererTarget.SandboxedPreload) { if (!isPreloadOnlyEntries(entryPoints)) { throw new Error('Invalid renderer entry point detected.'); } - for (const entryPoint of entryPoints) { - entry[entryPoint.name] = (entryPoint.prefixedEntries || []).concat([entryPoint.preload.js]); - } - const config: Configuration = { - target: rendererTargetToWebpackTarget(target), - entry, - output: { - path: path.resolve(this.webpackDir, 'renderer'), - filename: '[name]/preload.js', - globalObject: 'self', - ...(this.isProd ? {} : { publicPath: '/' }), - }, - plugins: - target === RendererTarget.ElectronPreload - ? [] - : [new webpack.ExternalsPlugin('commonjs2', ['electron', 'electron/renderer', 'electron/common', 'events', 'timers', 'url'])], - }; - return webpackMerge(baseConfig, rendererConfig || {}, config); + + const entryPointsWithPreloadConfig: WebpackPluginEntryPointPreloadOnly[] = [], + entryPointsWithoutPreloadConfig: WebpackPluginEntryPointPreloadOnly[] = []; + entryPoints.forEach((entryPoint) => (entryPoint.preload.config ? entryPointsWithPreloadConfig : entryPointsWithoutPreloadConfig).push(entryPoint)); + + rendererConfigs.push(this.buildRendererConfigForPreloadOrSandboxedPreloadTarget(entryPointsWithoutPreloadConfig, target)); + entryPointsWithPreloadConfig.forEach((entryPoint) => { + rendererConfigs.push(this.buildRendererConfigForPreloadOrSandboxedPreloadTarget([entryPoint], target)); + }); + return rendererConfigs; } else { throw new Error('Invalid renderer entry point detected.'); } diff --git a/packages/plugin/webpack/test/WebpackConfig_spec.ts b/packages/plugin/webpack/test/WebpackConfig_spec.ts index 595df537df..2426d00eaf 100644 --- a/packages/plugin/webpack/test/WebpackConfig_spec.ts +++ b/packages/plugin/webpack/test/WebpackConfig_spec.ts @@ -417,6 +417,33 @@ describe('WebpackConfigGenerator', () => { expect(webpackConfig[0].target).to.equal('web'); }); + it('allows you to specify a preload webpack config', async () => { + const config = { + renderer: { + config: { + target: 'web', + }, + entryPoints: [ + { + name: 'main', + preload: { + js: 'preload.js', + config: { + name: 'preload', + target: 'electron-preload', + entry: 'preload', + }, + }, + }, + ], + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig[0].target).to.equal('web'); + expect(webpackConfig[0].name).to.equal('preload'); + }); + it('generates a config from function', async () => { const generateWebpackConfig = (webpackConfig: WebpackConfiguration) => { const config = { From e9a50235bfc42a8113d8a015a98c993a38e66c70 Mon Sep 17 00:00:00 2001 From: George Xu Date: Wed, 15 Feb 2023 16:08:18 -0800 Subject: [PATCH 14/18] apply fixes --- packages/plugin/webpack/src/WebpackConfig.ts | 35 +++++++++++-------- .../webpack/src/util/rendererTypeUtils.ts | 2 +- .../webpack/test/AssetRelocatorPatch_spec.ts | 4 +-- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index 9557d9a90c..ee409ce74e 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -26,19 +26,26 @@ enum RendererTarget { ElectronPreload, SandboxedPreload, } + +enum WebpackTarget { + Web = 'web', + ElectronPreload = 'electron-preload', + ElectronRenderer = 'electron-renderer', +} + function isNotNull(item: T | null): item is T { - return !!item; + return item !== null; } -function rendererTargetToWebpackTarget(target: RendererTarget): string { +function rendererTargetToWebpackTarget(target: RendererTarget): WebpackTarget { switch (target) { case RendererTarget.Web: case RendererTarget.SandboxedPreload: - return 'web'; + return WebpackTarget.Web; case RendererTarget.ElectronPreload: - return 'electron-preload'; + return WebpackTarget.ElectronPreload; case RendererTarget.ElectronRenderer: - return 'electron-renderer'; + return WebpackTarget.ElectronRenderer; } } @@ -202,14 +209,14 @@ export default class WebpackConfigGenerator { } } } + const rendererConfigs = await Promise.all( - ( - await this.buildRendererConfigs(entryPointsForTarget.web, RendererTarget.Web) - ).concat( + [ + await this.buildRendererConfigs(entryPointsForTarget.web, RendererTarget.Web), await this.buildRendererConfigs(entryPointsForTarget.electronRenderer, RendererTarget.ElectronRenderer), await this.buildRendererConfigs(entryPointsForTarget.electronPreload, RendererTarget.ElectronPreload), - await this.buildRendererConfigs(entryPointsForTarget.sandboxedPreload, RendererTarget.SandboxedPreload) - ) + await this.buildRendererConfigs(entryPointsForTarget.sandboxedPreload, RendererTarget.SandboxedPreload), + ].reduce((configs, allConfigs) => allConfigs.concat(configs)) ); return rendererConfigs.filter(isNotNull); @@ -278,6 +285,9 @@ export default class WebpackConfigGenerator { if (entryPoints.length === 0) { return null; } + + const externals = ['electron', 'electron/renderer', 'electron/common', 'events', 'timers', 'url']; + const entry: webpack.Entry = {}; const baseConfig: webpack.Configuration = this.buildRendererBaseConfig(target); const rendererConfig = await this.resolveConfig(entryPoints[0].preload?.config || this.pluginConfig.renderer.config); @@ -294,10 +304,7 @@ export default class WebpackConfigGenerator { globalObject: 'self', ...(this.isProd ? {} : { publicPath: '/' }), }, - plugins: - target === RendererTarget.ElectronPreload - ? [] - : [new webpack.ExternalsPlugin('commonjs2', ['electron', 'electron/renderer', 'electron/common', 'events', 'timers', 'url'])], + plugins: target === RendererTarget.ElectronPreload ? [] : [new webpack.ExternalsPlugin('commonjs2', externals)], }; return webpackMerge(baseConfig, rendererConfig || {}, config); } diff --git a/packages/plugin/webpack/src/util/rendererTypeUtils.ts b/packages/plugin/webpack/src/util/rendererTypeUtils.ts index 88928ca0cb..66b6f8bfc8 100644 --- a/packages/plugin/webpack/src/util/rendererTypeUtils.ts +++ b/packages/plugin/webpack/src/util/rendererTypeUtils.ts @@ -17,7 +17,7 @@ export const isNoWindow = (entry: WebpackPluginEntryPoint): entry is WebpackPlug }; export const hasPreloadScript = (entry: WebpackPluginEntryPoint): entry is WebpackPluginEntryPointPreloadOnly => { - return !!(entry as any).preload; + return 'preload' in entry; }; export const isLocalOrNoWindowEntries = ( diff --git a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts index 79101fcb7b..55802a85f3 100644 --- a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts +++ b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts @@ -146,7 +146,7 @@ describe('AssetRelocatorPatch', () => { it('builds preload', async () => { const preloadConfig = await generator.getRendererConfig(config.renderer.entryPoints); - await asyncWebpack(preloadConfig[1]); + await asyncWebpack(preloadConfig[0]); await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: rendererOut, @@ -199,7 +199,7 @@ describe('AssetRelocatorPatch', () => { it('builds preload', async () => { const entryPoint = config.renderer.entryPoints[0] as WebpackPluginEntryPointLocalWindow; const preloadConfig = await generator.getRendererConfig([entryPoint]); - await asyncWebpack(preloadConfig[1]); + await asyncWebpack(preloadConfig[0]); await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: rendererOut, From 77a7cf27a3fc9fe4e37f748dcf1aedc1ff354e2a Mon Sep 17 00:00:00 2001 From: George Xu Date: Tue, 28 Feb 2023 17:18:52 -0800 Subject: [PATCH 15/18] chore: add webpack tests --- .../plugin/webpack/test/WebpackConfig_spec.ts | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/packages/plugin/webpack/test/WebpackConfig_spec.ts b/packages/plugin/webpack/test/WebpackConfig_spec.ts index 2426d00eaf..e3bb02d1d8 100644 --- a/packages/plugin/webpack/test/WebpackConfig_spec.ts +++ b/packages/plugin/webpack/test/WebpackConfig_spec.ts @@ -27,6 +27,55 @@ const sampleWebpackConfig = { }; describe('WebpackConfigGenerator', () => { + describe('rendererTarget', () => { + it('is web if undefined', async () => { + const config = { + renderer: { + entryPoints: [{ name: 'foo', js: 'foo/index.js' }], + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, '/', false, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig[0].target).to.equal('web'); + }); + + it('is web if false', async () => { + const config = { + renderer: { + entryPoints: [{ name: 'foo', js: 'foo/index.js' }], + nodeIntegration: false, + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, '/', false, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig[0].target).to.equal('web'); + }); + + it('is electron-renderer if true', async () => { + const config = { + renderer: { + entryPoints: [{ name: 'foo', js: 'foo/index.js' }], + nodeIntegration: true, + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, '/', false, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig[0].target).to.equal('electron-renderer'); + }); + + it('is web if entry nodeIntegration is false', async () => { + const config = { + renderer: { + entryPoints: [{ name: 'foo', js: 'foo/index.js', nodeIntegration: false }], + nodeIntegration: true, + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, '/', false, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig[0].target).to.equal('web'); + }); + }); + describe('getDefines', () => { it('throws an error if renderer.entryPoints does not exist', () => { const config = { @@ -332,9 +381,16 @@ describe('WebpackConfigGenerator', () => { const generator = new WebpackConfigGenerator(config, mockProjectDir, false, 3000); const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); expect(webpackConfig[0].target).to.equal('web'); + expect(webpackConfig[0].mode).to.equal('development'); expect(webpackConfig[0].entry).to.deep.equal({ main: ['rendererScript.js'], }); + expect(webpackConfig[0].output).to.deep.equal({ + path: path.join(mockProjectDir, '.webpack', 'renderer'), + filename: '[name]/preload.js', + globalObject: 'self', + publicPath: '/', + }); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion expect(webpackConfig[0].plugins!.length).to.equal(2); expect(hasAssetRelocatorPatchPlugin(webpackConfig[0].plugins)).to.equal(true); @@ -368,6 +424,34 @@ describe('WebpackConfigGenerator', () => { expect(hasAssetRelocatorPatchPlugin(webpackConfig[0].plugins)).to.equal(true); }); + it('generates a production config with entryPoint preload', async () => { + const config = { + renderer: { + entryPoints: [ + { + name: 'main', + preload: { + js: 'preload.js', + }, + }, + ], + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig[0].target).to.equal('web'); + expect(webpackConfig[0].mode).to.equal('production'); + expect(webpackConfig[0].entry).to.deep.equal({ main: ['preload.js'] }); + expect(webpackConfig[0].output).to.deep.equal({ + path: path.join(mockProjectDir, '.webpack', 'renderer'), + filename: '[name]/preload.js', + globalObject: 'self', + }); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + expect(webpackConfig[0].plugins!.length).to.equal(2); + expect(hasAssetRelocatorPatchPlugin(webpackConfig[0].plugins)).to.equal(true); + }); + it('generates a preload-only production config', async () => { const config = { renderer: { @@ -417,11 +501,35 @@ describe('WebpackConfigGenerator', () => { expect(webpackConfig[0].target).to.equal('web'); }); + it('prevents the preload target from being overridden', async () => { + const config = { + renderer: { + config: { + target: 'web', + }, + entryPoints: [ + { + name: 'main', + preload: { + js: 'preload.js', + }, + nodeIntegration: true, + }, + ], + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig[0].target).to.equal('electron-preload'); + }); + it('allows you to specify a preload webpack config', async () => { const config = { renderer: { config: { target: 'web', + name: 'renderer', + entry: 'renderer', }, entryPoints: [ { From c3d6fa1eaae5917b77b1a26c2ea5ef2a1afd4899 Mon Sep 17 00:00:00 2001 From: George Xu Date: Tue, 22 Aug 2023 15:50:45 -0700 Subject: [PATCH 16/18] clean up assetRelocatorPatch path --- packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts index 709813f618..70be2d3e09 100644 --- a/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts +++ b/packages/plugin/webpack/test/AssetRelocatorPatch_spec.ts @@ -204,7 +204,7 @@ describe('AssetRelocatorPatch', () => { await expectOutputFileToHaveTheCorrectNativeModulePath({ outDir: rendererOut, jsPath: path.join(rendererOut, 'main_window/preload.js'), - nativeModulesString: '.ab=require("path").resolve(require("path").dirname(__filename),"..")+"/native_modules/"', + nativeModulesString: '.ab=require("path").resolve(__dirname,"..")+"/native_modules/"', nativePathString: `.ab+"${nativePathSuffix}"`, }); }); From 43ab5904f324046cca1245c8219b3b8fdff6fad7 Mon Sep 17 00:00:00 2001 From: George Xu Date: Mon, 28 Aug 2023 16:53:23 -0700 Subject: [PATCH 17/18] add test and fix merge order prioritization --- packages/plugin/webpack/src/WebpackConfig.ts | 4 +- .../plugin/webpack/test/WebpackConfig_spec.ts | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index ee409ce74e..cbd28b1019 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -275,7 +275,7 @@ export default class WebpackConfigGenerator { ); } } - return webpackMerge(baseConfig, rendererConfig || {}, { entry, output, plugins }); + return webpackMerge({ entry, output, plugins }, rendererConfig || {}, baseConfig); } async buildRendererConfigForPreloadOrSandboxedPreloadTarget( @@ -306,7 +306,7 @@ export default class WebpackConfigGenerator { }, plugins: target === RendererTarget.ElectronPreload ? [] : [new webpack.ExternalsPlugin('commonjs2', externals)], }; - return webpackMerge(baseConfig, rendererConfig || {}, config); + return webpackMerge(config, rendererConfig || {}, baseConfig); } async buildRendererConfigs(entryPoints: WebpackPluginEntryPoint[], target: RendererTarget): Promise[]> { diff --git a/packages/plugin/webpack/test/WebpackConfig_spec.ts b/packages/plugin/webpack/test/WebpackConfig_spec.ts index e3bb02d1d8..6a390c2824 100644 --- a/packages/plugin/webpack/test/WebpackConfig_spec.ts +++ b/packages/plugin/webpack/test/WebpackConfig_spec.ts @@ -552,6 +552,54 @@ describe('WebpackConfigGenerator', () => { expect(webpackConfig[0].name).to.equal('preload'); }); + it('generates up to 4 rendererConfigs instead of 1 per entrypoint', async () => { + const config = { + renderer: { + config: { + target: 'web', + }, + entryPoints: [ + { + name: '1', + preload: { + js: 'preload.js', + }, + }, + { + name: '2', + preload: { + js: 'preload.js', + }, + nodeIntegration: true, + }, + { + html: './src/mediaPlayer/index.html', + js: './src/mediaPlayer/index.tsx', + name: '3', + }, + { + html: './src/mediaPlayer/index.html', + js: './src/mediaPlayer/index.tsx', + name: '4', + nodeIntegration: true, + }, + { + js: './src/background/background.ts', + name: '5', + }, + { + js: './src/background/background.ts', + name: '6', + nodeIntegration: true, + }, + ], + }, + } as WebpackPluginConfig; + const generator = new WebpackConfigGenerator(config, mockProjectDir, true, 3000); + const webpackConfig = await generator.getRendererConfig(config.renderer.entryPoints); + expect(webpackConfig.length).to.equal(4); + }); + it('generates a config from function', async () => { const generateWebpackConfig = (webpackConfig: WebpackConfiguration) => { const config = { From d2900677f83eeeec9749f49e26a95d0002d624c4 Mon Sep 17 00:00:00 2001 From: George Xu Date: Tue, 29 Aug 2023 14:25:45 -0700 Subject: [PATCH 18/18] revert webpack merge priority change --- packages/plugin/webpack/src/WebpackConfig.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/webpack/src/WebpackConfig.ts b/packages/plugin/webpack/src/WebpackConfig.ts index cbd28b1019..ee409ce74e 100644 --- a/packages/plugin/webpack/src/WebpackConfig.ts +++ b/packages/plugin/webpack/src/WebpackConfig.ts @@ -275,7 +275,7 @@ export default class WebpackConfigGenerator { ); } } - return webpackMerge({ entry, output, plugins }, rendererConfig || {}, baseConfig); + return webpackMerge(baseConfig, rendererConfig || {}, { entry, output, plugins }); } async buildRendererConfigForPreloadOrSandboxedPreloadTarget( @@ -306,7 +306,7 @@ export default class WebpackConfigGenerator { }, plugins: target === RendererTarget.ElectronPreload ? [] : [new webpack.ExternalsPlugin('commonjs2', externals)], }; - return webpackMerge(config, rendererConfig || {}, baseConfig); + return webpackMerge(baseConfig, rendererConfig || {}, config); } async buildRendererConfigs(entryPoints: WebpackPluginEntryPoint[], target: RendererTarget): Promise[]> {