Vite + Vue + TypeScript 项目搭建总结
1. 初始项目
官网地址:Vite | 下一代的前端工具链
1.1 项目搭建
pnpm create vite
然后按照提示操作,这里选择的是 Vue + TypeScript,生成的目录结构如下
├── .vscode │ └── extensions.json ├── public │ └── vite.svg ├── src │ ├── assets │ │ └── vue.svg │ ├── components │ │ └── HelloWorld.vue │ ├── App.vue │ ├── main.ts │ ├── style.css │ └── vite-env.d.ts ├── .gitignore ├── README.md ├── index.html ├── package.json ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts
- .vscode/extensions.json:用来配置推荐安装的 VSCode 插件
- public/vite.svg:网站图标,可自定义
-
src/:存放项目源代码
- assets/:存放静态资源,如图片、字体等
- components/:存放公共组件
- App.vue,根组件
- main.ts:入口 TypeScript 文件
- vite-env.d.ts:Vite 环境变量
- .gitignore:指定被 Git 忽略的文件或文件夹
- README.md:描述项目的主要信息
- index.html:入口 HTML 文件
- package.json:项目的依赖列表和工具配置信息
- tsconfig.app.json:定义项目中其他文件的 TypeScript 编译规则
- tsconfig.json:tsconfig.node.json和tsconfig.app.json最终会被引入到这个文件中
- tsconfig.node.json:专门用来配置vite.config.ts文件的编译规则
- vite.config.ts:Vite 配置文件
1.2 配置
修改vite.config.ts配置文件
1.2.1 服务器配置
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [vue()], server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } }, });
1.2.2 别名
下载@types/node依赖
pnpm install @types/node
添加别名
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import { resolve } from 'path'; export default defineConfig({ resolve: { alias: { '@': resolve(__dirname, 'src') } }, plugins: [vue()], server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } }, });
修改tsconfig.app.json,添加别名映射
{ "compilerOptions": { "composite": true, // 是否编译构建引用项目 "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", // 指定文件用来存储增量编译信息 "target": "ES2020", // 用于指定编译之后的版本目标 "useDefineForClassFields": true, // 改变类属性声明的行为 "module": "ESNext", // 指定要使用的模块标准 "lib": ["ES2020", "DOM", "DOM.Iterable"], // 指定要包含在编译中的库文件 "skipLibCheck": true, // 跳过声明文件的类型检查 /* Bundler mode */ "moduleResolution": "bundler", // 模块解析策略 "allowImportingTsExtensions": true, // 允许在非 TypeScript 文件中导入 .ts 或 .tsx 文件 "resolveJsonModule": true, // 解析 JSON 模块 "isolatedModules": true, // 是否将每个文件作为单独的模块 "moduleDetection": "force", // 强制 TypeScript 将所有文件视为模块 "noEmit": true, // 不生成编译文件 "jsx": "preserve", // 指定 JSX 代码用于的开发环境 /* Linting */ "strict": true, // 是否启动所有类型检查 "noUnusedLocals": true, // 检查是否有定义但是没有使用的变量 "noUnusedParameters": true, // 检查是否有在函数体中没有使用的参数 "noFallthroughCasesInSwitch": true, // 检查 Switch 中是否有 Case 没有使用 break 跳出 /* Alias */ "baseUrl": ".", // 设置解析非相对模块名称的基本目录 "paths": { "@/*": ["src/*"] } // 设置模块名称到基于 baseUrl 的路径映射 }, "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] // 指定要编译的路径列表 }
2. UnoCSS
官网地址:UnoCSS: The instant on-demand Atomic CSS engine
2.1 安装
pnpm add -D unocss
安装插件
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import { resolve } from 'path'; import UnoCSS from 'unocss/vite'; export default defineConfig({ resolve: { alias: { '@': resolve(__dirname, 'src') } }, plugins: [vue(), UnoCSS()], server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } }, });
根目录下创建uno.config.ts文件
import { defineConfig } from 'unocss'; export default defineConfig({ // ...UnoCSS options });
添加virtual:uno.css到主入口,即main.ts文件
import { createApp } from 'vue'; import App from './App.vue'; import 'virtual:uno.css'; createApp(App).mount('#app');
2.2 预设
- Uno preset:默认预设,目前相当于@unocss/preset-wind
- Wind preset:Tailwind CSS / Windi CSS 兼容预设,继承了@unocss/preset-mini
- Mini preset:基础预设,只包含最基本的工具
- Icons preset:使用纯 CSS 的任意图标,图标数据源为 Iconify
- pnpm add -D @iconify-json/ic
- pnpm add -D @iconify-json/mdi
- pnpm add -D @iconify-json/line-md
- pnpm add -D @iconify-json/twemoji
- …
- Attributify preset:为其他预设启用属性模式
- Typography preset:提供一组可以用于为原生 HTML 添加排版默认值的文本类
- Tagify preset:为其他预设启用标签化模式
修改uno.config.ts文件
import { defineConfig, presetAttributify, presetIcons, presetTagify, presetTypography, presetUno, } from 'unocss'; export default defineConfig({ presets: [ presetUno(), presetIcons(), presetAttributify(), presetTypography(), presetTagify(), ], });
3. unplugin-auto-import
GitHub 地址:unplugin/unplugin-auto-import: Auto import APIs on-demand for Vite, Webpack and Rollup
pnpm i -D unplugin-auto-import
安装插件
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import { resolve } from 'path'; import UnoCSS from 'unocss/vite'; import AutoImport from 'unplugin-auto-import/vite'; export default defineConfig({ resolve: { alias: { '@': resolve(__dirname, 'src') } }, plugins: [ vue(), UnoCSS(), AutoImport({ imports: ['vue', 'vue-router', 'pinia'], dirs: [], vueTemplate: true, }), ], server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } }, });
当安装了 TypeScript 时,会应用默认配置,生成相关的./auto-imports.d.ts文件,即根目录下,但可以看到在tsconfig.app.json里编译路径列表只包含了src/下的文件,因此要手动添加进去,或者修改配置自定义生成文件路径
{ "compilerOptions": { "composite": true, // 是否编译构建引用项目 "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", // 指定文件用来存储增量编译信息 "target": "ES2020", // 用于指定编译之后的版本目标 "useDefineForClassFields": true, // 改变类属性声明的行为 "module": "ESNext", // 指定要使用的模块标准 "lib": ["ES2020", "DOM", "DOM.Iterable"], // 指定要包含在编译中的库文件 "skipLibCheck": true, // 跳过声明文件的类型检查 /* Bundler mode */ "moduleResolution": "bundler", // 模块解析策略 "allowImportingTsExtensions": true, // 允许在非 TypeScript 文件中导入 .ts 或 .tsx 文件 "resolveJsonModule": true, // 解析 JSON 模块 "isolatedModules": true, // 是否将每个文件作为单独的模块 "moduleDetection": "force", // 强制 TypeScript 将所有文件视为模块 "noEmit": true, // 不生成编译文件 "jsx": "preserve", // 指定 JSX 代码用于的开发环境 /* Linting */ "strict": true, // 是否启动所有类型检查 "noUnusedLocals": true, // 检查是否有定义但是没有使用的变量 "noUnusedParameters": true, // 检查是否有在函数体中没有使用的参数 "noFallthroughCasesInSwitch": true, // 检查 Switch 中是否有 Case 没有使用 break 跳出 /* Alias */ "baseUrl": ".", // 设置解析非相对模块名称的基本目录 "paths": { "@/*": ["src/*"] } // 设置模块名称到基于 baseUrl 的路径映射 }, // 指定要编译的路径列表 "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts" ] }
4. unplugin-vue-components
GitHub 地址:unplugin/unplugin-vue-components: ?? On-demand components auto importing for Vue
pnpm i unplugin-vue-components -D
安装插件
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import { resolve } from 'path'; import UnoCSS from 'unocss/vite'; import AutoImport from 'unplugin-auto-import/vite'; import Components from 'unplugin-vue-components/vite'; export default defineConfig({ resolve: { alias: { '@': resolve(__dirname, 'src') } }, plugins: [ vue(), UnoCSS(), AutoImport({ imports: ['vue', 'vue-router', 'pinia'], dirs: [], vueTemplate: true, }), Components(), ], server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } }, });
和 unplugin-auto-import 一样,会应用默认配置,生成相关的./components.d.ts文件,同样将其加入到编译路径列表
{ "compilerOptions": { "composite": true, // 是否编译构建引用项目 "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", // 指定文件用来存储增量编译信息 "target": "ES2020", // 用于指定编译之后的版本目标 "useDefineForClassFields": true, // 改变类属性声明的行为 "module": "ESNext", // 指定要使用的模块标准 "lib": ["ES2020", "DOM", "DOM.Iterable"], // 指定要包含在编译中的库文件 "skipLibCheck": true, // 跳过声明文件的类型检查 /* Bundler mode */ "moduleResolution": "bundler", // 模块解析策略 "allowImportingTsExtensions": true, // 允许在非 TypeScript 文件中导入 .ts 或 .tsx 文件 "resolveJsonModule": true, // 解析 JSON 模块 "isolatedModules": true, // 是否将每个文件作为单独的模块 "moduleDetection": "force", // 强制 TypeScript 将所有文件视为模块 "noEmit": true, // 不生成编译文件 "jsx": "preserve", // 指定 JSX 代码用于的开发环境 /* Linting */ "strict": true, // 是否启动所有类型检查 "noUnusedLocals": true, // 检查是否有定义但是没有使用的变量 "noUnusedParameters": true, // 检查是否有在函数体中没有使用的参数 "noFallthroughCasesInSwitch": true, // 检查 Switch 中是否有 Case 没有使用 break 跳出 /* Alias */ "baseUrl": ".", // 设置解析非相对模块名称的基本目录 "paths": { "@/*": ["src/*"] } // 设置模块名称到基于 baseUrl 的路径映射 }, // 指定要编译的路径列表 "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts", "components.d.ts" ] }
5. Vue Router
官网地址:Vue Router | Vue.js 的官方路由
pnpm add vue-router@4
创建src/router/index.ts文件
import { createRouter, createWebHistory } from 'vue-router'; const routes = [{ path: '/', component: () => import('@/App.vue') }]; const router = createRouter({ history: createWebHistory(), routes, scrollBehavior(_to, _from, savedPosition) { return savedPosition ? savedPosition : { left: 0, top: 0 }; }, }); export default router;
将src/router/index.ts添加到主入口
import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; import 'virtual:uno.css'; createApp(App).use(router).mount('#app');
6. Pinia
官网地址:Pinia | The intuitive store for Vue.js
pnpm install pinia
创建一个 pinia 实例(根 store)并将其传递给应用
import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; import { createPinia } from 'pinia'; import 'virtual:uno.css'; createApp(App).use(router).use(createPinia()).mount('#app');
创建一个src\pinia\index.ts文件
export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), getters: { double: (state) => state.count * 2, }, actions: { increment() { this.count++; }, }, });
7. Axios
官网地址:Axios
pnpm install axios
创建src\request\index.ts文件,自定义一个 Axios 实例
import axios from 'axios'; const request = axios.create({ timeout: 5000, headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, }); // 请求拦截器 request.interceptors.request.use( (config) => { return config; }, (error) => { return Promise.reject(error); } ); // 响应拦截器 request.interceptors.response.use( (response) => { return response; }, (error) => { if (error.response) { switch (error.response.status) { case 401: // 未认证 break; case 403: // 未授权 break; case 404: // 资源未找到 break; case 408: // 超时 break; case 500: // 服务器错误 break; default: // 未知错误 break; } } return Promise.reject(error); } ); export default request;
8. Element Plus(可选)
官网地址:一个 Vue 3 UI 框架 | Element Plus
自动导入
import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import { resolve } from 'path'; import UnoCSS from 'unocss/vite'; import AutoImport from 'unplugin-auto-import/vite'; import Components from 'unplugin-vue-components/vite'; import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'; export default defineConfig({ resolve: { alias: { '@': resolve(__dirname, 'src') } }, plugins: [ vue(), UnoCSS(), AutoImport({ imports: ['vue', 'vue-router', 'pinia'], dirs: ['src/router', 'src/request'], vueTemplate: true, resolvers: [ElementPlusResolver()], }), Components({ resolvers: [ElementPlusResolver()], }), ], server: { port: 3000, proxy: { '/api': 'http://localhost:8080' } }, });
本站大部分文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了您的权益请来信告知我们删除。邮箱:1451803763@qq.com