Clean and Consistent Imports in Vite: Mastering Path Aliases

Clean and Consistent Imports in Vite: Mastering Path Aliases
Photo by Ahmad Kadhim / Unsplash

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.

Support Us