Skip to content

Commit 07b5405

Browse files
committed
add architecture doc file
1 parent 2832845 commit 07b5405

20 files changed

Lines changed: 2772 additions & 0 deletions
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# Frontend Optimization Architecture
2+
3+
## Overview
4+
5+
React frontend optimization extends Codeflash's existing JS/TS support with
6+
framework-specific component discovery, React Profiler instrumentation,
7+
memoization-focused optimization, and render-count-aware acceptance criteria.
8+
9+
## Design Principle
10+
11+
React optimization is a **framework plugin** under JS/TS, not a separate language.
12+
It reuses the existing tree-sitter parser (JSX/TSX), Jest/Vitest runner, comparator,
13+
and instrumentation infrastructure. Framework-specific logic is isolated in
14+
`languages/javascript/frameworks/react/`.
15+
16+
This pattern is designed to be reused for other frontend frameworks (Vue, Angular, Svelte)
17+
by adding new directories under `languages/javascript/frameworks/<framework>/`.
18+
19+
## Architecture Diagram
20+
21+
┌──────────────────────────────────────────────────────────┐
22+
│ CLI Entry Point │
23+
│ codeflash optimize --file src/components/TaskList.tsx │
24+
└────────────────────────┬─────────────────────────────────┘
25+
26+
27+
┌──────────────────────────────────────────────────────────┐
28+
│ Framework Detection (detector.py) │
29+
│ package.json → FrameworkInfo(name="react", version=18) │
30+
└────────────────────────┬─────────────────────────────────┘
31+
32+
33+
┌──────────────────────────────────────────────────────────┐
34+
│ Component Discovery (discovery.py) │
35+
│ tree-sitter → ReactComponentInfo[] │
36+
│ PascalCase + JSX return + hooks → is_react_component │
37+
└────────────────────────┬─────────────────────────────────┘
38+
39+
40+
┌──────────────────────────────────────────────────────────┐
41+
│ Context Extraction (context.py + analyzer.py) │
42+
│ Component source + props interface + hooks + parents │
43+
│ + optimization opportunities (missing memo/useMemo) │
44+
└────────────────────────┬─────────────────────────────────┘
45+
46+
┌──────────────┴──────────────┐
47+
▼ ▼
48+
┌───────────────────┐ ┌──────────────────────────────┐
49+
│ Test Generation │ │ Optimization Generation │
50+
│ (testgen.py) │ │ (aiservice + react prompts)│
51+
│ │ │ │
52+
│ React Testing │ │ React.memo wrapping │
53+
│ Library tests │ │ useMemo for computations │
54+
│ + re-render │ │ useCallback for handlers │
55+
│ counting tests │ │ Inline object elimination │
56+
└────────┬──────────┘ └──────────────┬───────────────┘
57+
│ │
58+
└──────────────┬─────────────────┘
59+
60+
┌──────────────────────────────────────────────────────────┐
61+
│ Verification (existing Jest/Vitest runner) │
62+
│ Run existing + generated tests on original AND candidate │
63+
│ compare_test_results() → behavioral equivalence │
64+
└────────────────────────┬─────────────────────────────────┘
65+
66+
67+
┌──────────────────────────────────────────────────────────┐
68+
│ React Benchmarking (profiler.py + benchmarking.py)│
69+
│ React Profiler instrumentation → render count + duration │
70+
│ Parse !######REACT_RENDER:...######! markers │
71+
│ Compare original vs optimized render profiles │
72+
└────────────────────────┬─────────────────────────────────┘
73+
74+
75+
┌──────────────────────────────────────────────────────────┐
76+
│ Critic (render_efficiency_critic) │
77+
│ Accept if: render_count reduced >= 20% │
78+
│ OR: render_duration reduced >= threshold │
79+
│ AND: all tests pass (behavioral equivalence) │
80+
└────────────────────────┬─────────────────────────────────┘
81+
82+
83+
┌──────────────────────────────────────────────────────────┐
84+
│ PR Creation │
85+
│ "Reduced re-renders from 47 → 3 (93.6% fewer)" │
86+
│ "Render time: 340ms → 12ms (28x faster)" │
87+
│ Includes generated tests + optimized component code │
88+
└──────────────────────────────────────────────────────────┘
89+
90+
## File Structure
91+
92+
languages/javascript/
93+
├── support.py # Delegates to react/ when framework detected
94+
├── treesitter.py # Reused — already handles JSX/TSX
95+
├── test_runner.py # Reused — runs Jest/Vitest
96+
├── comparator.py # Reused — compares test results
97+
├── instrument.py # Reused — capturePerf wrapping
98+
├── parse.py # Extended — parse REACT_RENDER markers
99+
├── frameworks/
100+
│ ├── __init__.py
101+
│ ├── detector.py # Detect React from package.json
102+
│ └── react/
103+
│ ├── __init__.py
104+
│ ├── discovery.py # Find React components via tree-sitter
105+
│ ├── analyzer.py # Detect optimization opportunities
106+
│ ├── profiler.py # React Profiler instrumentation
107+
│ ├── context.py # Component context extraction
108+
│ ├── benchmarking.py # Render count/duration comparison
109+
│ └── testgen.py # React Testing Library test helpers
110+
111+
## Verification Model
112+
113+
React optimization uses the SAME verification guarantees as code optimization:
114+
115+
┌─────────────────────────────────────────────────┐
116+
│ Behavioral Equivalence │
117+
│ │
118+
│ For each test invocation: │
119+
│ original.did_pass == candidate.did_pass │
120+
│ original.return_value ≡ candidate.return_value │
121+
│ original.stdout ≡ candidate.stdout │
122+
│ │
123+
│ PLUS for React: │
124+
│ candidate.render_count <= original.render_count │
125+
│ candidate.render_duration < original.render_duration │
126+
└─────────────────────────────────────────────────┘
127+
128+
## Optimization Patterns (Tier 1)
129+
130+
| Pattern | Detection | Optimization | Verification |
131+
|---------|-----------|-------------|--------------|
132+
| Missing React.memo | Component not wrapped + receives stable props | Wrap with React.memo() | Same render output, fewer renders |
133+
| Missing useMemo | Array .filter/.sort/.map in render body | Wrap computation in useMemo() | Same computed result, fewer executions |
134+
| Missing useCallback | Function defined in render, passed as prop | Wrap with useCallback() | Same behavior, stable reference |
135+
| Inline object props | Object literal in JSX prop position | Extract to useMemo or module constant | Same prop values, stable reference |
136+
137+
## Extending to Other Frameworks
138+
139+
To add support for a new framework (e.g., Vue):
140+
141+
1. Create `languages/javascript/frameworks/vue/` directory
142+
2. Add discovery module: detect Vue SFCs (`.vue` files), `<script setup>`, composition API
143+
3. Add analyzer module: detect reactivity patterns (missing `computed()`, inline watchers)
144+
4. Add context module: extract component props, emits, slots, composables
145+
5. Add profiler module: instrument with Vue Devtools performance API
146+
6. Add benchmarking module: compare reactive dependency tracking counts
147+
7. Update `detector.py` to detect Vue from `package.json`
148+
8. Add backend prompts in `django/aiservice/core/languages/js_ts/prompts/vue_optimizer/`
149+
150+
The framework detection → discovery → context → optimize → verify → benchmark pipeline
151+
is shared infrastructure. Only the framework-specific detection and analysis differ.
152+
153+
## Test Project
154+
155+
A comprehensive React test project lives at `code_to_optimize/js/code_to_optimize_react/`
156+
with components that exercise each optimization pattern:
157+
158+
| Component | Optimization Patterns |
159+
|-----------|----------------------|
160+
| TaskBoard | useMemo, useCallback, inline styles, React.memo |
161+
| DataGrid | useMemo (aggregations, pagination), useCallback, inline styles |
162+
| SearchableList | Unstable references defeating memo'd children, useMemo |
163+
| FormWithValidation | useMemo (validation), useCallback (handlers), regex caching |
164+
| VirtualizedTree | useMemo (tree flattening, search), useCallback |
165+
| OptimizedCounter | Already optimized — should be skipped |
166+
| ServerDashboard | Server Component — should be skipped |
167+
| useFilteredData | Hook returning unstable object reference |
168+
| useDebounce | Standard hook — should be detected as hook, not component |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
language: typescript
2+
module_root: .
3+
tests_root: tests
4+
test_framework: jest
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { Config } from 'jest';
2+
3+
const config: Config = {
4+
preset: 'ts-jest',
5+
testEnvironment: 'jsdom',
6+
testMatch: [
7+
'**/tests/**/*.test.ts',
8+
'**/tests/**/*.test.tsx',
9+
'**/tests/**/*.spec.tsx'
10+
],
11+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
12+
setupFilesAfterSetup: ['@testing-library/jest-dom'],
13+
collectCoverageFrom: [
14+
'src/**/*.{ts,tsx}',
15+
'!**/node_modules/**',
16+
'!**/dist/**',
17+
'!jest.config.ts'
18+
],
19+
reporters: [
20+
'default',
21+
[
22+
'jest-junit',
23+
{
24+
outputDirectory: '.codeflash',
25+
outputName: 'jest-results.xml',
26+
includeConsoleOutput: true
27+
}
28+
]
29+
],
30+
transform: {
31+
'^.+\\.tsx?$': ['ts-jest', {
32+
useESM: false,
33+
tsconfig: 'tsconfig.json'
34+
}]
35+
}
36+
};
37+
38+
export default config;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "codeflash-react-test",
3+
"version": "1.0.0",
4+
"description": "Sample React TypeScript project for codeflash optimization testing",
5+
"main": "dist/index.js",
6+
"scripts": {
7+
"test": "jest",
8+
"test:coverage": "jest --coverage",
9+
"build": "tsc"
10+
},
11+
"codeflash": {
12+
"moduleRoot": ".",
13+
"testsRoot": "tests"
14+
},
15+
"keywords": [
16+
"codeflash",
17+
"optimization",
18+
"testing",
19+
"react",
20+
"typescript"
21+
],
22+
"author": "CodeFlash Inc.",
23+
"license": "BSL 1.1",
24+
"dependencies": {
25+
"react": "^18.2.0",
26+
"react-dom": "^18.2.0"
27+
},
28+
"devDependencies": {
29+
"@testing-library/jest-dom": "^6.0.0",
30+
"@testing-library/react": "^14.0.0",
31+
"@testing-library/user-event": "^14.0.0",
32+
"@types/jest": "^29.5.0",
33+
"@types/node": "^20.0.0",
34+
"@types/react": "^18.2.0",
35+
"@types/react-dom": "^18.2.0",
36+
"codeflash": "file:../../../packages/codeflash",
37+
"jest": "^29.7.0",
38+
"jest-environment-jsdom": "^29.7.0",
39+
"jest-junit": "^16.0.0",
40+
"ts-jest": "^29.1.0",
41+
"ts-node": "^10.9.2",
42+
"typescript": "^5.0.0"
43+
}
44+
}

0 commit comments

Comments
 (0)