From Vite to Next.js
I made my first commit on GitHub last year by creating a repository to build a crossword game. Fast forward to February and I'm converting a whole existing codebase from one language I no zero about to one I know very little about, thanks to Trae.
This is pretty much a summary of the bugs I faced while migrating the codebase from Vite to Next.js in less than 24 hours; bugs that almost knocked me out, even with Trae for help. Thank God for chicken — no kidding.
The initial challenge: module resolution
My first major hurdle came from the different module resolution strategies between Vite and Next.js. Vite's more lenient approach to imports clashed with Next.js's stricter requirements.
The bug:
// This worked in Vite but broke in Next.js
import { SomeComponent } from 'components/SomeComponent'
The solution:
I updated the import paths and configure path aliases in tsconfig.json:
{
"compilerOptions": {
"paths": {
"@/*": ["./"]
}
}
}
But this didn't stop there because I also had to fix import issues on multiple files, especially because Trae wasn't fixing all of them at once, which sucked big time as the coding noob that I'm.
React Router vs Next.js Router
One of the trickiest parts was dealing with routing conflicts. The codebase heavily relied on React Router, which apparently doesn't play nicely with Next.js's built-in routing.
The bug:
Multiple routing systems fighting for control led to unpredictable navigation and broken deep links.
The solution:
I gradually migrated to Next.js's App Router, converting all routes to the new format:
// Old React Router approach
<Route path="/dashboard" element={<Dashboard />} />
// New Next.js approach
// app/dashboard/page.tsx
export default function DashboardPage() {
return <Dashboard />
}
Image optimisation challenges
Vite's approach to image handling differed significantly from Next.js's Image component requirements.
The bug:
Images that worked perfectly in Vite started throwing errors about unoptimised images in Next.js.
The solution:
I configured the Next.js Image component in next.config.js:
module.exports = {
images: {
domains: ['[redacted]'],
formats: ['image/webp']
}
}
Environment variables
Environment variable handling between Vite and Next.js required some adjustments.
The bug:
// This worked in Vite but failed in Next.js
const apiKey = import.meta.env.VITE_API_KEY
The solution:
const apiKey = process.env.NEXT_PUBLIC_API_KEY
Build configuration
The build process needed significant updates to work with Next.js's requirements.
The solution:
const nextConfig = {
experimental: {
esmExternals: false,
},
reactStrictMode: true,
swcMinify: true,
output: 'standalone'
}
Lessons learned
- Plan the migration: A gradual, feature-by-feature migration worked better than a big-bang approach.
- Update dependencies early: Identify and update dependencies that might conflict with Next.js.
- Test everything: Each migration step needs thorough testing, especially routing and data fetching.
- Documentation is key: Keep track of changes and solutions for future reference.
Migrating from Vite to Next.js was challenging but worthwhile. The improved performance, better SEO capabilities, and enhanced customer experience will make this really memorable. Personally tho, every bug was an opportunity to ask Claude/ChatGPT/Deepseek to explain like I'm five, so lots of (un)structured learnings.
Looking forward to the next one!