Initial commit
This commit is contained in:
383
skills/mcp-chrome-devtools/workflows/performance-analysis.md
Normal file
383
skills/mcp-chrome-devtools/workflows/performance-analysis.md
Normal file
@@ -0,0 +1,383 @@
|
||||
# Performance Analysis Workflows
|
||||
|
||||
Advanced tools for JavaScript execution, performance tracing, device emulation, and automation utilities.
|
||||
|
||||
## Tools in This Group
|
||||
|
||||
### evaluate_script
|
||||
Executes JavaScript code in the page context and returns JSON-serializable results.
|
||||
|
||||
**Required:** `--function FUNCTION_STRING`
|
||||
**Optional:** `--args JSON_ARRAY`
|
||||
|
||||
```bash
|
||||
# Simple extraction
|
||||
node scripts/evaluate_script.js --function "() => document.title"
|
||||
|
||||
# With parameters
|
||||
node scripts/evaluate_script.js --function "(x, y) => x + y" --args '[5, 3]'
|
||||
|
||||
# Complex extraction
|
||||
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('h2')).map(h => h.textContent)"
|
||||
```
|
||||
|
||||
### wait_for
|
||||
Waits for specific text to appear on the page (for dynamic content loading).
|
||||
|
||||
**Required:** `--text TEXT`
|
||||
**Optional:** `--timeout MILLISECONDS`
|
||||
|
||||
```bash
|
||||
# Wait up to 10 seconds
|
||||
node scripts/wait_for.js --text "Loading complete" --timeout 10000
|
||||
|
||||
# Wait for error message
|
||||
node scripts/wait_for.js --text "Error" --timeout 5000
|
||||
```
|
||||
|
||||
### handle_dialog
|
||||
Handles browser dialogs (alert, confirm, prompt).
|
||||
|
||||
**Required:** `--action [accept|dismiss]`
|
||||
**Optional:** `--promptText TEXT`
|
||||
|
||||
```bash
|
||||
# Accept alert
|
||||
node scripts/handle_dialog.js --action accept
|
||||
|
||||
# Dismiss confirm
|
||||
node scripts/handle_dialog.js --action dismiss
|
||||
|
||||
# Accept prompt with text
|
||||
node scripts/handle_dialog.js --action accept --promptText "User input"
|
||||
```
|
||||
|
||||
### emulate
|
||||
Emulates network conditions and CPU throttling.
|
||||
|
||||
**Optional:** `--networkConditions JSON`, `--cpuThrottlingRate NUMBER`
|
||||
|
||||
```bash
|
||||
# Slow 3G network
|
||||
node scripts/emulate.js --networkConditions '{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'
|
||||
|
||||
# 4x CPU throttling
|
||||
node scripts/emulate.js --cpuThrottlingRate 4
|
||||
|
||||
# Both
|
||||
node scripts/emulate.js --networkConditions '{"downloadThroughput":100000,"uploadThroughput":50000,"latency":100}' --cpuThrottlingRate 2
|
||||
```
|
||||
|
||||
### performance_start_trace
|
||||
Starts recording performance trace for Core Web Vitals and performance insights.
|
||||
|
||||
**Required:** `--reload [true|false]`, `--autoStop [true|false]`
|
||||
|
||||
```bash
|
||||
# Start tracing with page reload
|
||||
node scripts/performance_start_trace.js --reload true --autoStop false
|
||||
|
||||
# Start tracing without reload
|
||||
node scripts/performance_start_trace.js --reload false --autoStop true
|
||||
```
|
||||
|
||||
### performance_stop_trace
|
||||
Stops the active performance trace and returns results.
|
||||
|
||||
```bash
|
||||
node scripts/performance_stop_trace.js
|
||||
```
|
||||
|
||||
**Output includes:**
|
||||
- Core Web Vitals: LCP, FID, CLS scores
|
||||
- Performance insights and recommendations
|
||||
- Insight set IDs for detailed analysis
|
||||
|
||||
### performance_analyze_insight
|
||||
Gets detailed information about a specific performance insight.
|
||||
|
||||
**Required:** `--insightSetId SET_ID`, `--insightName INSIGHT_NAME`
|
||||
|
||||
```bash
|
||||
node scripts/performance_analyze_insight.js --insightSetId set_abc123 --insightName LargestContentfulPaint
|
||||
```
|
||||
|
||||
## Workflows
|
||||
|
||||
### Workflow: Extract Structured Data
|
||||
|
||||
Scrape data from pages using JavaScript:
|
||||
|
||||
- [ ] Open page: `node scripts/new_page.js --url https://example.com/products`
|
||||
- [ ] Wait for load: `node scripts/wait_for.js --text "Products" --timeout 10000`
|
||||
- [ ] Extract product titles:
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.product-title')).map(el => el.textContent)"
|
||||
```
|
||||
- [ ] Extract product prices:
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.product-price')).map(el => el.textContent)"
|
||||
```
|
||||
- [ ] Extract complete product data:
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.product')).map(p => ({title: p.querySelector('.title').textContent, price: p.querySelector('.price').textContent, id: p.dataset.id}))"
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
Structured JSON data extracted from page, ready for processing.
|
||||
|
||||
### Workflow: Comprehensive Performance Analysis
|
||||
|
||||
Measure page performance and Core Web Vitals:
|
||||
|
||||
- [ ] Open page: `node scripts/new_page.js --url https://example.com/landing`
|
||||
- [ ] Start trace with reload: `node scripts/performance_start_trace.js --reload true --autoStop false`
|
||||
- [ ] Wait for page load: `node scripts/wait_for.js --text "Get Started" --timeout 20000`
|
||||
- [ ] Interact with page: `node scripts/click.js --uid button_cta`
|
||||
- [ ] Wait for interaction: `node scripts/wait_for.js --text "Form" --timeout 5000`
|
||||
- [ ] Stop trace: `node scripts/performance_stop_trace.js`
|
||||
- [ ] Review output for:
|
||||
- LCP (Largest Contentful Paint) - should be < 2.5s
|
||||
- FID (First Input Delay) - should be < 100ms
|
||||
- CLS (Cumulative Layout Shift) - should be < 0.1
|
||||
- Performance insights list
|
||||
- [ ] Analyze specific insight: `node scripts/performance_analyze_insight.js --insightSetId <set-id> --insightName LargestContentfulPaint`
|
||||
|
||||
**Expected Output:**
|
||||
Full performance profile, CWV scores, actionable insights for optimization.
|
||||
|
||||
### Workflow: Test Under Network Constraints
|
||||
|
||||
Simulate slow connections:
|
||||
|
||||
- [ ] Set up slow 3G: `node scripts/emulate.js --networkConditions '{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'`
|
||||
- [ ] Open page: `node scripts/new_page.js --url https://example.com --timeout 60000`
|
||||
- [ ] Start performance trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
|
||||
- [ ] Wait for load: `node scripts/wait_for.js --text "Content" --timeout 60000`
|
||||
- [ ] Stop trace: `node scripts/performance_stop_trace.js`
|
||||
- [ ] Review load times: Check trace output for timing metrics
|
||||
- [ ] Screenshot loaded state: `node scripts/take_screenshot.js --filePath slow_3g_loaded.png`
|
||||
- [ ] Reset to fast network: `node scripts/emulate.js --networkConditions '{"downloadThroughput":10000000,"uploadThroughput":10000000,"latency":10}'`
|
||||
|
||||
**Expected Output:**
|
||||
Page behavior under slow network documented, performance impact measured.
|
||||
|
||||
### Workflow: CPU Throttling Test
|
||||
|
||||
Test performance on low-powered devices:
|
||||
|
||||
- [ ] Apply 4x throttling: `node scripts/emulate.js --cpuThrottlingRate 4`
|
||||
- [ ] Open app: `node scripts/new_page.js --url https://example.com/app`
|
||||
- [ ] Start trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
|
||||
- [ ] Interact with heavy UI: `node scripts/click.js --uid button_render_chart`
|
||||
- [ ] Wait for render: `node scripts/wait_for.js --text "Chart loaded" --timeout 30000`
|
||||
- [ ] Stop trace: `node scripts/performance_stop_trace.js`
|
||||
- [ ] Check JavaScript execution time in trace output
|
||||
- [ ] Remove throttling: `node scripts/emulate.js --cpuThrottlingRate 1`
|
||||
- [ ] Repeat test for comparison
|
||||
|
||||
**Expected Output:**
|
||||
Performance comparison between throttled and normal CPU, bottlenecks identified.
|
||||
|
||||
### Workflow: Handle Dynamic Content Loading
|
||||
|
||||
Work with lazy-loaded content:
|
||||
|
||||
- [ ] Open page: `node scripts/new_page.js --url https://example.com/infinite-scroll`
|
||||
- [ ] Wait for initial load: `node scripts/wait_for.js --text "Item 1" --timeout 5000`
|
||||
- [ ] Scroll to bottom: `node scripts/evaluate_script.js --function "() => window.scrollTo(0, document.body.scrollHeight)"`
|
||||
- [ ] Wait for more items: `node scripts/wait_for.js --text "Item 20" --timeout 10000`
|
||||
- [ ] Take snapshot: `node scripts/take_snapshot.js`
|
||||
- [ ] Scroll again: `node scripts/evaluate_script.js --function "() => window.scrollTo(0, document.body.scrollHeight)"`
|
||||
- [ ] Wait for more: `node scripts/wait_for.js --text "Item 40" --timeout 10000`
|
||||
- [ ] Extract all items:
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.item')).length"
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
All lazy-loaded content triggered and captured, full list extracted.
|
||||
|
||||
### Workflow: Automated Dialog Handling
|
||||
|
||||
Automate flows with browser dialogs:
|
||||
|
||||
- [ ] Open page: `node scripts/new_page.js --url https://example.com/confirm-action`
|
||||
- [ ] Click delete button: `node scripts/click.js --uid button_delete`
|
||||
- [ ] Handle confirm dialog: `node scripts/handle_dialog.js --action accept`
|
||||
- [ ] Wait for deletion: `node scripts/wait_for.js --text "Deleted successfully" --timeout 5000`
|
||||
- [ ] Verify: `node scripts/take_snapshot.js`
|
||||
|
||||
**For prompt dialog:**
|
||||
```bash
|
||||
# Click button that opens prompt
|
||||
node scripts/click.js --uid button_rename
|
||||
|
||||
# Enter new name and accept
|
||||
node scripts/handle_dialog.js --action accept --promptText "New Name"
|
||||
|
||||
# Verify change
|
||||
node scripts/wait_for.js --text "New Name" --timeout 3000
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
Browser dialogs handled automatically, flow completes without manual intervention.
|
||||
|
||||
### Workflow: Custom Metrics Collection
|
||||
|
||||
Collect custom performance metrics:
|
||||
|
||||
- [ ] Open page: `node scripts/new_page.js --url https://example.com/dashboard`
|
||||
- [ ] Wait for load: `node scripts/wait_for.js --text "Dashboard" --timeout 10000`
|
||||
- [ ] Get page load time:
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => performance.timing.loadEventEnd - performance.timing.navigationStart"
|
||||
```
|
||||
- [ ] Get resource count:
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => performance.getEntriesByType('resource').length"
|
||||
```
|
||||
- [ ] Get memory usage (if available):
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => performance.memory ? performance.memory.usedJSHeapSize : null"
|
||||
```
|
||||
- [ ] Get paint timings:
|
||||
```bash
|
||||
node scripts/evaluate_script.js --function "() => performance.getEntriesByType('paint').map(p => ({name: p.name, time: p.startTime}))"
|
||||
```
|
||||
|
||||
**Expected Output:**
|
||||
Custom performance metrics collected via Performance API, specific to your needs.
|
||||
|
||||
### Workflow: A/B Test Performance Comparison
|
||||
|
||||
Compare performance across variants:
|
||||
|
||||
- [ ] **Variant A:**
|
||||
- [ ] Open: `node scripts/new_page.js --url https://example.com?variant=a`
|
||||
- [ ] Trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
|
||||
- [ ] Wait: `node scripts/wait_for.js --text "Content" --timeout 15000`
|
||||
- [ ] Stop: `node scripts/performance_stop_trace.js > variant_a_trace.txt`
|
||||
- [ ] Screenshot: `node scripts/take_screenshot.js --filePath variant_a.png`
|
||||
- [ ] **Variant B:**
|
||||
- [ ] Navigate: `node scripts/navigate_page.js --url https://example.com?variant=b`
|
||||
- [ ] Trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
|
||||
- [ ] Wait: `node scripts/wait_for.js --text "Content" --timeout 15000`
|
||||
- [ ] Stop: `node scripts/performance_stop_trace.js > variant_b_trace.txt`
|
||||
- [ ] Screenshot: `node scripts/take_screenshot.js --filePath variant_b.png`
|
||||
- [ ] Compare CWV scores from both trace files
|
||||
|
||||
**Expected Output:**
|
||||
Performance metrics for both variants, data-driven comparison for optimization.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Pattern: Safe Script Evaluation
|
||||
|
||||
Always return JSON-serializable data:
|
||||
|
||||
```bash
|
||||
# Good: Returns string
|
||||
node scripts/evaluate_script.js --function "() => document.title"
|
||||
|
||||
# Good: Returns array of strings
|
||||
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('a')).map(a => a.href)"
|
||||
|
||||
# Bad: Returns DOM nodes (not serializable)
|
||||
# node scripts/evaluate_script.js --function "() => document.querySelectorAll('a')"
|
||||
```
|
||||
|
||||
### Pattern: Wait Before Interaction
|
||||
|
||||
Always wait for dynamic content:
|
||||
|
||||
```bash
|
||||
# 1. Trigger action
|
||||
node scripts/click.js --uid button_load
|
||||
|
||||
# 2. Wait for content
|
||||
node scripts/wait_for.js --text "Loaded" --timeout 10000
|
||||
|
||||
# 3. Now safe to interact
|
||||
node scripts/take_snapshot.js
|
||||
```
|
||||
|
||||
### Pattern: Complete Performance Workflow
|
||||
|
||||
Standard performance analysis sequence:
|
||||
|
||||
```bash
|
||||
# 1. Start tracing
|
||||
node scripts/performance_start_trace.js --reload true --autoStop false
|
||||
|
||||
# 2. Let page load completely
|
||||
node scripts/wait_for.js --text "Ready" --timeout 20000
|
||||
|
||||
# 3. Stop tracing
|
||||
node scripts/performance_stop_trace.js
|
||||
|
||||
# 4. Analyze specific insights
|
||||
node scripts/performance_analyze_insight.js --insightSetId <id> --insightName <name>
|
||||
```
|
||||
|
||||
### Pattern: Emulation Reset
|
||||
|
||||
Reset emulation to normal after testing:
|
||||
|
||||
```bash
|
||||
# 1. Test under constraints
|
||||
node scripts/emulate.js --cpuThrottlingRate 4
|
||||
|
||||
# ... run tests ...
|
||||
|
||||
# 2. Reset to normal
|
||||
node scripts/emulate.js --cpuThrottlingRate 1
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Problem:** evaluate_script returns null or error
|
||||
|
||||
**Solution:**
|
||||
- Ensure function returns JSON-serializable values (no DOM nodes, functions, or circular references)
|
||||
- Use .map() to extract primitive values from DOM elements
|
||||
- Check browser console for JavaScript errors: `list_console_messages.js --types error`
|
||||
|
||||
**Problem:** wait_for times out
|
||||
|
||||
**Solution:**
|
||||
- Increase timeout: `--timeout 30000` (30 seconds)
|
||||
- Verify text actually appears on page (check with `take_snapshot.js`)
|
||||
- Text match is exact - check spelling and case
|
||||
- Wait for network to finish if text appears after API call
|
||||
|
||||
**Problem:** Dialog not handled
|
||||
|
||||
**Solution:**
|
||||
- Dialog must be already open when you call `handle_dialog.js`
|
||||
- Trigger dialog first (e.g., click button), then immediately call `handle_dialog.js`
|
||||
- Some "dialogs" are custom HTML, not browser dialogs - use `click.js` instead
|
||||
|
||||
**Problem:** Performance trace shows unexpected results
|
||||
|
||||
**Solution:**
|
||||
- Ensure page fully loads before stopping trace
|
||||
- Use `--reload true` for consistent initial page load measurement
|
||||
- Clear browser cache if testing first-time load performance
|
||||
- Disable browser extensions that might affect performance
|
||||
|
||||
**Problem:** Emulation not working
|
||||
|
||||
**Solution:**
|
||||
- Emulation settings persist for the session
|
||||
- To remove emulation, set back to normal values
|
||||
- Network conditions JSON must be valid with all three properties
|
||||
- CPU throttling rate of 1 = normal, higher = slower
|
||||
|
||||
**Problem:** Script evaluation with args fails
|
||||
|
||||
**Solution:**
|
||||
- Args must be valid JSON array: `--args '[1, 2, 3]'`
|
||||
- Function must accept the correct number of parameters
|
||||
- Use single quotes around JSON, double quotes inside
|
||||
- Example: `--function "(a, b) => a + b" --args '[5, 10]'`
|
||||
Reference in New Issue
Block a user