mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-16 21:53:07 +00:00
feat: Batch dev server logs and fix React module resolution order
This commit is contained in:
@@ -74,6 +74,20 @@ export function useDevServerLogs({ worktreePath, autoSubscribe = true }: UseDevS
|
||||
// Keep track of whether we've fetched initial logs
|
||||
const hasFetchedInitialLogs = useRef(false);
|
||||
|
||||
// Buffer for batching rapid output events into fewer setState calls.
|
||||
// Content accumulates here and is flushed via requestAnimationFrame,
|
||||
// ensuring at most one React re-render per animation frame (~60fps max).
|
||||
const pendingOutputRef = useRef('');
|
||||
const rafIdRef = useRef<number | null>(null);
|
||||
|
||||
const resetPendingOutput = useCallback(() => {
|
||||
if (rafIdRef.current !== null) {
|
||||
cancelAnimationFrame(rafIdRef.current);
|
||||
rafIdRef.current = null;
|
||||
}
|
||||
pendingOutputRef.current = '';
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Fetch buffered logs from the server
|
||||
*/
|
||||
@@ -130,6 +144,7 @@ export function useDevServerLogs({ worktreePath, autoSubscribe = true }: UseDevS
|
||||
* Clear logs and reset state
|
||||
*/
|
||||
const clearLogs = useCallback(() => {
|
||||
resetPendingOutput();
|
||||
setState({
|
||||
logs: '',
|
||||
logsVersion: 0,
|
||||
@@ -144,13 +159,7 @@ export function useDevServerLogs({ worktreePath, autoSubscribe = true }: UseDevS
|
||||
serverError: null,
|
||||
});
|
||||
hasFetchedInitialLogs.current = false;
|
||||
}, []);
|
||||
|
||||
// Buffer for batching rapid output events into fewer setState calls.
|
||||
// Content accumulates here and is flushed via requestAnimationFrame,
|
||||
// ensuring at most one React re-render per animation frame (~60fps max).
|
||||
const pendingOutputRef = useRef('');
|
||||
const rafIdRef = useRef<number | null>(null);
|
||||
}, [resetPendingOutput]);
|
||||
|
||||
const flushPendingOutput = useCallback(() => {
|
||||
rafIdRef.current = null;
|
||||
@@ -197,12 +206,9 @@ export function useDevServerLogs({ worktreePath, autoSubscribe = true }: UseDevS
|
||||
// Clean up pending RAF on unmount to prevent state updates after unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (rafIdRef.current !== null) {
|
||||
cancelAnimationFrame(rafIdRef.current);
|
||||
rafIdRef.current = null;
|
||||
}
|
||||
resetPendingOutput();
|
||||
};
|
||||
}, []);
|
||||
}, [resetPendingOutput]);
|
||||
|
||||
// Fetch initial logs when worktreePath changes
|
||||
useEffect(() => {
|
||||
@@ -230,6 +236,7 @@ export function useDevServerLogs({ worktreePath, autoSubscribe = true }: UseDevS
|
||||
|
||||
switch (event.type) {
|
||||
case 'dev-server:started': {
|
||||
resetPendingOutput();
|
||||
const { payload } = event;
|
||||
logger.info('Dev server started:', payload);
|
||||
setState((prev) => ({
|
||||
@@ -279,7 +286,7 @@ export function useDevServerLogs({ worktreePath, autoSubscribe = true }: UseDevS
|
||||
});
|
||||
|
||||
return unsubscribe;
|
||||
}, [worktreePath, autoSubscribe, appendLogs]);
|
||||
}, [worktreePath, autoSubscribe, appendLogs, resetPendingOutput]);
|
||||
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -930,7 +930,8 @@ export class HttpApiClient implements ElectronAPI {
|
||||
const isHighFrequency =
|
||||
data.type === 'dev-server:output' ||
|
||||
data.type === 'test-runner:output' ||
|
||||
data.type === 'auto_mode_progress';
|
||||
data.type === 'feature:progress' ||
|
||||
(data.type === 'auto-mode:event' && data.payload?.type === 'auto_mode_progress');
|
||||
if (!isHighFrequency) {
|
||||
logger.info('WebSocket message:', data.type);
|
||||
}
|
||||
|
||||
@@ -248,16 +248,12 @@ export default defineConfig(({ command }) => {
|
||||
{ find: '@', replacement: path.resolve(__dirname, './src') },
|
||||
// Force ALL React imports (including from nested deps like zustand@4 inside
|
||||
// @xyflow/react) to resolve to a single copy.
|
||||
// Explicit subpath aliases must come BEFORE the broad regex so Vite's
|
||||
// first-match-wins resolution applies the specific match first.
|
||||
{
|
||||
find: /^react-dom(\/|$)/,
|
||||
replacement: path.resolve(__dirname, '../../node_modules/react-dom') + '/',
|
||||
},
|
||||
{
|
||||
find: /^react(\/|$)/,
|
||||
replacement: path.resolve(__dirname, '../../node_modules/react') + '/',
|
||||
},
|
||||
// Explicit subpath aliases avoid mixed module IDs between bare imports and
|
||||
// optimized deps (e.g. react/jsx-runtime), which can manifest as duplicate React.
|
||||
{
|
||||
find: 'react/jsx-runtime',
|
||||
replacement: path.resolve(__dirname, '../../node_modules/react/jsx-runtime.js'),
|
||||
@@ -266,6 +262,10 @@ export default defineConfig(({ command }) => {
|
||||
find: 'react/jsx-dev-runtime',
|
||||
replacement: path.resolve(__dirname, '../../node_modules/react/jsx-dev-runtime.js'),
|
||||
},
|
||||
{
|
||||
find: /^react(\/|$)/,
|
||||
replacement: path.resolve(__dirname, '../../node_modules/react') + '/',
|
||||
},
|
||||
],
|
||||
dedupe: ['react', 'react-dom', 'zustand', 'use-sync-external-store', '@xyflow/react'],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user