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 86c0745
Show file tree
Hide file tree
Showing 5 changed files with 351 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.includes(dep.dest));
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
116 changes: 116 additions & 0 deletions packages/plugin/vite/src/util/package.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
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;
}

function isRootDirectory(dir: string) {
// Linux or Windows root path
return dir === '/' || /^[A-Z]:$/i.test(dir);
}

export async function lookupNodeModulesPaths(root: string, paths: string[] = []): Promise<string[]> {
if (!root) return paths;
if (!path.isAbsolute(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 isRootDirectory(root) ? 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 && !isRootDirectory(curPath)) {
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 depsFlat = new Map<string, SourceAndDestination>();

const flatten = (dep: Dependency) => {
depsFlat.set(dep.path.src, dep.path); // dedup
dep.dependencies.forEach(flatten);
};
dpesTree.forEach(flatten);

return [...depsFlat.values()];
}
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 86c0745

Please sign in to comment.