perf(build): optimize build speed and parallelize asset copying

This commit is contained in:
Sehoon Shon
2026-03-25 03:19:07 -04:00
parent 73526416cf
commit 31d31576f9
15 changed files with 85 additions and 47 deletions
+3
View File
@@ -32,6 +32,9 @@
"docs:settings": "tsx ./scripts/generate-settings-doc.ts",
"docs:keybindings": "tsx ./scripts/generate-keybindings-doc.ts",
"build": "node scripts/build.js",
"build:assets": "npm run copy:assets --workspaces --if-present",
"build:clients": "npm run build:client --workspaces --if-present",
"build:devs": "npm run build:dev --workspaces --if-present",
"build-and-start": "npm run build && npm run start --",
"build:vscode": "node scripts/build_vscode_companion.js",
"build:all": "npm run build && npm run build:sandbox && npm run build:vscode",
+2 -1
View File
@@ -13,7 +13,8 @@
"gemini-cli-a2a-server": "dist/a2a-server.mjs"
},
"scripts": {
"build": "node ../../scripts/build_package.js",
"copy:assets": "node ../../scripts/copy_files.js",
"build": "tsc -b && npm run copy:assets",
"start": "node dist/src/http/server.js",
"lint": "eslint . --ext .ts,.tsx",
"format": "prettier --write .",
+2 -1
View File
@@ -13,7 +13,8 @@
"gemini": "dist/index.js"
},
"scripts": {
"build": "node ../../scripts/build_package.js",
"copy:assets": "node ../../scripts/copy_files.js",
"build": "tsc -b && npm run copy:assets",
"start": "node dist/index.js",
"debug": "node --inspect-brk dist/index.js",
"lint": "eslint . --ext .ts,.tsx",
+1
View File
@@ -2,6 +2,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"composite": true,
"jsx": "react-jsx",
"lib": ["DOM", "DOM.Iterable", "ES2023"],
"types": ["node", "vitest/globals"]
+2 -1
View File
@@ -11,7 +11,8 @@
"main": "dist/index.js",
"scripts": {
"bundle:browser-mcp": "node scripts/bundle-browser-mcp.mjs",
"build": "node ../../scripts/build_package.js",
"copy:assets": "node ../../scripts/copy_files.js",
"build": "tsc -b && npm run copy:assets",
"lint": "eslint . --ext .ts,.tsx",
"format": "prettier --write .",
"test": "vitest run",
+2 -1
View File
@@ -12,7 +12,8 @@
}
},
"scripts": {
"build": "npm run build:client && tsc -p tsconfig.build.json",
"copy:assets": "node ../../scripts/copy_files.js",
"build": "npm run build:client && tsc -b tsconfig.build.json && npm run copy:assets",
"build:client": "node esbuild.client.js"
},
"files": [
+2 -2
View File
@@ -2,11 +2,11 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist/src",
"composite": true,
"declaration": true,
"sourceMap": true,
"noEmit": false,
"composite": false,
"incremental": false,
"incremental": true,
"verbatimModuleSyntax": false
},
"include": ["src"]
+2 -1
View File
@@ -11,7 +11,8 @@
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "node ../../scripts/build_package.js",
"copy:assets": "node ../../scripts/copy_files.js",
"build": "tsc -b && npm run copy:assets",
"lint": "eslint . --ext .ts,.tsx",
"format": "prettier --write .",
"test": "vitest run",
+2 -1
View File
@@ -6,7 +6,8 @@
"license": "Apache-2.0",
"type": "module",
"scripts": {
"build": "node ../../scripts/build_package.js",
"copy:assets": "node ../../scripts/copy_files.js",
"build": "tsc -b && npm run copy:assets",
"typecheck": "tsc --noEmit"
},
"dependencies": {
+5 -3
View File
@@ -106,14 +106,16 @@
"main": "./dist/extension.cjs",
"type": "module",
"scripts": {
"prepackage": "npm run generate:notices && npm run check-types && npm run lint && npm run build:prod",
"build": "npm run build:dev",
"build:dev": "npm run check-types && npm run lint && node esbuild.js",
"prepackage": "npm run generate:notices && npm run validate && npm run build:prod",
"copy:assets": "node ../../scripts/copy_files.js",
"build": "npm run build:dev && npm run copy:assets",
"build:dev": "node esbuild.js",
"build:prod": "node esbuild.js --production",
"generate:notices": "node ./scripts/generate-notices.js",
"prepare": "npm run generate:notices",
"check-types": "tsc --noEmit",
"lint": "eslint src",
"validate": "npm run check-types && npm run lint",
"watch": "npm-run-all2 -p watch:*",
"watch:esbuild": "node esbuild.js --watch",
"watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
+3 -6
View File
@@ -5,12 +5,9 @@
"target": "ES2022",
"lib": ["ES2022", "dom"],
"sourceMap": true,
/*
* skipLibCheck is necessary because the a2a-server package depends on
* @google-cloud/storage which pulls in @types/request which depends on
* tough-cookie@4.x while jsdom requires tough-cookie@5.x. This causes a
* type checking error in ../../node_modules/@types/request/index.d.ts.
*/
"composite": true,
"declaration": true,
"incremental": true,
"skipLibCheck": true,
"rootDir": "src",
"strict": true /* enable all strict type-checking options */
+25 -2
View File
@@ -18,7 +18,7 @@
// limitations under the License.
import { execSync } from 'node:child_process';
import { existsSync } from 'node:fs';
import { existsSync, writeFileSync, readdirSync, statSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
@@ -31,8 +31,19 @@ if (!existsSync(join(root, 'node_modules'))) {
}
// build all workspaces/packages
console.log('Generating commit info...');
execSync('npm run generate', { stdio: 'inherit', cwd: root });
execSync('npm run build --workspaces', { stdio: 'inherit', cwd: root });
console.log('Building TypeScript packages (incremental)...');
execSync('npx tsc -b', { stdio: 'inherit', cwd: root });
console.log(
'Running asset copy and package-specific build steps in parallel...',
);
execSync('npx npm-run-all --parallel build:assets build:clients build:devs', {
stdio: 'inherit',
cwd: root,
});
// also build container image if sandboxing is enabled
// skip (-s) npm install + build since we did that above
@@ -53,3 +64,15 @@ try {
} catch {
// ignore
}
// Final step: update the .last_build timestamp for all packages to ensure
// they are newer than any files modified during the build (like git-commit.ts).
console.log('Updating build timestamps...');
const packagesDir = join(root, 'packages');
const packages = readdirSync(packagesDir);
for (const pkg of packages) {
const distDir = join(packagesDir, pkg, 'dist');
if (existsSync(distDir) && statSync(distDir).isDirectory()) {
writeFileSync(join(distDir, '.last_build'), '');
}
}
+15 -27
View File
@@ -18,41 +18,29 @@
// limitations under the License.
import { execSync } from 'node:child_process';
import { writeFileSync, existsSync, cpSync } from 'node:fs';
import { join, basename } from 'node:path';
import { writeFileSync, existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
if (!process.cwd().includes('packages')) {
console.error('must be invoked from a package directory');
process.exit(1);
}
const packageName = basename(process.cwd());
// build typescript files incrementally
execSync('tsc -b', { stdio: 'inherit' });
// build typescript files
execSync('tsc --build', { stdio: 'inherit' });
// Run package-specific bundling if the script exists
const bundleScript = join(process.cwd(), 'scripts', 'bundle-browser-mcp.mjs');
if (packageName === 'core' && existsSync(bundleScript)) {
console.log('Running chrome devtools MCP bundling...');
execSync('npm run bundle:browser-mcp', {
stdio: 'inherit',
});
}
// copy .{md,json} files
execSync('node ../../scripts/copy_files.js', { stdio: 'inherit' });
// Copy documentation for the core package
if (packageName === 'core') {
const docsSource = join(process.cwd(), '..', '..', 'docs');
const docsTarget = join(process.cwd(), 'dist', 'docs');
if (existsSync(docsSource)) {
cpSync(docsSource, docsTarget, { recursive: true, dereference: true });
console.log('Copied documentation to dist/docs');
}
// Check for copy:assets script in package.json
const packageJson = JSON.parse(readFileSync('package.json', 'utf8'));
if (packageJson.scripts && packageJson.scripts['copy:assets']) {
execSync('npm run copy:assets', { stdio: 'inherit' });
} else {
// fallback to generic copy
execSync('node ../../scripts/copy_files.js', { stdio: 'inherit' });
}
// touch dist/.last_build
writeFileSync(join(process.cwd(), 'dist', '.last_build'), '');
const distDir = join(process.cwd(), 'dist');
if (existsSync(distDir)) {
writeFileSync(join(distDir, '.last_build'), '');
}
process.exit(0);
+8
View File
@@ -81,6 +81,14 @@ if (packageName === 'core') {
if (fs.existsSync(builtinSkillsSource)) {
fs.cpSync(builtinSkillsSource, builtinSkillsTarget, { recursive: true });
}
// Copy documentation for the core package
const docsSource = path.join(process.cwd(), '..', '..', 'docs');
const docsTarget = path.join(process.cwd(), 'dist', 'docs');
if (fs.existsSync(docsSource)) {
fs.cpSync(docsSource, docsTarget, { recursive: true, dereference: true });
console.log('Copied documentation to dist/docs');
}
}
console.log('Successfully copied files.');
+11 -1
View File
@@ -27,5 +27,15 @@
"target": "es2022",
"types": ["node", "vitest/globals"],
"jsx": "react-jsx"
}
},
"files": [],
"references": [
{ "path": "packages/core" },
{ "path": "packages/cli" },
{ "path": "packages/sdk" },
{ "path": "packages/a2a-server" },
{ "path": "packages/test-utils" },
{ "path": "packages/devtools/tsconfig.build.json" },
{ "path": "packages/vscode-ide-companion" }
]
}