Clean and Consistent Imports in Vite: Mastering Path Aliases
In modern front-end development, keeping your import paths clean is more than just a matter of aesthetics—it's about maintainability, scalability, and sanity. If you've ever found yourself typing ../../../
just to reach a utility file, you're not alone. Luckily, Vite supports path aliasing, and in this article, we'll walk through how to set it up properly, so you can use imports like:
import { cn } from "@/lib/utils"
instead of:
import { cn } from "../../lib/utils"
We'll cover Vite, TypeScript, and some caveats you might not be aware of—especially if you're using React Router 7, shadcn/ui, or other modern stacks.
Setting Up Path Aliases in Vite
To make @
point to your src
folder (a popular convention), you need to modify your vite.config.ts
or vite.config.js
file.
1. Update Vite Configuration
In vite.config.ts
:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
});
Important: Always use path.resolve(__dirname, './src')
instead of hardcoding the full path.
2. Update tsconfig.json
or jsconfig.json
For your IDE and TypeScript server to recognize the alias, update your tsconfig.json
like so:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
If you're using JavaScript instead of TypeScript, the file will be named jsconfig.json
but the structure is the same.
3. Restart Your IDE
Don't forget this step. Your editor (like VS Code) needs to reload the config to pick up the changes.
Common Pitfalls
❌ Import still doesn't resolve?
- Check file casing. Some systems (like Windows) are case-insensitive; others (like Linux) are not.
- Ensure
tsconfig.json
is in your project root. If it's nested or misnamed, it won't be respected. - Make sure you're using Vite and not something else. Aliasing strategies vary across bundlers like Webpack, Rollup, etc.
Integrating with shadcn/ui and React Router 7
Libraries like shadcn/ui often assume your project follows modern conventions, including clean paths. However, React Router 7 (or any dynamic routing solution) doesn’t care about your aliases—it only matters during the build process. So if things "break" when you deploy, but work locally, it’s almost always a misconfigured alias or base path.
Pro tip: If you're deploying to a subdirectory (e.g. /app/
instead of /
), also set base
in vite.config.ts
:
export default defineConfig({
base: '/app/',
// ...rest of config
})
Bonus Tips
Use More Than One Alias
You can define multiple aliases:
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@utils': path.resolve(__dirname, './src/lib/utils')
}
ESLint and Aliases
If you're using ESLint, make sure it understands your alias. Install and configure eslint-import-resolver-alias
or use the typescript
resolver with the correct settings.
shadcn/ui Directory Convention
If you're organizing your components under something like src/components/ui
, it makes sense to add:
'@ui': path.resolve(__dirname, './src/components/ui')
Finally
Setting up path aliases in Vite is straightforward, but it requires synchronizing between your Vite config, tsconfig, and optionally ESLint. Once it's done, you'll enjoy:
- Cleaner imports
- Better maintainability
- Consistent developer experience across the team
If you're using tools like shadcn/ui, React Router, or any layered architecture, this setup will help keep your project scalable and your codebase elegant.
Comments ()