Deeply nested relative imports like '../../../components/Button' are fragile and hard to read. This lesson covers how to configure clean, absolute-style path aliases in Vite, why tsconfig.json needs matching configuration, and when to split into multiple, more specific aliases.
1The Problem with Relative Imports
As a project's folder structure grows deeper, relative imports like '../../../components/ui/Button' become common — fragile to file moves and hard to read at a glance. Path aliases replace these with a consistent, absolute-style import such as '@/components/ui/Button' that works identically regardless of the importing file's location.
2Configuring resolve.alias in Vite
Aliases are defined in vite.config.ts under resolve.alias, mapping a prefix like '@' to an absolute directory path, typically the src folder. Vite rewrites imports using that prefix during both development serving and the production build, so behavior stays consistent across modes.
3TypeScript Needs to Know Too
Configuring an alias in vite.config.ts makes it work at runtime, but TypeScript's own tooling — autocomplete, type checking, go-to-definition — is unaware of it unless the same mapping is also declared in tsconfig.json's compilerOptions.paths. Both files must be kept in sync for the alias to work seamlessly in the editor as well as at runtime.
4A Widely Used Convention: @/*
Mapping '@' to the src directory, so that '@/*' resolves to 'src/*', is one of the most common alias conventions in the React ecosystem, giving every import in the app a short, unambiguous, absolute-style prefix instead of relative path chains.
5Aliasing Beyond a Single '@'
Larger codebases sometimes define multiple, more specific aliases — like @components, @hooks, or @utils — each pointing directly at a subfolder, trading a single catch-all prefix for more explicit, self-documenting import statements.
6Step-by-Step Breakdown
The Problem with Relative Imports. As a project grows, imports like import Button from '../../../components/ui/Button' become common — fragile, hard to read, and painful to update when you move a file. Path aliases let you replace that with a clean, absolute-style import: import Button from '@/components/ui/Button', no matter how deep the importing file lives.
Configuring resolve.alias in Vite. Path aliases are set up in vite.config.ts under resolve.alias, mapping a prefix like @ to an absolute directory path. Vite rewrites any import starting with that prefix during both dev serving and the production build, so the alias works identically in every mode.
Where is a Vite path alias like @ → src/ actually configured?
- →In vite.config.ts, under resolve.alias
- →In package.json, under 'dependencies'
TypeScript Needs to Know Too. Configuring the alias in vite.config.ts makes the import work at build and runtime, but TypeScript's editor tooling — autocomplete, type checking, 'go to definition' — has no idea about it unless you also declare it in tsconfig.json under compilerOptions.paths. Both configs must agree, or you'll get red squiggly lines despite the code actually working.
**This Very Codebase Uses @/*.** This exact pattern — @/* mapping to src/* — is what Code Syllabus itself uses, which is why every content and component file you've explored imports with @/types/lesson, @/services/..., or @/components/... instead of long chains of ../. It's one of the most common alias conventions in the React ecosystem.
You added an alias to vite.config.ts and imports work at runtime, but your editor still shows a 'cannot find module' error. What's the likely cause?
- →tsconfig.json's compilerOptions.paths is missing the same alias
- →The computer needs to be restarted
Aliasing Beyond a Single '@'. You're not limited to one alias. Larger codebases often define several, like @components, @hooks, @utils, or @assets, each pointing at a specific subfolder — trading a single catch-all alias for more explicit, self-documenting import prefixes.
Mastery Achieved. You now know how to set up path aliases: configuring resolve.alias in vite.config.ts for runtime resolution, mirroring it in tsconfig.json's paths for editor tooling, and optionally splitting into multiple, more specific aliases as a project grows. Next, you'll look at how Vite handles images, fonts, and other static assets.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Aliases are resolved entirely at build time; no runtime browser feature is involved.
Fully applicable.
Fully applicable.
Fully applicable.
Accessibility (A11y)
1Cleaner Imports Support Faster, More Accurate Code Review
While not a direct accessibility feature, readable import paths make it easier for reviewers to correctly verify accessibility-related component usage during code review, since imports aren't obscured by long relative path chains.
SEO Implications
- 1
Path Aliases Have No Runtime Effect on Shipped Output
Aliases are purely a development-time and build-time convenience — they're fully resolved to real paths before the bundle is produced, so they have no bearing on SEO or shipped bundle size.
Best Practices
Keep vite.config.ts and tsconfig.json Aliases in Sync
Whenever an alias is added or changed in one file, update the other immediately — a mismatch causes confusing situations where code runs correctly but the editor shows false type errors, or vice versa.
Prefer One Broad Alias Unless the Project Is Large
A single '@' → src alias is usually sufficient for small to mid-sized projects; only introduce multiple granular aliases (@components, @hooks, etc.) once the extra specificity clearly earns its added configuration complexity.
Frequent Bugs
An import using an alias works when running the dev server but fails a separate type-check or lint script.
The alias is likely defined in vite.config.ts but missing from tsconfig.json's compilerOptions.paths (or vice versa for a linting tool that reads tsconfig). Ensure both files declare the exact same alias mapping.
Autocomplete in the editor doesn't suggest files under an aliased import path.
The TypeScript language server needs baseUrl and paths configured in tsconfig.json to resolve the alias for editor tooling — a Vite-only alias configuration isn't visible to the editor.
Real-World Examples
Standardizing Imports Across a Large Feature Codebase
A team's imports had drifted into inconsistent relative paths of varying depth across dozens of feature folders. Introducing a single '@' → src alias in both vite.config.ts and tsconfig.json let them run a codemod converting every relative import to the consistent '@/...' form, making the codebase noticeably easier to navigate.
// vite.config.ts
resolve: { alias: { '@': path.resolve(__dirname, './src') } }
// tsconfig.json
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }