Vite 配置中 JavaScript 和 TypeScript 的区别
·
Vite 配置中 JavaScript 和 TypeScript 的区别
一、配置文件对比
二、配置文件写法对比
2.1 JavaScript 配置 (vite.config.js)
// vite.config.js - CommonJS 格式
const { defineConfig } = require('vite')
const vue = require('@vitejs/plugin-vue')
const path = require('path')
module.exports = defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
}
}
})
// vite.config.mjs - ES Module 格式(推荐)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
2.2 TypeScript 配置 (vite.config.ts)
// vite.config.ts
import { defineConfig, UserConfig, ConfigEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url'
// 使用类型注解
export default defineConfig((config: ConfigEnv): UserConfig => {
const { command, mode } = config
return {
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
port: 3000,
host: true
}
}
})
三、主要区别详解
3.1 类型安全对比
JavaScript 示例(无类型检查):
// vite.config.js - 可能的错误不会被提前发现
export default defineConfig({
plugins: [vue()],
server: {
port: '3000', // ❌ 错误:应该是数字,但 JS 不会报错
open: 'yes' // ❌ 错误:应该是布尔值
},
build: {
rollupOptions: {
output: {
manualChunks: 'vendor' // ❌ 错误:应该是函数或对象
}
}
}
})
TypeScript 示例(有类型检查):
// vite.config.ts - 错误会在编译时被发现
import { defineConfig, UserConfig } from 'vite'
export default defineConfig((): UserConfig => {
return {
plugins: [vue()],
server: {
port: '3000', // ❌ TypeScript 错误:类型"string"不能分配给类型"number"
open: 'yes' // ❌ TypeScript 错误:类型"string"不能分配给类型"boolean"
},
build: {
rollupOptions: {
output: {
manualChunks: 'vendor' // ❌ TypeScript 错误:类型不匹配
}
}
}
}
})
3.2 智能提示对比
// TypeScript 配置 - 完整的智能提示
import { defineConfig, PluginOption } from 'vite'
export default defineConfig({
plugins: [
// 鼠标悬停可以看到完整的类型定义
{
name: 'my-plugin',
// 自动提示所有可用的钩子函数
configResolved(config) {
// config 参数有完整的类型定义
console.log(config.base)
},
transform(code, id) {
// 参数类型自动推断
if (id.endsWith('.vue')) {
return code
}
}
} as PluginOption
]
})
四、TypeScript 特有配置
4.1 使用 TypeScript 需要的额外配置
1. 安装必要依赖:
# TypeScript 项目需要额外安装
npm install -D typescript vue-tsc @types/node
2. tsconfig.json 配置:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"moduleResolution": "node",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
3. 环境变量类型声明:
// env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_API_BASE_URL: string
readonly VITE_APP_ENV: 'development'
4.2 高级 TypeScript 配置示例
// vite.config.ts - 使用高级类型
import { defineConfig, Plugin, UserConfig, ConfigEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
// 自定义插件类型
interface MyPluginOptions {
include?: string[]
exclude?: string[]
}
// 创建自定义插件
function myPlugin(options: MyPluginOptions = {}): Plugin {
return {
name: 'my-custom-plugin',
transform(code: string, id: string) {
if (options.include?.some(pattern => id.includes(pattern))) {
return {
code: code.replace(/console\.log/g, ''),
map: null
}
}
}
}
}
// 条件配置类型
type ViteConfig = UserConfig & {
customOption?: {
apiUrl: string
timeout: number
}
}
export default defineConfig(({ command, mode }: ConfigEnv): ViteConfig => {
const isDev = mode === 'development'
const isBuild = command === 'build'
return {
plugins: [
vue(),
myPlugin({
include: ['src/components'],
exclude: ['node_modules']
})
],
// 自定义配置(需要扩展类型)
customOption: {
apiUrl: isDev ? 'http://localhost:3000' : 'https://api.example.com',
timeout: 5000
},
// 条件配置
build: isBuild ? {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
}
} : undefined
}
})
五、实际项目配置对比
5.1 JavaScript 项目完整配置
// vite.config.mjs
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig(({ command, mode }) => {
const env = loadEnv(mode, process.cwd())
return {
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'components': path.resolve(__dirname, './src/components'),
'views': path.resolve(__dirname, './src/views')
}
},
server: {
port: parseInt(env.VITE_PORT) || 3000,
proxy: {
'/api': {
target: env.VITE_API_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
build: {
outDir: 'dist',
sourcemap: mode === 'development'
}
}
})
5.2 TypeScript 项目完整配置
// vite.config.ts
import { defineConfig, loadEnv, UserConfig, ConfigEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// 定义环境变量接口
interface ViteEnv {
VITE_PORT: number
VITE_API_URL: string
VITE_PUBLIC_PATH: string
VITE_PROXY: boolean
}
// 解析环境变量
function wrapperEnv(envConf: Record<string, string>): ViteEnv {
const ret: any = {}
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g, '\n')
realName = realName === 'true' ? true : realName === 'false' ? false : realName
if (envName === 'VITE_PORT') {
realName = Number(realName)
}
ret[envName] = realName
}
return ret as ViteEnv
}
export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
const root = process.cwd()
const env = loadEnv(mode, root)
const viteEnv = wrapperEnv(env)
const { VITE_PORT, VITE_PUBLIC_PATH, VITE_PROXY, VITE_API_URL } = viteEnv
const isBuild = command === 'build'
return {
base: VITE_PUBLIC_PATH,
root,
plugins: [vue()],
resolve: {
alias: {
'@': resolve(root, './src'),
'#': resolve(root, './types'),
'components': resolve(root, './src/components'),
'views': resolve(root, './src/views')
}
},
server: {
host: true,
port: VITE_PORT,
proxy: VITE_PROXY ? {
'/api': {
target: VITE_API_URL,
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/api/, '')
}
} : undefined
},
build: {
target: 'es2015',
outDir: 'dist',
sourcemap: !isBuild,
reportCompressedSize: false,
chunkSizeWarningLimit: 2000,
rollupOptions: {
output: {
manualChunks: {
vue: ['vue', 'vue-router', 'pinia'],
elementPlus: ['element-plus'],
utils: ['axios', 'dayjs']
}
}
}
},
optimizeDeps: {
include: ['vue', 'vue-router', 'pinia', 'axios'],
exclude: ['vue-demi']
}
}
})
六、选择建议
总结建议:
- 小型/个人项目:使用 JavaScript 配置即可,快速简单
- 中大型项目:推荐使用 TypeScript,提供更好的类型安全和开发体验
- 团队协作项目:强烈推荐 TypeScript,统一的类型定义有助于团队协作
- 学习项目:建议从 JavaScript 开始,逐步过渡到 TypeScript
更多推荐
所有评论(0)