vite配置
1.package
{
"name": "newspublish",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --mode development",
"build": "vue-tsc && vite build --mode production",
"preview": "vite preview --mode development",
"ts": "vue-tsc --noEmit",
"test": "vitest --config ./vitest.config.ts",
"coverage": "vitest --config ./vitest.config.ts run --coverage",
"db": "json-server --watch --port 8080 --delay 2000 ./src/jsonServer/newsDB.json --static ./src/assets"
},
"dependencies": {
"@ant-design/icons-vue": "^6.1.0",
"ant-design-vue": "^3.2.20",
"axios": "^1.4.0",
"element-plus": "^2.3.4",
"js-cookie": "^3.0.5",
"json-server": "^0.17.3",
"pinia": "^2.0.36",
"pinia-plugin-persist": "^1.0.0",
"postcss-preset-env": "^8.3.2",
"store2": "^2.14.2",
"unplugin-auto-import": "^0.15.3",
"unplugin-vue-components": "^0.24.1",
"vue": "^3.2.47",
"vue-router": "^4.2.0"
},
"devDependencies": {
"@types/js-cookie": "^3.0.3",
"@types/node": "^20.1.3",
"@vitejs/plugin-vue": "^4.1.0",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"typescript": "^5.0.2",
"vite": "^4.3.2",
"vitest": "^0.31.0",
"vue-tsc": "^1.4.2"
},
"description": "This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.",
"main": "index.js",
"author": "",
"license": "ISC"
}
2.tsconfig.json
{
"compilerOptions": {
// 将代码编译为最新版本的 JS
"target": "ESNext",
// 使用 ES Module 格式打包编译后的文件
"module": "ESNext",
// 使用 Node 的模块解析策略
"moduleResolution": "node",
// 引入 ES 最新特性和 DOM 接口的类型定义
"lib": ["ESNext", "DOM", "DOM.Iterable"],
// 跳过对 .d.ts 文件的类型检查
"skipLibCheck": true,
// 允许引入 JSON 文件
"resolveJsonModule": true,
// 要求所有文件都是 ES Module 模块。
"isolatedModules": true,
// 不输出文件,即编译后不会生成任何js文件
"noEmit": true,
// 保留原始的 JSX 代码,不进行编译
"jsx": "preserve",
// 开启所有严格的类型检查
"strict": true,
// 报告未使用的局部变量的错误
"noUnusedLocals": true,
// 报告函数中未使用参数的错误
"noUnusedParameters": true,
// 确保switch语句中的任何非空情况都包含
"noFallthroughCasesInSwitch": true,
// 允许使用 import 引入使用 export = 导出的内容
"esModuleInterop": true,
// 允许使用js
"allowJs": true,
// 查询的基础路径
"baseUrl": ".",
// 路径映射,配合别名使用
"paths": {
"@/*": ["src/*"],
"#/*": ["types/*"]
},
"types": ["element-plus/global","node"]
},
// 需要检测的文件
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
// 为文件进行不同配置
"references": [
{
"path": "./tsconfig.node.json"
}
]
}
3.vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import Components from "unplugin-vue-components/vite";
import {
AntDesignVueResolver,
ElementPlusResolver,
} from "unplugin-vue-components/resolvers";
import AutoImport from "unplugin-auto-import/vite";
// 这个path用到了上面安装的 @types/node
import path from "path";
import postcssPresetEnv from "postcss-preset-env";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [AntDesignVueResolver(), ElementPlusResolver()],
}),
],
// 在这里进行配置别名
resolve: {
alias: {
// @代替src
"@": path.resolve("./src"),
// #代替types
"#": path.resolve("./types"),
},
},
css: {
modules: {
// 转换类名(camelCase为驼峰、camelCaseOnly只为驼峰其他都被替换、
// dashes为中划线、dashesOnly为只能是中划线)
localsConvention: "dashes",
// 设置样式是否是局部的 local(默认)生成hash,global全局样式
scopeBehaviour: "local",
// 设置样式命名方式
// generateScopedName:"[hash:5]_[name]_local"
generateScopedName: (name, filename, css) => {
return `${name}${filename}${css}`;
},
// 默认类名+其他字符串(文件名、随机)加入到hash生成中
hashPrefix: "myPro",
// 不解析该文件样式名,一般用于引入第三方
globalModulePaths: [/base.module.css/g],
},
// 预处理器(常用)
preprocessorOptions: {
// 整个配置会再less执行的时候当作参数提交执行lessc,所以怎么配置看less文档
less: {
//可以使用 100/2px --math="always"
math: "always",
// 定义全局的样式变量
globalVars: {},
// 可以用来导入全局变量文件(常用)
additionalData: `@import '@/styles/base.less';`,
//开启css映像索引,生产环境定位问题文件
sourceMap: true,
javascriptEnabled: true,
},
},
postcss: {
// 设置css后处理,类似js中babel,兼容低版本页面。加载默认配置
plugins: [postcssPresetEnv({ browsers: "last 2 versions" })],
},
},
build: {
// rollup打包配置,具体看rollupAPI
rollupOptions: {
output: {
assetFileNames: "[hash]-[name][extname]",
},
},
// 4kb以下去打包成base64
assetsInlineLimit: 4096,
// 指定输出路径
outDir: "dist",
//指定静态资源路径
assetsDir: "static",
//打包前清空文件,默认true
emptyOutDir: true,
},
define: {
"process.env": process.env,
},
});
4..env.development
NODE_ENV=dev
VITE_APP_API_URL=http://localhost:8080/
5.typing.d.ts
import { ComponentCustomProperties } from "@vue/runtime-core";
import { MessageApi } from "ant-design-vue/lib/message";
import { StoreType } from "store2";
// 声明 window 上自定义属性,如事件总线
declare interface Window {
eventBus: any;
}
// 声明 .vue 文件
declare module '*.vue' {
import { DefineComponent } from 'vue';
const component: DefineComponent<object, object, any>;
export default component;
}
// ts声明全局参数,不然this会报不存在属性
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$message: MessageApi; // 这里填类型
$localStore:StoreType
}
}
6.main.ts
import { createApp } from "vue";
import "./style.css";
import { createPinia } from "pinia";
import piniaPluginPersist from "pinia-plugin-persist";
import router from "./router";
import AppVue from "./App.vue";
import "ant-design-vue/dist/antd.css";
import "element-plus/dist/index.css";
import { Button, message } from "ant-design-vue";
import "./utils/ajaxUtil";
import localStore from "store2";
const pinia = createPinia();
pinia.use(piniaPluginPersist);
const app = createApp(AppVue);
app.use(router);
app.use(pinia);
app.use(Button);
message.config({
maxCount: 1,
});
app.config.globalProperties.$message = message;
app.config.globalProperties.$localStore = localStore;
app.config.globalProperties.$testMsg = "testMsg";
app.mount("#app");
7.routes/index.ts
import { createRouter, createWebHashHistory } from "vue-router";
import routes from "./routes";
import { message } from "ant-design-vue";
const router = createRouter({
history: createWebHashHistory(),
routes,
});
//全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to, from, next) => {
localStorage.setItem("path", to.path);
const hide = message.loading('加载中···');
//如果路由需要跳转
if (to.meta.isAuth) {
//判断 如果user-status本地存储是login的时候,可以进去
if (localStorage.getItem("user-status") === "login") {
hide();
next(); //放行
} else {
// next(); //放行
alert("抱歉,您无权限查看!");
next("/login"); //放行
setTimeout(() => {
hide();
location.reload();
}, 1000);
// location.reload();
}
} else {
// 否则,放行
next();
}
});
//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to, from) => {
(document as any).title = to.meta.title || "默认名"; //修改网页的title
});
export default router;
8.useStore.ts
import { defineStore } from "pinia";
export const useNoiseStatistics = defineStore({
id: "counter",
state: () => ({}),
getters: {},
actions: {},
});
9.example
9.1 no setup
no setup
<script lang="ts">
import { useMainStore } from "@/store/useMainStore";
import { mapWritableState, mapActions } from "pinia";
export default {
setup() {},
data: () => ({
testData: "test",
}),
computed: {
...mapWritableState(useMainStore, {
hello2: "helloPinia",
name2: "name",
loading: "loading",
newName: "newName",
}),
hello() {
return this.hello2;
},
},
methods: {
...mapActions(useMainStore, ["changeHello2", "changeHello", "setUser"]),
changePinia() {
this.hello2 = "test";
},
actionTest1() {
this.changeHello();
},
actionTest2() {
this.changeHello2();
},
reset() {
// this.$s
},
},
};
</script>
<template>
<hr />
<div>异步测试</div>
<p>{{ testData }}</p>
<hr />
<div class="pinia">
<p>setup:{{ hello }}</p>
<p>nosetup:{{ hello2 }}</p>
<p>async set:{{ name2 || "notSet" }}</p>
<p>async getter:{{ newName || "notSet" }}</p>
<div>
<button @click="changePinia">state change pinia</button>
<button @click="actionTest1">setUp change pinia</button>
<button @click="actionTest2">mapAction change pinia</button>
<button @click="setUser">{{ !loading ? "async" : "loading···" }}</button>
<hr />
<button @click="reset">重置</button>
</div>
</div>
</template>
<style></style>
9.2 setup
setup
<script lang="ts" setup>
import { getCurrentInstance } from "vue";
import { PoweroffOutlined } from "@ant-design/icons-vue";
// import { useNewsStore } from "@/store/useNewsStore";
// import { storeToRefs } from "pinia";
// console.log("vue-env", import.meta.env, import.meta.env.VITE_APP_TAG);
const { proxy } = getCurrentInstance() as any;
// const newsStore = useNewsStore();
// const { user } = storeToRefs(newsStore);
// newsStore.setUser();
// const input = ref("");
const test = () => {
proxy?.$message.error("这是一个测试");
};
</script>
<template>
<a-button type="primary" @click="test">
<template #icon><PoweroffOutlined /></template>
主页</a-button
>
</template>