perf: React Compiler compat, bundle size & architecture improvements#1465
perf: React Compiler compat, bundle size & architecture improvements#1465haddoumounir wants to merge 8 commits intovercel:mainfrom
Conversation
Switch from `motion` to `m` components across all files and wrap the app in a LazyMotion provider with `domAnimation` features. This avoids bundling the full framer-motion runtime (~30kb savings). Also replaces dangerouslySetInnerHTML script with next/script for safer loading.
Use Next.js Image component for automatic optimization, lazy loading, and responsive sizing in image-editor, console, and model-selector.
- Derive hasReasoning inline instead of useState+useEffect latch - Use conditional setState during render instead of ref patterns for detecting prop/state changes (shell, sheet-editor, use-messages) - Add portalTarget state in text-editor to avoid reading ref during render These patterns are compatible with React Compiler optimization.
Merge currentModelId, input, showCreditCardAlert, and hasLoadedCookieModel into a single useReducer in ActiveChatProvider. Make setInput and setShowCreditCardAlert stable callbacks with empty dependency arrays since no callers use functional updates.
Break PureArtifact (412 lines) into focused pieces: - ArtifactHeader: title, save status, version badge - ArtifactContentArea: content renderer, toolbar, version footer - useArtifactDocuments: document fetching, versioning, content saving Also consolidates mode/document/versionIndex/isContentDirty into a single useReducer and fixes try/finally patterns for compiler compat.
Extract useFileUpload and useSlashCommands hooks from PureMultimodalInput (475 → 292 lines). Simplify toolbar by removing redundant isHovered state and driving tooltip from selection state.
…Input Break PromptInput (429 → 137 lines) by extracting file management into usePromptInputFiles hook and drag-and-drop setup into useDropHandlers hook. Add onKeyDown support to input-group.
- Add prefers-reduced-motion CSS media query to disable animations - Add page metadata for SEO on chat routes - Add use-reduced-motion hook for runtime motion preference detection - Remove autoFocus from auth form input (a11y best practice)
|
@haddoumounir is attempting to deploy a commit to the Templates Test vtest314 Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 946dc03abe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| setPrevChatId(chatId); | ||
| stop(); | ||
| setArtifact(initialArtifactData); |
There was a problem hiding this comment.
Move chat-switch side effects out of render
This block runs during render and invokes stop() plus setArtifact(...), both of which update state outside ChatShell. On chat navigation, React can run/discard renders (especially in Strict/Concurrent mode), so executing these mutations in render can trigger Cannot update a component while rendering a different component warnings and non-deterministic resets/cancellations. Keep only local derivation in render and move these side effects into a useEffect keyed by chatId.
Useful? React with 👍 / 👎.
| if (artifact.status === "streaming" || !isContentDirty) { | ||
| setArtifact((currentArtifact) => ({ | ||
| ...currentArtifact, |
There was a problem hiding this comment.
Avoid mutating artifact store during render
When documents changes, this render-path branch calls setArtifact(...) immediately. Because setArtifact mutates shared SWR-backed state, this is a cross-component update during render, which can warn in React and run multiple times on interrupted/double renders, causing unstable artifact content synchronization. The document→artifact sync should happen in an effect tied to documents instead of directly in render.
Useful? React with 👍 / 👎.
| if (!hasInitialized && localStorageInput) { | ||
| setHasInitialized(true); | ||
| setInput(localStorageInput); |
There was a problem hiding this comment.
Initialize input without updating parent during render
This initialization path calls setInput(localStorageInput) while PureMultimodalInput is rendering. Since setInput updates ActiveChatProvider state, this is a parent update during child render and can produce React warnings plus duplicate initialization under Strict Mode. Initialize the draft value in an effect (or in the provider’s initial state) so the update happens after render commit.
Useful? React with 👍 / 👎.
Summary
motion→mcomponents + wrap app inLazyMotionprovider (~30kb savings), replacedangerouslySetInnerHTMLscript withnext/script<img>withnext/imagein image-editor, console, and model-selectoruseStatecalls intouseReducerinActiveChatProviderandPureArtifactPureArtifact(412 → 179 lines):ArtifactHeader,ArtifactContentArea,useArtifactDocumentsPureMultimodalInput(475 → 292 lines):useFileUpload,useSlashCommandsPromptInput(429 → 137 lines):usePromptInputFiles,useDropHandlersprefers-reduced-motionCSS media query,use-reduced-motionhook, removeautoFocus