Skip to content

Commit

Permalink
fix(plugin-vite): build size to lage
Browse files Browse the repository at this point in the history
  • Loading branch information
caoxiemeihao committed Dec 31, 2023
1 parent 219bde6 commit 7560f15
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 7 deletions.
4 changes: 2 additions & 2 deletions packages/plugin/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
"main": "dist/VitePlugin.js",
"typings": "dist/VitePlugin.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",
"@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"
Expand All @@ -33,6 +32,7 @@
"@electron-forge/web-multi-logger": "7.2.0",
"chalk": "^4.0.0",
"debug": "^4.3.1",
"fs-extra": "^10.0.0",
"vite": "^4.1.1"
},
"publishConfig": {
Expand Down
68 changes: 63 additions & 5 deletions packages/plugin/vite/src/VitePlugin.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import fs from 'node:fs/promises';
import { AddressInfo } from 'node:net';
import path from 'node:path';

import { namedHookWithTaskFn, PluginBase } from '@electron-forge/plugin-base';
import { ForgeMultiHookMap, StartResult } from '@electron-forge/shared-types';
import { ForgeMultiHookMap, ResolvedForgeConfig, StartResult } from '@electron-forge/shared-types';
import chalk from 'chalk';
import debug from 'debug';
import fs from 'fs-extra';
// eslint-disable-next-line node/no-extraneous-import
import { RollupWatcher } from 'rollup';
import { default as vite } from 'vite';

import { VitePluginConfig } from './Config';
import { getFlatDependencies } from './util/package';
import ViteConfigGenerator from './ViteConfig';

// Convenient for user customization.
export { resolveDependencies } from './util/package';

const d = debug('electron-forge:plugin:vite');

export default class VitePlugin extends PluginBase<VitePluginConfig> {
Expand Down Expand Up @@ -41,7 +46,7 @@ export default class VitePlugin extends PluginBase<VitePluginConfig> {
process.on('SIGINT' as NodeJS.Signals, (_signal) => this.exitHandler({ exit: true }));
};

private setDirectories(dir: string): void {
public setDirectories(dir: string): void {
this.projectDir = dir;
this.baseDir = path.join(dir, '.vite');
}
Expand All @@ -55,7 +60,7 @@ export default class VitePlugin extends PluginBase<VitePluginConfig> {
prePackage: [
namedHookWithTaskFn<'prePackage'>(async () => {
this.isProd = true;
await fs.rm(this.baseDir, { recursive: true, force: true });
await fs.remove(this.baseDir);

await Promise.all([this.build(), this.buildRenderer()]);
}, 'Building vite bundles'),
Expand All @@ -67,14 +72,67 @@ export default class VitePlugin extends PluginBase<VitePluginConfig> {
this.exitHandler({ cleanup: true, exit: true });
});
},
resolveForgeConfig: this.resolveForgeConfig,
packageAfterCopy: this.packageAfterCopy,
};
};

resolveForgeConfig = async (forgeConfig: ResolvedForgeConfig): Promise<ResolvedForgeConfig> => {
forgeConfig.packagerConfig ??= {};

if (forgeConfig.packagerConfig.ignore) {
if (typeof forgeConfig.packagerConfig.ignore !== 'function') {
console.error(
chalk.red(`You have set packagerConfig.ignore, the Electron Forge Vite plugin normally sets this automatically.
Your packaged app may be larger than expected if you dont ignore everything other than the '.vite' folder`)
);
}
return forgeConfig;
}

const flatDependencies = await getFlatDependencies(this.projectDir);

forgeConfig.packagerConfig.ignore = (file: string) => {
if (!file) return false;

const isViteBuiltFile = /^[/\\]\.vite($|[/\\]).*$/.test(file);
if (isViteBuiltFile) return true;

const isAppRuntimeDeps = flatDependencies.find((dep) => file.startsWith(dep.src));
if (isAppRuntimeDeps) return true;

return false;
};
return forgeConfig;
};

packageAfterCopy = async (_forgeConfig: ResolvedForgeConfig, buildPath: string): Promise<void> => {
const pj = await fs.readJson(path.resolve(this.projectDir, 'package.json'));

if (!/^(.\/)?.vite\//.test(pj.main)) {
throw new Error(`Electron Forge is configured to use the Vite plugin. The plugin expects the
"main" entry point in "package.json" to be ".vite/*" (where the plugin outputs
the generated files). Instead, it is ${JSON.stringify(pj.main)}`);
}

if (pj.config) {
delete pj.config.forge;
}

await fs.writeJson(path.resolve(buildPath, 'package.json'), pj, {
spaces: 2,
});

// TODO: exact node_modules files includes
await fs.copy(path.resolve(this.projectDir, 'node_modules'), path.resolve(buildPath, 'node_modules'));
};

startLogic = async (): Promise<StartResult> => {
if (VitePlugin.alreadyStarted) return false;
VitePlugin.alreadyStarted = true;

await fs.rm(this.baseDir, { recursive: true, force: true });
await fs.remove(this.baseDir);

return {
tasks: [
Expand Down
115 changes: 115 additions & 0 deletions packages/plugin/vite/src/util/package.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import fs from 'node:fs';
import path from 'node:path';

import type { PackageJsonManifest } from './packageJson';

export interface Dependency {
name: string;
path: SourceAndDestination;
dependencies: Dependency[];
}

export interface SourceAndDestination {
src: string;
dest: string;
}

const VOLUME_RE = /^[A-Z]:/i;
export async function lookupNodeModulesPaths(root: string, paths: string[] = []): Promise<string[]> {
if (!root) return paths;
// Linux or Windows absolute path
if (!(root.startsWith('/') || VOLUME_RE.test(root))) return paths;

const p = path.join(root, 'node_modules');

if (fs.existsSync(p) && (await fs.promises.stat(p)).isDirectory()) {
paths = paths.concat(p);
}
root = path.join(root, '..');

return root === '/' || /^[A-Z]:$/i.test(root) // root path
? paths
: await lookupNodeModulesPaths(root, paths);
}

export async function readPackageJson(root = process.cwd()): Promise<PackageJsonManifest> {
const packageJsonPath = path.join(root, 'package.json');
try {
const packageJsonStr = await fs.promises.readFile(packageJsonPath, 'utf8');
try {
return JSON.parse(packageJsonStr);
} catch (error) {
console.error(`parse 'package.json': ${packageJsonPath}`);
throw error;
}
} catch (error) {
console.error(`'package.json' not found: ${packageJsonPath}`);
throw error;
}
}

export async function resolveDependencies(root: string) {
const rootDependencies = Object.keys((await readPackageJson(root)).dependencies || {});
const resolve = async (prePath: string, dependencies: string[], collected: Map<string, Dependency> = new Map()) =>
await Promise.all(
dependencies.map(async (name) => {
let curPath = prePath,
depPath = null,
packageJson = null;
while (!packageJson && root.length <= curPath.length) {
const allNodeModules = await lookupNodeModulesPaths(curPath);

for (const nodeModules of allNodeModules) {
depPath = path.join(nodeModules, name);
if (fs.existsSync(depPath)) break;
}

if (depPath) {
try {
packageJson = await readPackageJson(depPath);
} catch (err) {
// lookup node_modules
curPath = path.join(curPath, '..');
if (curPath.length < root.length) {
console.error(`not found 'node_modules' in root path: ${root}`);
throw err;
}
}
}
}

if (!depPath || !packageJson) {
throw new Error(`find dependencies error in: ${curPath}`);
}

const result: Dependency = {
name,
path: {
src: depPath,
dest: path.relative(root, depPath),
},
dependencies: [],
};
const shouldResolveDeps = !collected.has(depPath);
collected.set(depPath, result);
if (shouldResolveDeps) {
result.dependencies = await resolve(depPath, Object.keys(packageJson.dependencies || {}), collected);
}
return result;
})
);
return resolve(root, rootDependencies);
}

export async function getFlatDependencies(root = process.cwd()) {
const dpesTree = await resolveDependencies(root);
const collected: SourceAndDestination[] = [];

const flatten = (dep: Dependency) => {
collected.push(dep.path);
dep.dependencies.forEach(flatten);
};
dpesTree.forEach(flatten);

return collected;
}
45 changes: 45 additions & 0 deletions packages/plugin/vite/src/util/packageJson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
export interface Person {
name: string;
url?: string;
email?: string;
}

export interface PackageJsonManifest {
// mandatory (npm)
name: string;
version: string;
engines: { [name: string]: string };

// optional (npm)
author?: string | Person;
displayName?: string;
description?: string;
keywords?: string[];
categories?: string[];
homepage?: string;
bugs?: string | { url?: string; email?: string };
license?: string;
contributors?: string | Person[];
main?: string;
browser?: string;
repository?: string | { type?: string; url?: string };
scripts?: { [name: string]: string };
dependencies?: { [name: string]: string };
devDependencies?: { [name: string]: string };
private?: boolean;
pricing?: string;

// not supported (npm)
// files?: string[];
// bin
// man
// directories
// config
// peerDependencies
// bundledDependencies
// optionalDependencies
// os?: string[];
// cpu?: string[];
// preferGlobal
// publishConfig
}
Loading

0 comments on commit 7560f15

Please sign in to comment.