gen-ai-writen via Cursor IDE agent mode auto (likely claude 3.7)
related: Debugging CRA to Vite Migrations - A Systematic Approach
1. SVG Import Pattern Changes
Original CRA Pattern
// This worked in CRA
import StarIcon from "../icons/star.svg?react";
import HeartIcon from "../icons/heart.svg?react";Vite Pattern
// Required for Vite
import { ReactComponent as StarIcon } from "../icons/star.svg";
import { ReactComponent as HeartIcon } from "../icons/heart.svg";Why It Broke
- CRA used a custom webpack loader (
?reactquery parameter) - Vite uses a different SVG handling strategy
- The
?reactsyntax is CRA-specific and not supported in Vite
2. Function Initialization Order
Original Pattern (Worked in CRA)
// This worked in CRA despite being out of order
const sortByPrice = (carA, carB) => {
// Uses calculateDiscount and getFinalPrice before they're defined
const discountA = calculateDiscount(carA);
const finalPriceA = getFinalPrice(carA, discountA);
// ...
};
const calculateDiscount = (car) =>
car.features.some((feature) => specialOffers.includes(feature.name));
const getFinalPrice = (car, discount) =>
car.basePrice - (car.basePrice * discount);Fixed Pattern (Required for Vite)
// Functions must be defined before use
const calculateDiscount = (car) =>
car.features.some((feature) => specialOffers.includes(feature.name));
const getFinalPrice = (car, discount) =>
car.basePrice - (car.basePrice * discount);
const sortByPrice = (carA, carB) => {
// Now calculateDiscount and getFinalPrice are defined
const discountA = calculateDiscount(carA);
const finalPriceA = getFinalPrice(carA, discountA);
// ...
};Why It Broke
- CRA’s webpack might have reordered the code
- Vite preserves the exact order of the code
- Function expressions (const fn = () ⇒ {}) are not hoisted
- Only function declarations (function fn() {}) are hoisted
3. Error Boundary Initialization
Original Pattern
// This worked in CRA even if ErrorTracker wasn't initialized
<ErrorBoundary>
<CarListing />
</ErrorBoundary>Fixed Pattern
// Need to check if error reporting is available
if (ErrorTracker?.logError) {
ErrorTracker.logError(error, {
context: {
component: "CarListing",
carId: car.id,
},
});
}Why It Broke
- CRA’s development server was more forgiving of undefined objects
- Vite’s development server is closer to production behavior
- Error boundaries need proper initialization checks
4. Environment Variables
Original CRA Pattern
// This worked in CRA
process.env.REACT_APP_API_URLVite Pattern
// Required for Vite
import.meta.env.VITE_API_URLWhy It Broke
- CRA used
process.env - Vite uses
import.meta.env - Prefix requirement changed from
REACT_APP_toVITE_
5. Global Variables
Original Pattern
// This worked in CRA
let specialOffers = []; // Global variable
const CarListing = () => {
specialOffers = currentPromotions; // Mutating global
// ...
}Better Pattern
// Use state or context instead
const CarListing = () => {
const [specialOffers, setSpecialOffers] = useState([]);
useEffect(() => {
setSpecialOffers(currentPromotions);
}, [currentPromotions]);
// ...
}Why It Broke
- CRA was more forgiving of global state
- Vite’s module system makes global variables more problematic
- React’s functional components prefer local state
Key Takeaways
-
SVG Imports
- Remove
?reactsuffix - Use
ReactComponentimport syntax - Update usage in components
- Remove
-
Function Order
- Define functions before use
- Use function declarations for hoisting when needed
- Be explicit about dependencies
-
Error Handling
- Add null checks for error reporting
- Initialize error boundaries properly
- Handle undefined states
-
Environment Variables
- Update prefix from
REACT_APP_toVITE_ - Use
import.meta.envinstead ofprocess.env - Update build configuration
- Update prefix from
-
State Management
- Avoid global variables
- Use React’s state management
- Be explicit about dependencies