From 393709d3493ec3d90a0ac1c9b1d7536afde092eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8D=89=E9=9E=8B=E6=B2=A1=E5=8F=B7?= <308487730@qq.com> Date: Sat, 25 Feb 2023 08:14:36 +0800 Subject: [PATCH] feat(template): add vite template (#3071) * feat(template): add vite template * refactor: better `CLIOptions` type define * feat: semantic Renderer config * feat!:support multiple renderer * chore: cleanup * feat: add ViteConfig test * chore: format code * feat: add util/plugins test * fix(test): compatible Windows OS * Update packages/plugin/vite/src/ViteConfig.ts Co-authored-by: Black-Hole <158blackhole@gmail.com> * Update packages/plugin/vite/src/util/plugins.ts Co-authored-by: Black-Hole <158blackhole@gmail.com> * Update packages/template/vite/.eslintignore Co-authored-by: Black-Hole <158blackhole@gmail.com> * Update packages/plugin/vite/src/ViteConfig.ts Co-authored-by: Black-Hole <158blackhole@gmail.com> * fix: typo * Update packages/plugin/vite/README.md Co-authored-by: Black-Hole <158blackhole@gmail.com> * Update packages/plugin/vite/src/VitePlugin.ts Co-authored-by: Black-Hole <158blackhole@gmail.com> * Update packages/plugin/vite/src/VitePlugin.ts Co-authored-by: Black-Hole <158blackhole@gmail.com> * Update packages/plugin/vite/src/VitePlugin.ts Co-authored-by: Black-Hole <158blackhole@gmail.com> * Update packages/plugin/vite/src/VitePlugin.ts Co-authored-by: Black-Hole <158blackhole@gmail.com> * chore: format code * chore: update version * chore: update version numbers * chore: update lockfile --------- Co-authored-by: Black-Hole <158blackhole@gmail.com> Co-authored-by: Erick Zhao --- package.json | 1 + packages/plugin/vite/README.md | 36 ++++ packages/plugin/vite/package.json | 38 ++++ packages/plugin/vite/src/Config.ts | 34 ++++ packages/plugin/vite/src/ViteConfig.ts | 129 +++++++++++++ packages/plugin/vite/src/VitePlugin.ts | 161 ++++++++++++++++ packages/plugin/vite/src/util/plugins.ts | 35 ++++ packages/plugin/vite/test/ViteConfig_spec.ts | 70 +++++++ .../plugin/vite/test/util/plugins_spec.ts | 45 +++++ packages/template/base/tmpl/_gitignore | 3 + packages/template/vite/.eslintignore | 1 + packages/template/vite/package.json | 30 +++ packages/template/vite/src/ViteTemplate.ts | 65 +++++++ .../template/vite/test/ViteTemplate_spec.ts | 58 ++++++ packages/template/vite/tmpl/forge.config.js | 48 +++++ packages/template/vite/tmpl/package.json | 5 + packages/template/vite/tmpl/preload.js | 2 + packages/template/vite/tmpl/renderer.js | 31 +++ .../template/vite/tmpl/vite.main.config.mjs | 4 + .../vite/tmpl/vite.preload.config.mjs | 4 + .../vite/tmpl/vite.renderer.config.mjs | 4 + yarn.lock | 178 +++++++++++++++++- 22 files changed, 981 insertions(+), 1 deletion(-) create mode 100644 packages/plugin/vite/README.md create mode 100644 packages/plugin/vite/package.json create mode 100644 packages/plugin/vite/src/Config.ts create mode 100644 packages/plugin/vite/src/ViteConfig.ts create mode 100644 packages/plugin/vite/src/VitePlugin.ts create mode 100644 packages/plugin/vite/src/util/plugins.ts create mode 100644 packages/plugin/vite/test/ViteConfig_spec.ts create mode 100644 packages/plugin/vite/test/util/plugins_spec.ts create mode 100644 packages/template/vite/.eslintignore create mode 100644 packages/template/vite/package.json create mode 100644 packages/template/vite/src/ViteTemplate.ts create mode 100644 packages/template/vite/test/ViteTemplate_spec.ts create mode 100644 packages/template/vite/tmpl/forge.config.js create mode 100644 packages/template/vite/tmpl/package.json create mode 100644 packages/template/vite/tmpl/preload.js create mode 100644 packages/template/vite/tmpl/renderer.js create mode 100644 packages/template/vite/tmpl/vite.main.config.mjs create mode 100644 packages/template/vite/tmpl/vite.preload.config.mjs create mode 100644 packages/template/vite/tmpl/vite.renderer.config.mjs diff --git a/package.json b/package.json index d90d35f193..94a5a489af 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "source-map-support": "^0.5.13", "sudo-prompt": "^9.1.1", "username": "^5.1.0", + "vite": "^4.1.1", "webpack": "^5.69.1", "webpack-dev-server": "^4.0.0", "webpack-merge": "^5.7.3", diff --git a/packages/plugin/vite/README.md b/packages/plugin/vite/README.md new file mode 100644 index 0000000000..f6f3b2695c --- /dev/null +++ b/packages/plugin/vite/README.md @@ -0,0 +1,36 @@ +## plugin-vite + +This plugin makes it easy to set up standard vite tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers. + +```javascript +// forge.config.js + +module.exports = { + plugins: [ + { + name: '@electron-forge/plugin-vite', + config: { + // `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc. + // If you are familiar with Vite configuration, it will look really familiar. + build: [ + { + // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`. + entry: 'src/main.js', + config: 'vite.main.config.mjs', + }, + { + entry: 'src/preload.js', + config: 'vite.preload.config.mjs', + }, + ], + renderer: [ + { + name: 'main_window', + config: 'vite.renderer.config.mjs', + }, + ], + }, + }, + ], +}; +``` \ No newline at end of file diff --git a/packages/plugin/vite/package.json b/packages/plugin/vite/package.json new file mode 100644 index 0000000000..7b8d294709 --- /dev/null +++ b/packages/plugin/vite/package.json @@ -0,0 +1,38 @@ +{ + "name": "@electron-forge/plugin-vite", + "version": "6.1.0", + "description": "Vite plugin for Electron Forge, lets you use Vite directly in your tooling", + "repository": { + "type": "git", + "url": "https://github.com/electron/forge", + "directory": "packages/plugin/vite" + }, + "author": "caoxiemeihao", + "license": "MIT", + "main": "dist/VitePlugin.js", + "typings": "dist/VitePlugin.d.ts", + "scripts": { + "test": "xvfb-maybe mocha --config ../../../.mocharc.js test/**/*_spec.ts" + }, + "devDependencies": { + "@malept/cross-spawn-promise": "^2.0.0", + "@types/node": "^18.0.3", + "chai": "^4.3.3", + "fs-extra": "^10.0.0", + "mocha": "^9.0.1", + "which": "^2.0.2", + "xvfb-maybe": "^0.2.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "dependencies": { + "@electron-forge/core-utils": "6.0.5", + "@electron-forge/plugin-base": "6.0.5", + "@electron-forge/shared-types": "6.0.5", + "@electron-forge/web-multi-logger": "6.0.5", + "chalk": "^4.0.0", + "debug": "^4.3.1", + "vite": "^4.1.1" + } +} diff --git a/packages/plugin/vite/src/Config.ts b/packages/plugin/vite/src/Config.ts new file mode 100644 index 0000000000..2f1ffd3601 --- /dev/null +++ b/packages/plugin/vite/src/Config.ts @@ -0,0 +1,34 @@ +import type { LibraryOptions } from 'vite'; + +export interface VitePluginBuildConfig { + /** + * Alias of `build.lib.entry` in `config`. + */ + entry?: LibraryOptions['entry']; + /** + * Vite config file path. + */ + config?: string; +} + +export interface VitePluginRendererConfig { + /** + * Human friendly name of your entry point + */ + name: string; + /** + * Vite config file path. + */ + config: string; +} + +export interface VitePluginConfig { + /** + * Build anything such as Main process, Preload scripts and Worker process, etc. + */ + build: VitePluginBuildConfig[]; + /** + * Renderer process. + */ + renderer: VitePluginRendererConfig[]; +} diff --git a/packages/plugin/vite/src/ViteConfig.ts b/packages/plugin/vite/src/ViteConfig.ts new file mode 100644 index 0000000000..c03449054c --- /dev/null +++ b/packages/plugin/vite/src/ViteConfig.ts @@ -0,0 +1,129 @@ +import path from 'node:path'; + +import debug from 'debug'; +import { ConfigEnv, loadConfigFromFile, mergeConfig, UserConfig } from 'vite'; + +import { VitePluginConfig } from './Config'; +import { externalBuiltins } from './util/plugins'; + +const d = debug('electron-forge:plugin:vite:viteconfig'); + +/** + * Vite allows zero-config runs, if the user does not provide `vite.config.js`, + * then the value of `LoadResult` will become `null`. + */ +export type LoadResult = Awaited>; + +export default class ViteConfigGenerator { + private readonly baseDir: string; + + private rendererConfigCache!: Promise[]; + + constructor(private readonly pluginConfig: VitePluginConfig, private readonly projectDir: string, private readonly isProd: boolean) { + this.baseDir = path.join(projectDir, '.vite'); + d('Config mode:', this.mode); + } + + resolveConfig(config: string, configEnv: Partial = {}) { + // `command` is to be passed as an arguments when the user export a function in `vite.config.js`. + // @see - https://vitejs.dev/config/#conditional-config + configEnv.command ??= this.isProd ? 'build' : 'serve'; + // `mode` affects `.env.[mode]` file loading. + configEnv.mode ??= this.mode; + return loadConfigFromFile(configEnv as ConfigEnv, config); + } + + get mode(): string { + // Vite's `mode` can be passed in via command. + // Since we are currently using the JavaScript API, we are opinionated defining two default values for mode here. + // The `mode` set by the end user in `vite.config.js` has a higher priority. + return this.isProd ? 'production' : 'development'; + } + + async getDefines(): Promise> { + const defines: Record = {}; + const rendererConfigs = await this.getRendererConfig(); + for (const [index, userConfig] of rendererConfigs.entries()) { + const name = this.pluginConfig.renderer[index].name; + if (!name) { + continue; + } + const NAME = name.toUpperCase().replace(/ /g, '_'); + // There is no guarantee that `port` will always be available, because it may auto increment. + // https://github.com/vitejs/vite/blob/v4.0.4/packages/vite/src/node/http.ts#L170 + defines[`${NAME}_VITE_DEV_SERVER_URL`] = this.isProd + ? undefined + : userConfig?.server?.port && JSON.stringify(`http://localhost:${userConfig.server.port}`); + defines[`${NAME}_VITE_NAME`] = JSON.stringify(name); + } + return defines; + } + + async getBuildConfig(watch = false): Promise { + if (!Array.isArray(this.pluginConfig.build)) { + throw new Error('"config.build" must be an Array'); + } + + const define = await this.getDefines(); + const plugins = [externalBuiltins()]; + const configs = this.pluginConfig.build + .filter(({ entry, config }) => entry || config) + .map>(async ({ entry, config }) => { + const defaultConfig: UserConfig = { + // Ensure that each build config loads the .env file correctly. + mode: this.mode, + build: { + lib: entry + ? { + entry, + // Electron can only support cjs. + formats: ['cjs'], + fileName: () => '[name].js', + } + : undefined, + // Prevent multiple builds from interfering with each other. + emptyOutDir: false, + // 🚧 Multiple builds may conflict. + outDir: path.join(this.baseDir, 'build'), + watch: watch ? {} : undefined, + }, + clearScreen: false, + define, + plugins, + }; + if (config) { + const loadResult = await this.resolveConfig(config); + return mergeConfig(defaultConfig, loadResult?.config ?? {}); + } + return defaultConfig; + }); + + return await Promise.all(configs); + } + + async getRendererConfig(): Promise { + if (!Array.isArray(this.pluginConfig.renderer)) { + throw new Error('"config.renderer" must be an Array'); + } + + let port = 5173; + const configs = (this.rendererConfigCache ??= this.pluginConfig.renderer.map(async ({ name, config }) => { + const defaultConfig: UserConfig = { + // Ensure that each build config loads the .env file correctly. + mode: this.mode, + // Make sure that Electron can be loaded into the local file using `loadFile` after packaging. + base: './', + build: { + outDir: path.join(this.baseDir, 'renderer', name), + }, + clearScreen: false, + }; + const loadResult = (await this.resolveConfig(config)) ?? { path: '', config: {}, dependencies: [] }; + loadResult.config.server ??= {}; + loadResult.config.server.port ??= port++; + return mergeConfig(defaultConfig, loadResult.config); + })); + + return await Promise.all(configs); + } +} diff --git a/packages/plugin/vite/src/VitePlugin.ts b/packages/plugin/vite/src/VitePlugin.ts new file mode 100644 index 0000000000..9e2bfe3174 --- /dev/null +++ b/packages/plugin/vite/src/VitePlugin.ts @@ -0,0 +1,161 @@ +import fs from 'node:fs/promises'; +import http from 'node:http'; +import path from 'node:path'; + +import { namedHookWithTaskFn, PluginBase } from '@electron-forge/plugin-base'; +import { ForgeMultiHookMap, StartResult } from '@electron-forge/shared-types'; +import debug from 'debug'; +// eslint-disable-next-line node/no-extraneous-import +import { RollupWatcher } from 'rollup'; +import { default as vite } from 'vite'; + +import { VitePluginConfig } from './Config'; +import ViteConfigGenerator from './ViteConfig'; + +const d = debug('electron-forge:plugin:vite'); + +export default class VitePlugin extends PluginBase { + private static alreadyStarted = false; + + public name = 'vite'; + + private isProd = false; + + // The root of the Electron app + private projectDir!: string; + + // Where the Vite output is generated. Usually `${projectDir}/.vite` + private baseDir!: string; + + private configGeneratorCache!: ViteConfigGenerator; + + private watchers: RollupWatcher[] = []; + + private servers: http.Server[] = []; + + init = (dir: string): void => { + this.setDirectories(dir); + + d('hooking process events'); + process.on('exit', (_code) => this.exitHandler({ cleanup: true })); + process.on('SIGINT' as NodeJS.Signals, (_signal) => this.exitHandler({ exit: true })); + }; + + private setDirectories(dir: string): void { + this.projectDir = dir; + this.baseDir = path.join(dir, '.vite'); + } + + private get configGenerator(): ViteConfigGenerator { + return (this.configGeneratorCache ??= new ViteConfigGenerator(this.config, this.projectDir, this.isProd)); + } + + getHooks = (): ForgeMultiHookMap => { + return { + prePackage: [ + namedHookWithTaskFn<'prePackage'>(async () => { + this.isProd = true; + await fs.rmdir(this.baseDir, { recursive: true }); + + await Promise.all([this.build(), this.buildRenderer()]); + }, 'Building vite bundles'), + ], + }; + }; + + startLogic = async (): Promise => { + if (VitePlugin.alreadyStarted) return false; + VitePlugin.alreadyStarted = true; + + await fs.rmdir(this.baseDir, { recursive: true }); + + return { + tasks: [ + { + title: 'Compiling main process code', + task: async () => { + await this.build(true); + }, + options: { + showTimer: true, + }, + }, + { + title: 'Launching dev servers for renderer process code', + task: async () => { + await this.launchRendererDevServers(); + }, + options: { + persistentOutput: true, + showTimer: true, + }, + }, + ], + result: false, + }; + }; + + // Main process, Preload scripts and Worker process, etc. + build = async (watch = false): Promise => { + for (const userConfig of await this.configGenerator.getBuildConfig(watch)) { + const buildResult = await vite.build({ + // Avoid recursive builds caused by users configuring @electron-forge/plugin-vite in Vite config file. + configFile: false, + ...userConfig, + }); + + if (Object.keys(buildResult).includes('close')) { + this.watchers.push(buildResult as RollupWatcher); + } + } + }; + + // Renderer process + buildRenderer = async (): Promise => { + for (const userConfig of await this.configGenerator.getRendererConfig()) { + await vite.build({ + configFile: false, + ...userConfig, + }); + } + }; + + launchRendererDevServers = async (): Promise => { + for (const userConfig of await this.configGenerator.getRendererConfig()) { + const viteDevServer = await vite.createServer({ + configFile: false, + ...userConfig, + }); + + await viteDevServer.listen(); + viteDevServer.printUrls(); + + if (viteDevServer.httpServer) { + this.servers.push(viteDevServer.httpServer); + } + } + }; + + exitHandler = (options: { cleanup?: boolean; exit?: boolean }, err?: Error): void => { + d('handling process exit with:', options); + if (options.cleanup) { + for (const watcher of this.watchers) { + d('cleaning vite watcher'); + watcher.close(); + } + this.watchers = []; + + for (const server of this.servers) { + d('cleaning http server'); + server.close(); + } + this.servers = []; + } + if (err) console.error(err.stack); + // Why: This is literally what the option says to do. + // eslint-disable-next-line no-process-exit + if (options.exit) process.exit(); + }; +} + +export { VitePlugin }; diff --git a/packages/plugin/vite/src/util/plugins.ts b/packages/plugin/vite/src/util/plugins.ts new file mode 100644 index 0000000000..fb5df3db1b --- /dev/null +++ b/packages/plugin/vite/src/util/plugins.ts @@ -0,0 +1,35 @@ +import { builtinModules } from 'node:module'; + +import type { Plugin } from 'vite'; + +/** + * `electron` and Node.js built-in modules should always be externalize. + */ +export function externalBuiltins() { + return { + name: '@electron-forge/plugin-vite:external-builtins', + config(config) { + const nativeModules = builtinModules.filter((e) => !e.startsWith('_')); + const builtins = ['electron', ...nativeModules, ...nativeModules.map((m) => `node:${m}`)]; + + config.build ??= {}; + config.build.rollupOptions ??= {}; + + let external = config.build.rollupOptions.external; + if (Array.isArray(external) || typeof external === 'string' || external instanceof RegExp) { + external = builtins.concat(external as string[]); + } else if (typeof external === 'function') { + const original = external; + external = function (source, importer, isResolved) { + if (builtins.includes(source)) { + return true; + } + return original(source, importer, isResolved); + }; + } else { + external = builtins; + } + config.build.rollupOptions.external = external; + }, + }; +} diff --git a/packages/plugin/vite/test/ViteConfig_spec.ts b/packages/plugin/vite/test/ViteConfig_spec.ts new file mode 100644 index 0000000000..3699dab4f4 --- /dev/null +++ b/packages/plugin/vite/test/ViteConfig_spec.ts @@ -0,0 +1,70 @@ +import path from 'node:path'; + +import { expect } from 'chai'; +import { UserConfig } from 'vite'; + +import { VitePluginConfig } from '../src/Config'; +import ViteConfigGenerator from '../src/ViteConfig'; + +describe('ViteConfigGenerator', () => { + it('getDefines', async () => { + const config = { + renderer: [{ name: 'foo_window' }, { name: 'bar_window' }], + } as VitePluginConfig; + const generator = new ViteConfigGenerator(config, '', false); + const define = await generator.getDefines(); + expect(define.FOO_WINDOW_VITE_DEV_SERVER_URL).equal('"http://localhost:5173"'); + expect(define.FOO_WINDOW_VITE_NAME).equal('"foo_window"'); + expect(define.BAR_WINDOW_VITE_DEV_SERVER_URL).equal('"http://localhost:5174"'); + expect(define.BAR_WINDOW_VITE_NAME).equal('"bar_window"'); + }); + + it('getBuildConfig', async () => { + const config = { + build: [{ entry: 'foo.js' }], + renderer: [], + } as VitePluginConfig; + const generator = new ViteConfigGenerator(config, '', true); + const buildConfig = (await generator.getBuildConfig())[0]; + expect(buildConfig).deep.equal({ + mode: 'production', + build: { + lib: { + entry: 'foo.js', + formats: ['cjs'], + // shims + fileName: (buildConfig.build?.lib as any)?.fileName, + }, + emptyOutDir: false, + outDir: path.join('.vite', 'build'), + watch: undefined, + }, + clearScreen: false, + define: {}, + // shims + plugins: [buildConfig.plugins?.[0]], + } as UserConfig); + }); + + it('getRendererConfig', async () => { + const config = { + renderer: [{ name: 'foo_window' }, { name: 'bar_window' }], + } as VitePluginConfig; + const generator = new ViteConfigGenerator(config, '', false); + let port = 5173; + const configs = await generator.getRendererConfig(); + for (const [index, rendererConfig] of configs.entries()) { + expect(rendererConfig).deep.equal({ + mode: 'development', + base: './', + build: { + outDir: path.join('.vite', 'renderer', config.renderer[index].name), + }, + clearScreen: false, + server: { + port: port++, + }, + } as UserConfig); + } + }); +}); diff --git a/packages/plugin/vite/test/util/plugins_spec.ts b/packages/plugin/vite/test/util/plugins_spec.ts new file mode 100644 index 0000000000..bdf0eb226e --- /dev/null +++ b/packages/plugin/vite/test/util/plugins_spec.ts @@ -0,0 +1,45 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { builtinModules } from 'module'; + +import { expect } from 'chai'; +// eslint-disable-next-line node/no-extraneous-import +import { ExternalOption } from 'rollup'; +import { resolveConfig } from 'vite'; + +import { externalBuiltins } from '../../src/util/plugins'; + +describe('plugins', () => { + it('externalBuiltins', async () => { + const nativeModules = builtinModules.filter((e) => !e.startsWith('_')); + const builtins: any[] = ['electron', ...nativeModules, ...nativeModules.map((m) => `node:${m}`)]; + const getConfig = (external: ExternalOption) => + resolveConfig( + { + configFile: false, + build: { + rollupOptions: { + external, + }, + }, + plugins: [externalBuiltins()], + }, + 'build' + ); + + const external_string: ExternalOption = 'electron'; + const external_string2 = (await getConfig(external_string))!.build!.rollupOptions!.external; + expect(external_string2).deep.equal(builtins.concat(external_string)); + + const external_array: ExternalOption = ['electron']; + const external_array2 = (await getConfig(external_array))!.build!.rollupOptions!.external; + expect(external_array2).deep.equal(builtins.concat(external_array)); + + const external_regexp: ExternalOption = /electron/; + const external_regexp2 = (await getConfig(external_regexp))!.build!.rollupOptions!.external; + expect(external_regexp2).deep.equal(builtins.concat(external_regexp)); + + const external_function: ExternalOption = (source) => ['electron'].includes(source); + const external_function2 = (await getConfig(external_function))!.build!.rollupOptions!.external; + expect((external_function2 as (source: string) => boolean)('electron')).true; + }); +}); diff --git a/packages/template/base/tmpl/_gitignore b/packages/template/base/tmpl/_gitignore index 8e3a106692..8296128de7 100644 --- a/packages/template/base/tmpl/_gitignore +++ b/packages/template/base/tmpl/_gitignore @@ -85,5 +85,8 @@ typings/ # Webpack .webpack/ +# Vite +.vite/ + # Electron-Forge out/ diff --git a/packages/template/vite/.eslintignore b/packages/template/vite/.eslintignore new file mode 100644 index 0000000000..14e485a5bc --- /dev/null +++ b/packages/template/vite/.eslintignore @@ -0,0 +1 @@ +tmpl diff --git a/packages/template/vite/package.json b/packages/template/vite/package.json new file mode 100644 index 0000000000..f8826eb4f7 --- /dev/null +++ b/packages/template/vite/package.json @@ -0,0 +1,30 @@ +{ + "name": "@electron-forge/template-vite", + "version": "6.1.0", + "description": "Vite template for Electron Forge, gets you started with Vite really quickly", + "repository": { + "type": "git", + "url": "https://github.com/electron/forge", + "directory": "packages/template/vite" + }, + "author": "caoxiemeihao", + "license": "MIT", + "main": "dist/ViteTemplate.js", + "typings": "dist/ViteTemplate.d.ts", + "scripts": { + "test": "mocha --config ../../../.mocharc.js test/**/*_spec.ts" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "dependencies": { + "@electron-forge/shared-types": "6.0.5", + "@electron-forge/template-base": "6.0.5", + "fs-extra": "^10.0.0" + }, + "devDependencies": { + "@electron-forge/test-utils": "6.0.5", + "chai": "^4.3.3", + "listr2": "^5.0.3" + } +} diff --git a/packages/template/vite/src/ViteTemplate.ts b/packages/template/vite/src/ViteTemplate.ts new file mode 100644 index 0000000000..2dbe62e474 --- /dev/null +++ b/packages/template/vite/src/ViteTemplate.ts @@ -0,0 +1,65 @@ +import path from 'path'; + +import { ForgeListrTaskDefinition, InitTemplateOptions } from '@electron-forge/shared-types'; +import { BaseTemplate } from '@electron-forge/template-base'; +import fs from 'fs-extra'; + +class ViteTemplate extends BaseTemplate { + public templateDir = path.resolve(__dirname, '..', 'tmpl'); + + public async initializeTemplate(directory: string, options: InitTemplateOptions): Promise { + const superTasks = await super.initializeTemplate(directory, options); + return [ + ...superTasks, + { + title: 'Setting up Forge configuration', + task: async () => { + await this.copyTemplateFile(directory, 'forge.config.js'); + }, + }, + { + title: 'Setting up Vite configuration', + task: async () => { + await this.copyTemplateFile(directory, 'vite.renderer.config.mjs'); + await this.copyTemplateFile(directory, 'vite.main.config.mjs'); + await this.copyTemplateFile(directory, 'vite.preload.config.mjs'); + await this.copyTemplateFile(path.join(directory, 'src'), 'renderer.js'); + await this.copyTemplateFile(path.join(directory, 'src'), 'preload.js'); + + await this.updateFileByLine( + path.resolve(directory, 'src', 'index.js'), + (line) => { + if (line.includes('mainWindow.loadFile')) + return ` if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { + mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL); + } else { + mainWindow.loadFile(path.join(__dirname, \`../renderer/\${MAIN_WINDOW_VITE_NAME}/index.html\`)); + }`; + return line; + }, + path.resolve(directory, 'src', 'main.js') + ); + + // TODO: Compatible with any path entry. + // Vite uses index.html under the root path as the entry point. + fs.moveSync(path.join(directory, 'src', 'index.html'), path.join(directory, 'index.html')); + await this.updateFileByLine(path.join(directory, 'index.html'), (line) => { + if (line.includes('link rel="stylesheet"')) return ''; + if (line.includes('')) return ' \n '; + return line; + }); + + // update package.json entry point + const pjPath = path.resolve(directory, 'package.json'); + const currentPJ = await fs.readJson(pjPath); + currentPJ.main = '.vite/build/main.js'; + await fs.writeJson(pjPath, currentPJ, { + spaces: 2, + }); + }, + }, + ]; + } +} + +export default new ViteTemplate(); diff --git a/packages/template/vite/test/ViteTemplate_spec.ts b/packages/template/vite/test/ViteTemplate_spec.ts new file mode 100644 index 0000000000..d6c5d07eea --- /dev/null +++ b/packages/template/vite/test/ViteTemplate_spec.ts @@ -0,0 +1,58 @@ +import path from 'path'; + +import * as testUtils from '@electron-forge/test-utils'; +import { expect } from 'chai'; +import fs from 'fs-extra'; +import { Listr } from 'listr2'; + +import template from '../src/ViteTemplate'; + +describe('ViteTemplate', () => { + let dir: string; + + before(async () => { + dir = await testUtils.ensureTestDirIsNonexistent(); + }); + + it('should succeed in initializing the vite template', async () => { + const tasks = await template.initializeTemplate(dir, {}); + const runner = new Listr(tasks, { concurrent: false, exitOnError: false }); + await runner.run(); + expect(runner.err).to.have.lengthOf(0); + }); + + context('template files are copied to project', () => { + const expectedFiles = [ + 'vite.renderer.config.mjs', + 'vite.main.config.mjs', + 'vite.preload.config.mjs', + path.join('src', 'renderer.js'), + path.join('src', 'preload.js'), + ]; + for (const filename of expectedFiles) { + it(`${filename} should exist`, async () => { + await testUtils.expectProjectPathExists(dir, filename, 'file'); + }); + } + }); + + it('should move and rewrite the main process file', async () => { + await testUtils.expectProjectPathNotExists(dir, path.join('src', 'index.js'), 'file'); + await testUtils.expectProjectPathExists(dir, path.join('src', 'main.js'), 'file'); + const mainFile = (await fs.readFile(path.join(dir, 'src', 'main.js'))).toString(); + expect(mainFile).to.match(/MAIN_WINDOW_VITE_DEV_SERVER_URL/); + expect(mainFile).to.match(/\.\.\/renderer\/\${MAIN_WINDOW_VITE_NAME}\/index\.html/); + }); + + it('should remove the stylesheet link from the HTML file', async () => { + expect((await fs.readFile(path.join(dir, 'index.html'))).toString()).to.not.match(/link rel="stylesheet"/); + }); + + it('should inject script into the HTML file', async () => { + expect((await fs.readFile(path.join(dir, 'index.html'))).toString()).to.match(/src="\/src\/renderer\.js"/); + }); + + after(async () => { + await fs.remove(dir); + }); +}); diff --git a/packages/template/vite/tmpl/forge.config.js b/packages/template/vite/tmpl/forge.config.js new file mode 100644 index 0000000000..04403354a6 --- /dev/null +++ b/packages/template/vite/tmpl/forge.config.js @@ -0,0 +1,48 @@ +module.exports = { + packagerConfig: {}, + rebuildConfig: {}, + makers: [ + { + name: '@electron-forge/maker-squirrel', + config: {}, + }, + { + name: '@electron-forge/maker-zip', + platforms: ['darwin'], + }, + { + name: '@electron-forge/maker-deb', + config: {}, + }, + { + name: '@electron-forge/maker-rpm', + config: {}, + }, + ], + plugins: [ + { + name: '@electron-forge/plugin-vite', + config: { + // `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc. + // If you are familiar with Vite configuration, it will look really familiar. + build: [ + { + // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`. + entry: 'src/main.js', + config: 'vite.main.config.mjs', + }, + { + entry: 'src/preload.js', + config: 'vite.preload.config.mjs', + }, + ], + renderer: [ + { + name: 'main_window', + config: 'vite.renderer.config.mjs', + }, + ], + }, + }, + ], +}; diff --git a/packages/template/vite/tmpl/package.json b/packages/template/vite/tmpl/package.json new file mode 100644 index 0000000000..03feaefeef --- /dev/null +++ b/packages/template/vite/tmpl/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@electron-forge/plugin-vite": "ELECTRON_FORGE/VERSION" + } +} diff --git a/packages/template/vite/tmpl/preload.js b/packages/template/vite/tmpl/preload.js new file mode 100644 index 0000000000..5e9d369cc9 --- /dev/null +++ b/packages/template/vite/tmpl/preload.js @@ -0,0 +1,2 @@ +// See the Electron documentation for details on how to use preload scripts: +// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts diff --git a/packages/template/vite/tmpl/renderer.js b/packages/template/vite/tmpl/renderer.js new file mode 100644 index 0000000000..22f238be8a --- /dev/null +++ b/packages/template/vite/tmpl/renderer.js @@ -0,0 +1,31 @@ +/** + * This file will automatically be loaded by vite and run in the "renderer" context. + * To learn more about the differences between the "main" and the "renderer" context in + * Electron, visit: + * + * https://electronjs.org/docs/tutorial/application-architecture#main-and-renderer-processes + * + * By default, Node.js integration in this file is disabled. When enabling Node.js integration + * in a renderer process, please be aware of potential security implications. You can read + * more about security risks here: + * + * https://electronjs.org/docs/tutorial/security + * + * To enable Node.js integration in this file, open up `main.js` and enable the `nodeIntegration` + * flag: + * + * ``` + * // Create the browser window. + * mainWindow = new BrowserWindow({ + * width: 800, + * height: 600, + * webPreferences: { + * nodeIntegration: true + * } + * }); + * ``` + */ + +import './index.css'; + +console.log('👋 This message is being logged by "renderer.js", included via Vite'); diff --git a/packages/template/vite/tmpl/vite.main.config.mjs b/packages/template/vite/tmpl/vite.main.config.mjs new file mode 100644 index 0000000000..690be5b1a9 --- /dev/null +++ b/packages/template/vite/tmpl/vite.main.config.mjs @@ -0,0 +1,4 @@ +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config +export default defineConfig({}); diff --git a/packages/template/vite/tmpl/vite.preload.config.mjs b/packages/template/vite/tmpl/vite.preload.config.mjs new file mode 100644 index 0000000000..690be5b1a9 --- /dev/null +++ b/packages/template/vite/tmpl/vite.preload.config.mjs @@ -0,0 +1,4 @@ +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config +export default defineConfig({}); diff --git a/packages/template/vite/tmpl/vite.renderer.config.mjs b/packages/template/vite/tmpl/vite.renderer.config.mjs new file mode 100644 index 0000000000..690be5b1a9 --- /dev/null +++ b/packages/template/vite/tmpl/vite.renderer.config.mjs @@ -0,0 +1,4 @@ +import { defineConfig } from 'vite'; + +// https://vitejs.dev/config +export default defineConfig({}); diff --git a/yarn.lock b/yarn.lock index 7038abe008..dd3b1fb457 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,6 +1215,116 @@ minimatch "^3.0.4" plist "^3.0.4" +"@esbuild/android-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz#cf91e86df127aa3d141744edafcba0abdc577d23" + integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg== + +"@esbuild/android-arm@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz#025b6246d3f68b7bbaa97069144fb5fb70f2fff2" + integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw== + +"@esbuild/android-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz#c820e0fef982f99a85c4b8bfdd582835f04cd96e" + integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ== + +"@esbuild/darwin-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz#edef4487af6b21afabba7be5132c26d22379b220" + integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w== + +"@esbuild/darwin-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz#42829168730071c41ef0d028d8319eea0e2904b4" + integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg== + +"@esbuild/freebsd-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz#1f4af488bfc7e9ced04207034d398e793b570a27" + integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw== + +"@esbuild/freebsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz#636306f19e9bc981e06aa1d777302dad8fddaf72" + integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug== + +"@esbuild/linux-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz#a003f7ff237c501e095d4f3a09e58fc7b25a4aca" + integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g== + +"@esbuild/linux-arm@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz#b591e6a59d9c4fe0eeadd4874b157ab78cf5f196" + integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ== + +"@esbuild/linux-ia32@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz#24333a11027ef46a18f57019450a5188918e2a54" + integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg== + +"@esbuild/linux-loong64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz#d5ad459d41ed42bbd4d005256b31882ec52227d8" + integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ== + +"@esbuild/linux-mips64el@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz#4e5967a665c38360b0a8205594377d4dcf9c3726" + integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw== + +"@esbuild/linux-ppc64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz#206443a02eb568f9fdf0b438fbd47d26e735afc8" + integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g== + +"@esbuild/linux-riscv64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz#c351e433d009bf256e798ad048152c8d76da2fc9" + integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw== + +"@esbuild/linux-s390x@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz#661f271e5d59615b84b6801d1c2123ad13d9bd87" + integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w== + +"@esbuild/linux-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz#e4ba18e8b149a89c982351443a377c723762b85f" + integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw== + +"@esbuild/netbsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz#7d4f4041e30c5c07dd24ffa295c73f06038ec775" + integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA== + +"@esbuild/openbsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz#970fa7f8470681f3e6b1db0cc421a4af8060ec35" + integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg== + +"@esbuild/sunos-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz#abc60e7c4abf8b89fb7a4fe69a1484132238022c" + integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw== + +"@esbuild/win32-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz#7b0ff9e8c3265537a7a7b1fd9a24e7bd39fcd87a" + integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw== + +"@esbuild/win32-ia32@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz#e90fe5267d71a7b7567afdc403dfd198c292eb09" + integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig== + +"@esbuild/win32-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz#c5a1a4bfe1b57f0c3e61b29883525c6da3e5c091" + integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q== + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -5279,6 +5389,34 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +esbuild@^0.16.14: + version "0.16.17" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" + integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg== + optionalDependencies: + "@esbuild/android-arm" "0.16.17" + "@esbuild/android-arm64" "0.16.17" + "@esbuild/android-x64" "0.16.17" + "@esbuild/darwin-arm64" "0.16.17" + "@esbuild/darwin-x64" "0.16.17" + "@esbuild/freebsd-arm64" "0.16.17" + "@esbuild/freebsd-x64" "0.16.17" + "@esbuild/linux-arm" "0.16.17" + "@esbuild/linux-arm64" "0.16.17" + "@esbuild/linux-ia32" "0.16.17" + "@esbuild/linux-loong64" "0.16.17" + "@esbuild/linux-mips64el" "0.16.17" + "@esbuild/linux-ppc64" "0.16.17" + "@esbuild/linux-riscv64" "0.16.17" + "@esbuild/linux-s390x" "0.16.17" + "@esbuild/linux-x64" "0.16.17" + "@esbuild/netbsd-x64" "0.16.17" + "@esbuild/openbsd-x64" "0.16.17" + "@esbuild/sunos-x64" "0.16.17" + "@esbuild/win32-arm64" "0.16.17" + "@esbuild/win32-ia32" "0.16.17" + "@esbuild/win32-x64" "0.16.17" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -8242,6 +8380,11 @@ nanoid@3.3.1: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -9139,6 +9282,15 @@ plist@^3.0.4, plist@^3.0.5: base64-js "^1.5.1" xmlbuilder "^15.1.1" +postcss@^8.4.21: + version "8.4.21" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" + integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -9610,7 +9762,7 @@ resolve@^1.1.6, resolve@^1.10.1, resolve@^1.11.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.0: +resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -9703,6 +9855,13 @@ roarr@^2.15.3: semver-compare "^1.0.0" sprintf-js "^1.1.2" +rollup@^3.10.0: + version "3.17.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.17.2.tgz#a4ecd29c488672a0606e41ef57474fad715750a9" + integrity sha512-qMNZdlQPCkWodrAZ3qnJtvCAl4vpQ8q77uEujVCCbC/6CLB7Lcmvjq7HyiOSnf4fxTT9XgsE36oLHJBH49xjqA== + optionalDependencies: + fsevents "~2.3.2" + run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -10043,6 +10202,11 @@ sort-keys@^4.0.0: dependencies: is-plain-obj "^2.0.0" +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + source-map-support@^0.5.13, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -10905,6 +11069,18 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +vite@^4.1.1: + version "4.1.4" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.1.4.tgz#170d93bcff97e0ebc09764c053eebe130bfe6ca0" + integrity sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg== + dependencies: + esbuild "^0.16.14" + postcss "^8.4.21" + resolve "^1.22.1" + rollup "^3.10.0" + optionalDependencies: + fsevents "~2.3.2" + vscode-oniguruma@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz#2bf4dfcfe3dd2e56eb549a3068c8ee39e6c30ce5"