@silverassist/performance-toolkit
v0.3.1
Published
PageSpeed Insights and Lighthouse CI integration for performance monitoring across SilverAssist projects
Maintainers
Readme
@silverassist/performance-toolkit
PageSpeed Insights and Lighthouse CI integration for performance monitoring across SilverAssist projects.
Features
- ✅ PageSpeed Insights API v5 - Full API integration with CrUX data
- ✅ Lighthouse CI - Programmatic LHCI with node/psi methods
- ✅ Bundle Analysis - Next.js bundle size analysis with @next/bundle-analyzer
- ✅ Core Web Vitals - LCP, FCP, CLS, TBT extraction
- ✅ LCP Element Detection - Identify the LCP element
- ✅ Opportunities & Diagnostics - Performance improvement suggestions
- ✅ Actionable Reports - Framework-aware optimization recommendations
- ✅ Project Context Detection - Auto-detect Next.js, React, Vue, etc.
- ✅ Export Pattern Analyzer - Optimize tree-shaking with named exports
- ✅ CLI Tool - Command-line interface for quick analysis
- ✅ Copilot Prompts & Skills - Pre-built AI workflows for performance optimization
- ✅ TypeScript - Full type definitions with subpath exports
Installation
npm install @silverassist/performance-toolkit
performance-toolkityarn add @silverassist/performance-toolkitpnpm add @silverassist/performance-toolkitQuick Start
PageSpeed Insights API
import { analyzeUrl } from "@silverassist/performance-toolkit";
const result = await analyzeUrl("https://www.example.com", {
strategy: "mobile",
apiKey: process.env.PAGESPEED_API_KEY,
});
console.log("Performance Score:", result.scores.performance);
console.log("LCP:", result.metrics.lcp.displayValue);
console.log("CLS:", result.metrics.cls.displayValue);Lighthouse CI Integration
import { createPSIRunner, getDefaultThresholds } from "@silverassist/performance-toolkit";
// Production URLs - use PSI method (consistent hardware)
const runner = createPSIRunner(
["https://www.example.com/care-type"],
process.env.PAGESPEED_API_KEY
)
.withAssertions(getDefaultThresholds())
.withTemporaryStorage();
const exitCode = await runner.run();Staging/Internal URLs
import { createNodeRunner } from "@silverassist/performance-toolkit";
// Staging URLs - use node method (local Chrome)
const runner = createNodeRunner([
"https://staging.example.com/care-type",
]).withAssertions({
performance: 50,
lcp: 4000,
fcp: 3000,
});
const exitCode = await runner.run();CLI Usage
# Basic analysis
perf-check https://www.example.com
# Desktop strategy with verbose output
perf-check https://www.example.com --desktop --verbose
# Audit export patterns for tree-shaking
perf-check --audit-exports
# CI mode (exit code 1 on failures)
perf-check https://www.example.com --ci --output results.jsonCLI Options
| Option | Alias | Description |
|--------|-------|-------------|
| --mobile | -m | Use mobile strategy (default) |
| --desktop | -d | Use desktop strategy |
| --verbose | -v | Show detailed output including opportunities |
| --insights | -i | Show all detailed insights (for AI agents) |
| --diagnostics | | Show diagnostics table (PageSpeed format) |
| --actionable | -a | Generate actionable report with key opportunities |
| --detect-context | | Detect project technology stack |
| --audit-exports | | Analyze export patterns for tree-shaking |
| --json | -j | Output structured JSON (for programmatic use) |
| --ci | | CI mode (exit with error on violations) |
| --output | -o | Output results to JSON file |
| --baseline | -b | Compare against baseline file |
| --config | -c | Path to configuration file |
| --help | -h | Show help message |
Bundle Analysis
Analyze Next.js bundle size and composition using @next/bundle-analyzer. This feature helps identify large dependencies, unused code, and optimization opportunities to reduce JavaScript bundle sizes.
Quick Start
# Analyze current Next.js project
perf-bundle
# Analyze specific project with auto-install
perf-bundle /path/to/nextjs-project --auto-install
# Generate reports and open in browser
perf-bundle --open --auto-installBundle Analysis Options
| Option | Description |
|--------|-------------|
| project-path | Path to Next.js project directory (default: current directory) |
| --auto-install | Automatically install @next/bundle-analyzer if missing |
| --open | Open HTML reports in browser after analysis |
| --help, -h | Show help message |
How It Works
The perf-bundle command:
- Detects Next.js Project: Verifies the project is a Next.js application
- Checks Dependencies: Looks for
@next/bundle-analyzerin package.json - Auto-Install (Optional): Installs the analyzer if
--auto-installflag is provided - Injects Configuration: Temporarily adds bundle analyzer to next.config
- Runs Build: Executes
ANALYZE=true npm run build - Generates Reports: Creates interactive HTML visualizations in
.next/analyze/ - Restores Config: Automatically restores original next.config file
Generated Reports
Reports are created in .next/analyze/ directory:
- client.html: Client-side JavaScript bundle breakdown
- server.html: Server-side bundle composition (if SSR is used)
- edge.html: Edge runtime bundles (if edge runtime is used)
Each report shows:
- Bundle size (parsed vs gzipped)
- Dependency tree visualization
- Package-by-package breakdown
- Module composition
Integration with Performance Analysis
When perf-check identifies "Reduce unused JavaScript" opportunities, use perf-bundle to discover which specific dependencies are causing bloat:
# 1. Run performance check
perf-check https://your-site.com --insights
# 2. If "Unused JavaScript" is flagged, analyze bundle
perf-bundle --auto-install
# 3. Review generated reports to identify optimization targets
open .next/analyze/client.htmlProgrammatic Usage
import { analyzeBundle } from "@silverassist/performance-toolkit";
const result = await analyzeBundle({
projectPath: "/path/to/nextjs-project",
autoInstall: true,
});
if (result.success) {
console.log("Reports:", result.reports);
console.log("Summary:", result.summary);
} else {
console.error("Error:", result.error);
}Note: The openBrowser option is only available via the CLI. For programmatic usage, handle report opening in your own code using the returned result.reports paths.
Best Practices
- Regular Analysis: Run bundle analysis before major releases
- Set Budgets: Establish bundle size budgets for your project
- Monitor Trends: Track bundle size over time in CI/CD
- Review Dependencies: Regularly audit large dependencies for lighter alternatives
- Code Splitting: Use dynamic imports for heavy components identified in reports
Troubleshooting
"Not a Next.js project" error:
- Ensure
package.jsoncontainsnextin dependencies
Build fails during analysis:
- Check that your Next.js project builds successfully without the analyzer
- Verify all dependencies are installed (
npm install)
No reports generated:
- Check
.next/analyze/directory exists - Ensure build completed successfully
AI Agent Usage
The toolkit provides detailed, structured insights that AI agents (like GitHub Copilot) can use to identify performance optimization opportunities and propose specific code changes.
# Get detailed insights in terminal format
perf-check https://www.example.com --insights
# Get machine-readable JSON for programmatic analysis
perf-check https://www.example.com --json > report.jsonThe --insights flag shows:
- LCP Timing Breakdown: TTFB, resource load delay, render delay
- Third-Party Impact: Blocking time and transfer size per vendor
- Unused JavaScript: Wasted bytes with first-party/third-party attribution
- Unused CSS: Stylesheets with coverage analysis
- Cache Policy Issues: Resources with poor or missing cache headers
- Image Optimization: Format, sizing, and lazy-loading opportunities
- Legacy JavaScript: Polyfills that can be removed
- Render-Blocking Resources: Scripts/styles delaying first paint
- Long Tasks: Main-thread blocking tasks with attribution
Example workflow for AI agents:
# 1. Generate structured report
perf-check https://example.com --json > perf-report.json
# 2. AI agent reads the report and identifies issues
# 3. AI agent proposes code changes based on insights.unusedJavaScript, etc.GitHub Copilot Prompts
The toolkit includes pre-built prompts for GitHub Copilot that provide structured workflows for performance optimization.
Install prompts:
# Create symlink to prompts (recommended - auto-updates with package)
npx perf-prompts install
# Or copy files instead (if you want to customize)
npx perf-prompts install --copy
# Check installation status
npx perf-prompts status
# Remove prompts
npx perf-prompts uninstallAvailable prompts:
| Prompt | Description |
|--------|-------------|
| analyze-performance | Full performance analysis with actionable report |
| optimize-lcp | LCP optimization with Next.js streaming-aware patterns |
| optimize-bundle | JavaScript bundle analysis and code splitting |
| nextjs-performance | Next.js App Router specific optimizations |
| detect-context | Detect project technology stack |
| performance-audit | Complete multi-phase audit |
Usage in VS Code:
@workspace /performance/analyze-performance https://your-site.com
@workspace /performance/optimize-lcp
@workspace /performance/nextjs-performanceWhy symlinks? Symlinks ensure prompts stay up-to-date automatically when you update the package. If you need to customize prompts, use --copy instead.
Agent Skills
Agent Skills are auto-loaded by GitHub Copilot based on context relevance (requires chat.useAgentSkills setting in VS Code).
| Skill | Description |
|-------|-------------|
| nextjs-performance | Next.js App Router performance patterns |
| web-performance-analysis | General web performance optimization |
| gtm-optimization | Google Tag Manager/GA4 performance optimization |
| nextjs-tree-shaking | Tree-shaking optimization with named exports |
Skills are installed automatically with npx perf-prompts install.
API Reference
analyzeUrl(url, options)
Analyze a single URL using PageSpeed Insights API.
interface PageSpeedOptions {
url: string;
strategy?: "mobile" | "desktop";
categories?: ("performance" | "accessibility" | "best-practices" | "seo")[];
apiKey?: string;
timeout?: number;
}PageSpeedClient
Full client for multiple analyses:
import { PageSpeedClient } from "@silverassist/performance-toolkit";
const client = new PageSpeedClient(process.env.PAGESPEED_API_KEY);
// Analyze both strategies
const { mobile, desktop } = await client.analyzeAll(
"https://www.example.com"
);LighthouseRunner
Programmatic Lighthouse CI:
import { LighthouseRunner } from "@silverassist/performance-toolkit";
const runner = new LighthouseRunner({
urls: ["https://example.com"],
method: "psi", // or "node"
psiApiKey: process.env.PAGESPEED_API_KEY,
numberOfRuns: 3,
});
// Add assertions
runner.withAssertions({
performance: 90,
lcp: 2500,
cls: 0.1,
});
// Configure upload
runner.withTemporaryStorage();
// or
runner.withLHCIServer("https://lhci.example.com", "build-token");
// Run
const exitCode = await runner.run();getDefaultThresholds(strict?)
Get recommended thresholds:
import { getDefaultThresholds } from "@silverassist/performance-toolkit";
// Standard thresholds
const standard = getDefaultThresholds();
// { performance: 50, lcp: 4000, fcp: 3000, cls: 0.25, tbt: 600 }
// Strict thresholds
const strict = getDefaultThresholds(true);
// { performance: 90, lcp: 2500, fcp: 1800, cls: 0.1, tbt: 200 }detectProjectContext()
Detect the project's technology stack:
import { detectProjectContext } from "@silverassist/performance-toolkit";
const context = await detectProjectContext();
console.log(context.framework); // { name: "Next.js", version: "14.2.0" }
console.log(context.isSSR); // true
console.log(context.hasAppDir); // trueanalyzeExports(options?)
Analyze module export patterns for tree-shaking optimization:
import { analyzeExports } from "@silverassist/performance-toolkit";
const analysis = await analyzeExports({
projectRoot: process.cwd(),
includeDirs: ["src", "app", "components"],
analyzeNextConfig: true,
});
console.log(analysis.summary);
// {
// totalFiles: 127,
// defaultExportFiles: 15,
// namedExportFiles: 112,
// problematicBarrelFiles: 3
// }
// Get recommendations
analysis.recommendations.forEach(rec => {
console.log(`${rec.priority}: ${rec.title}`);
console.log(`Impact: ${rec.impact.bundleSize}`);
});Analysis includes:
- Default vs named export detection
- Barrel file pattern analysis (
index.tsre-exports) next.config.jsoptimizePackageImportsconfiguration- Actionable recommendations with code examples
- Estimated bundle size impact
generateActionableReport(result, context?)
Generate an actionable report with framework-specific recommendations:
import { analyzeUrl, generateActionableReport, detectProjectContext } from "@silverassist/performance-toolkit";
const result = await analyzeUrl("https://example.com");
const context = await detectProjectContext();
const report = generateActionableReport(result, context);
console.log(report.keyOpportunities); // Top 3 prioritized opportunities
console.log(report.lcpAnalysis); // LCP breakdown and recommendations
console.log(report.nextSteps); // Prioritized action itemsanalyzeBundle(options?)
Analyze Next.js bundle size and composition:
import { analyzeBundle } from "@silverassist/performance-toolkit";
const result = await analyzeBundle({
projectPath: "/path/to/nextjs-project",
autoInstall: true,
});
if (result.success) {
console.log("Client bundle:", result.reports?.client);
console.log("Recommendations:", result.summary?.recommendations);
} else {
console.error("Analysis failed:", result.error);
}BundleAnalyzerRunner
Full control over bundle analysis with logging callbacks:
import { BundleAnalyzerRunner } from "@silverassist/performance-toolkit";
const runner = new BundleAnalyzerRunner({
projectPath: process.cwd(),
autoInstall: true,
});
// Set up logging (optional)
runner.setLogCallback((msg) => console.log(msg));
runner.setErrorCallback((msg) => console.error(msg));
const result = await runner.analyze();Performance Result
interface PerformanceResult {
url: string;
strategy: "mobile" | "desktop";
timestamp: string;
scores: {
performance: number | null;
accessibility: number | null;
bestPractices: number | null;
seo: number | null;
};
metrics: {
lcp: MetricValue;
fcp: MetricValue;
cls: MetricValue;
tbt: MetricValue;
si: MetricValue;
tti: MetricValue;
};
lcpElement?: {
tagName: string;
selector: string;
url?: string;
};
opportunities: Opportunity[];
diagnostics: Diagnostic[];
fieldData?: LoadingExperience;
}Environment Variables
| Variable | Description |
|----------|-------------|
| PAGESPEED_API_KEY | Google PageSpeed Insights API key |
Get your API key at: https://developers.google.com/speed/docs/insights/v5/get-started
Local Development
The CLI automatically loads .env.local or .env files from the current directory:
# .env.local
PAGESPEED_API_KEY=your-api-key-hereThen simply run:
perf-check https://www.example.com --insightsCI/CD Integration
GitHub Actions
name: Performance Check
on: [push, pull_request]
jobs:
performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run Performance Check
env:
PAGESPEED_API_KEY: ${{ secrets.PAGESPEED_API_KEY }}
run: npx perf-check https://www.example.com --ciBitbucket Pipelines
pipelines:
default:
- step:
name: Performance Check
script:
- npm ci
- npx perf-check https://www.example.com --ci
# Set PAGESPEED_API_KEY in Repository Settings > Pipelines > Environment variablesCore Web Vitals Thresholds
Based on Google's guidelines:
| Metric | Good | Needs Improvement | Poor | |--------|------|-------------------|------| | LCP | < 2.5s | 2.5s - 4s | > 4s | | FCP | < 1.8s | 1.8s - 3s | > 3s | | CLS | < 0.1 | 0.1 - 0.25 | > 0.25 | | TBT | < 200ms | 200ms - 600ms | > 600ms |
TypeScript
Full TypeScript support with exported types:
import type {
CoreWebVitals,
MetricValue,
PerformanceResult,
PageSpeedOptions,
LHCIOptions,
PerformanceThresholds,
BundleAnalyzerOptions,
BundleAnalysisResult,
ExportAnalyzerOptions,
ExportAnalysisResult,
ProjectContext,
ActionableReport,
} from "@silverassist/performance-toolkit";Subpath Exports
Import specific modules for smaller bundle size:
// PageSpeed module only
import { PageSpeedClient, analyzeUrl } from "@silverassist/performance-toolkit/pagespeed";
// Lighthouse module only
import { LighthouseRunner, createPSIRunner } from "@silverassist/performance-toolkit/lighthouse";
// Bundle module only
import { BundleAnalyzerRunner, analyzeBundle } from "@silverassist/performance-toolkit/bundle";
// Export analyzer module only
import { ExportAnalyzer, analyzeExports } from "@silverassist/performance-toolkit/analyzer";
// Context detection module only
import { ProjectContextDetector, detectProjectContext } from "@silverassist/performance-toolkit/context";
// Report generation module only
import { ActionableReportGenerator, generateActionableReport } from "@silverassist/performance-toolkit/report";
// Types only (no runtime code)
import type { PerformanceResult, CoreWebVitals, ExportAnalysisResult } from "@silverassist/performance-toolkit/types";Development
# Install dependencies
npm install
# Build
npm run build
# Test
npm test
# Type check
npm run typecheck
# Lint
npm run lintLicense
PolyForm Noncommercial License 1.0.0
Links
Made with ❤️ by Silver Assist
