Vite’s lightning-fast cold server start is largely due to its reliance on native ES modules, avoiding the costly bundling step during development.
Let’s get Vite set up with Vue and TypeScript, then dive into the configuration.
First, create a new project directory and navigate into it:
mkdir vite-vue-ts-app
cd vite-vue-ts-app
Now, initialize your project using npm, yarn, or pnpm. I’ll use npm here:
npm init vite@latest . --template vue-ts
This command npm init vite@latest . --template vue-ts creates a new Vite project in the current directory (.) using the vue-ts template, which pre-configures Vue and TypeScript.
After initialization, install the dependencies:
npm install
And then start the development server:
npm run dev
You should see output similar to this, indicating Vite is running:
VITE v4.4.9 ready in 300 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
Open http://localhost:5173/ in your browser. You’ll see the default Vite + Vue + TypeScript starter page.
The core of Vite’s TypeScript integration is handled by esbuild during development and vue-tsc (which wraps the TypeScript compiler) during build. Vite leverages esbuild for its incredible speed during the development server phase. When you use npm run dev, Vite doesn’t pre-bundle your entire application. Instead, it serves your source code directly to the browser, and the browser’s native ES module support handles the imports. esbuild transpiles your TypeScript to JavaScript on-the-fly, making it incredibly fast.
For production builds (npm run build), Vite uses Rollup under the hood, and vue-tsc is invoked to perform type checking and generate the final bundled JavaScript and type definition files.
Let’s look at the tsconfig.json file generated by the template. It’s usually quite comprehensive:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"strict": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json", "types": ["vite/client"] }]
}
Key options here:
"target": "ES2020": Specifies the JavaScript version to compile down to.ES2020is a good balance for modern browser support and features."module": "ESNext": Tells the compiler to use the latest ECMAScript module syntax."lib": ["ESNext", "DOM"]: Includes built-in type definitions for ECMAScript features and the browser DOM."moduleResolution": "Node": How TypeScript finds modules.Noderesolution is standard for Node.js environments."strict": true: Enables all strict type-checking options. This is highly recommended for catching errors early."noEmit": true: Crucial for Vite’s development server. It tells TypeScript not to emit any.jsfiles. Vite handles the JavaScript output for the dev server. During a production build,vue-tsc(which respectstsconfig.json) will emit files."baseUrl": "."and"paths": { "@/*": ["./src/*"] }: Configures path aliases. This lets you use@/components/MyComponent.vueinstead of../../components/MyComponent.vue.
The references section points to tsconfig.node.json, which is used for configuring TypeScript for Node.js-specific code, like vite.config.ts. The "types": ["vite/client"] part is important; it injects Vite’s ambient type definitions, giving you type safety for Vite-specific features like import.meta.env.
When you modify a .vue file, Vite (via its plugin ecosystem, specifically vitejs/plugin-vue) handles the Single File Component (SFC) compilation. It transforms the template and script sections into standard JavaScript/TypeScript that esbuild can then process. For TypeScript within <script lang="ts"> blocks, esbuild does the transpilation.
The vite.config.ts file is where you configure Vite itself. For a Vue + TS project, it typically looks like this:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
}
})
Here, vue() is the essential plugin for Vue 3 SFCs. The resolve.alias configuration mirrors the paths in tsconfig.json, ensuring consistency between your development tooling and your type checking. Vite uses this alias configuration to resolve module paths when serving files.
The skipLibCheck: true in tsconfig.json is a performance optimization. It tells the TypeScript compiler to skip type checking of declaration files (.d.ts) in node_modules. Since these are usually pre-compiled and trusted, skipping them speeds up compilation significantly, especially in large projects.
The verbatimModuleSyntax: true option is a newer TypeScript feature that aligns module syntax more closely with ECMAScript standards, especially regarding import/export. It ensures that Vite’s handling of ES modules is interpreted correctly by TypeScript.
One common point of confusion is the interaction between noEmit in tsconfig.json and the production build. During npm run dev, noEmit: true is active, and Vite handles the transpilation and serving. However, when you run npm run build, Vite orchestrates a build process that does involve type checking and emitting files. The vue-tsc command, which is implicitly run by Vite’s build process for TS projects, will perform the full TypeScript compilation and generate the necessary output files (JS bundles, .d.ts files if configured) in the dist directory, respecting the tsconfig.json settings for the build output.
The references array in tsconfig.json is how you manage multi-package or internal project references. In this case, it’s referencing tsconfig.node.json for Node-specific configurations and also telling the TypeScript server to include Vite’s client-side types. This is crucial for features like environment variables defined via import.meta.env.
If you were to see type errors during development, they would typically appear directly in your IDE (thanks to the TypeScript server integration) or in the browser’s console if vue-tsc’s error reporting is configured to show up there. During a npm run build, type errors would halt the build process and be printed to your terminal.
The next thing you’ll likely want to configure is how Vite handles environment variables, especially for different deployment stages.