1、创建项目
cmd
npm create vite@latest my-vue3-ts-project -- --template vue-ts
2、进入项目目录,安装依赖,运行项目
cmd
cd my-vue3-ts-project
npm install
npm run dev
3、配置环境加代理
- 1、新增.env.development文件
ts
# 页面标题
VITE_APP_TITLE = 学习从零搭建
# 开发环境配置
VITE_APP_ENV = 'development'
# 物业管理系统管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'
# 开发环境跨域代理,支持配置多个
VITE_PROXY = [["/dev-api","http://localhost:2547"]]
VITE_PORT = 8080
- 2、新增.env.production文件
ts
# 页面标题
VITE_APP_TITLE = 学习从零搭建
# 生产环境配置
VITE_APP_ENV = 'production'
# 物业管理系统/生产环境
VITE_APP_BASE_API = '/prod-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip
VITE_PROXY = [["/prod-api","https://hahaha.cn"]]
VITE_PORT = 2322
- 3、根目录下新建build/proxy.ts文件
ts
import type { ProxyOptions } from "vite";
type ProxyItem = [string, string];
type ProxyList = ProxyItem[];
type ProxyTargetList = Record<string, ProxyOptions>;
/**
* 创建代理,用于解析 .env.development 代理配置
* @param list
*/
export function createProxy(list: ProxyList = []) {
const ret: ProxyTargetList = {};
for (const [prefix, target] of list) {
const httpsRE = /^https:\/\//;
const isHttps = httpsRE.test(target);
// https://github.com/http-party/node-http-proxy#options
ret[prefix] = {
target: target,
changeOrigin: true,
ws: true,
rewrite: path => path.replace(new RegExp(`^${prefix}`), ""),
// https is require secure=false
...(isHttps ? { secure: false } : {})
};
}
return ret;
}
-
4、根目录下新建vite\plugins文件夹,再新建index.js、setup-extend.js、compression.js文件
- setup-extend.js文件
jsimport setupExtend from "vite-plugin-vue-setup-extend"; /** * * @returns 命名组件 * <script setup name="MyComponent"> // 你的逻辑代码 </script> <template> <div>这是我的组件</div> </template> */ export default function createSetupExtend() { return setupExtend(); }
- compression.js文件
jsimport compression from 'vite-plugin-compression' /** * * 功能特性 Gzip 压缩:生成 .gz 文件。 Brotli 压缩:生成 .br 文件。Brotli 通常比 Gzip 提供更好的压缩率。 自定义压缩选项:允许配置压缩级别、最小文件大小等参数。 删除原始文件:根据配置决定是否在生成压缩版本后删除原始文件。 */ export default function createCompression(env) { const { VITE_BUILD_COMPRESS } = env const plugin = [] if (VITE_BUILD_COMPRESS) { const compressList = VITE_BUILD_COMPRESS.split(',') if (compressList.includes('gzip')) { // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 plugin.push( compression({ ext: '.gz', deleteOriginFile: false }) ) } if (compressList.includes('brotli')) { plugin.push( compression({ ext: '.br', algorithm: 'brotliCompress', deleteOriginFile: false }) ) } } return plugin }
- index.js
jsimport vue from '@vitejs/plugin-vue' import createCompression from './compression' import createSetupExtend from './setup-extend' export default function createVitePlugins(viteEnv, isBuild = false) { const vitePlugins = [vue()] vitePlugins.push(createSetupExtend()) isBuild && vitePlugins.push(...createCompression(viteEnv)) return vitePlugins }
-
5、配置vite.config.ts
ts
import { defineConfig, loadEnv } from "vite";
import path from "path";
import { createProxy } from "./build/proxy";
import createVitePlugins from "./vite/plugins";
// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd());
const { VITE_APP_ENV, VITE_PROXY, VITE_PORT } = env;
const port = parseInt(VITE_PORT, 10) || 3000;
if (isNaN(port)) {
throw new Error("VITE_PORT 必须是一个有效的数字");
}
const proxyList = JSON.parse(VITE_PROXY || "[]");
return {
base: VITE_APP_ENV === "production" ? "/" : "/",
plugins: [
createVitePlugins(env, command === "build"),
Components({
dirs: ["src/components"],
extensions: ["vue"],
dts: "./components.d.ts",
}),
],
resolve: {
alias: {
"~": path.resolve(__dirname, "./"),
"@": path.resolve(__dirname, "./src"),
},
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
},
server: {
port: port,
host: true,
open: true,
proxy: createProxy(proxyList),
},
css: {
postcss: {
plugins: [
{
postcssPlugin: "internal:charset-removal",
AtRule: {
charset: (atRule) => {
if (atRule.name === "charset") {
atRule.remove();
}
},
},
},
],
},
},
};
});
4、集成组件库element-plus
- 1、安装element
cmd
npm install element-plus --save
- 2、安装自动导入插件
cmd
npm i unplugin-auto-import --save
npm i unplugin-vue-components --save
- 3、配置vite.config.ts
ts
import { defineConfig } from "vite";
// 按需导入element-plus的更多组件
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(),
// 打补丁
AutoImport({
imports: ["vue"],
dts: "./auto-imports.d.ts",
resolvers: [ElementPlusResolver()],
}),
Components({
dirs: ["src/components"],
extensions: ["vue"],
resolvers: [ElementPlusResolver()],
dts: "./components.d.ts",
}),
]
})
- 4、在main.ts文件中添加
ts
import 'element-plus/dist/index.css'
5、集成Tailwind CSS
官网:www.tailwindcss.cn/docs/instal...
ts
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest @tailwindcss/vite
- 1、vite.config.ts
ts
import tailwindcss from'@tailwindcss/vite'
plugins: [
tailwindcss(),
],
- 2、在src\assets\style 文件夹下新增tailwind.css
css
@import "tailwindcss";
- 3、main.ts
ts
import './styles/tailwind.css'
6、集成@headlessui/vue
@headlessui/vue
是一个完全无 UI 的组件库,专门为 Vue.js 框架设计。它由 Tailwind CSS 团队创建,旨在提供无障碍(accessibility)良好、灵活且易于定制的组件。这些组件不带有任何默认样式,允许开发者根据自己的设计系统或视觉需求自由地添加样式。
主要特点
- 无障碍优先:所有组件都考虑到了无障碍的需求,使得它们可以被屏幕阅读器等辅助技术良好支持。
- 无默认样式:因为它是"Headless"的,意味着没有预设的样式,所以你可以完全控制组件的外观。
- 易于集成:与 Tailwind CSS 配合使用效果尤佳,但也可以与其他CSS框架或自定义样式一起使用。
- 丰富的交互组件:包括对话框、下拉菜单、开关、标签组等常见的UI组件,但没有具体的视觉表示形式。
cmd
pnpm install @heroicons/vue
pnpm install @headlessui/vue
7、安装分析工具
rollup-plugin-visualizer
是一个用于分析和可视化 JavaScript 包(bundle)组成的插件,它通常与 Rollup 打包工具一起使用。尽管名字中提到的是 Rollup,但实际上它也可以与其他构建工具如 Vite 一起使用,因为 Vite 在内部使用了 Rollup 进行打包。
主要用途
- 分析包大小:帮助你了解你的应用或库的最终打包结果中每个模块或依赖项的大小。
- 优化建议:通过可视化的方式展示各个模块在最终包中的占比,从而帮助开发者识别出哪些部分可能需要优化,比如是否有些依赖被不必要的包含进来,或者是否存在重复导入等问题。
- 性能调优:基于分析结果进行代码分割、懒加载等策略调整,以提高应用加载速度和整体性能。
cmd
pnpm install rollup-plugin-visualizer
- vite.config.ts
ts
import{ visualizer }from'rollup-plugin-visualizer'
plugins: [
visualizer({
filename: './dist/stats.html', // 输出文件路径
open: true, // 构建完成后自动打开浏览器显示统计页面
gzipSize: true, // 显示Gzip压缩后的大小
brotliSize: true, // 显示Brotli压缩后的大小
template: 'sunburst', // 图表类型: 'treemap' | 'sunburst' | 'network'
}) as any // 类型断言,避免类型不兼容问题
]