当前位置: 首页 > news >正文

使用vite创建vue+ts项目,整合常用插件(scss、vue-router、pinia、axios等)和配置

一、检查node版本

指令:node -v
为什么要检查node版本?

Vite 需要 Node.js 版本 18+,20+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。

二、创建vite项目

指令:npm create vite@latest vue-ts-app -- --template vue-ts
参考vite官网

模板(template):

:::info
vanilla,vanilla-ts, vue, vue-ts,react,react-ts,react-swc,react-swc-ts,preact,preact-ts,lit,lit-ts,svelte,svelte-ts,solid,solid-ts,qwik,qwik-ts
:::

三、运行项目

安装插件:npm install
运行项目:npm run dev

{"name": "vue-ts-app","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite","build": "vue-tsc && vite build","preview": "vite preview"},"dependencies": {"vue": "^3.3.11"},"devDependencies": {"@vitejs/plugin-vue": "^4.5.2","typescript": "^5.2.2","vite": "^5.0.8","vue-tsc": "^1.8.25"}
}

四、安装element plus

  1. 安装指令:npm install element-plus --save
  2. 自动按需导入指令:npm install -D unplugin-vue-components unplugin-auto-import
  3. 在项目配置文件中配置如下代码:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
/** element plus 自动按需导入插件 start */
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
/** element plus 自动按需导入插件 end */// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),/** element plus 自动按需导入插件配置 start */AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver({ importStyle: 'sass' })] // importStyle: "sass" ---  解决覆盖element plus 的sass变量不生效的bug}),/** element plus 自动按需导入插件配置 end */],
})
  1. 测试element plus按需导入是否成功:
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script><template><div><!-- element plus组件 --><el-button type="primary">测试element plus</el-button><a href="https://vitejs.dev" target="_blank"><img src="/vite.svg" class="logo" alt="Vite logo" /></a><a href="https://vuejs.org/" target="_blank"><img src="./assets/vue.svg" class="logo vue" alt="Vue logo" /></a></div><HelloWorld msg="Vite + Vue" />
</template>

测试成功:
image.png

五、配置根目录别名

在vite.config.ts中配置:

import { fileURLToPath, URL } from 'node:url'export default defineConfig({plugins: [vue(),],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url)),},},
})

在tsconfig.json中配置:

"baseUrl": "./", // 解析非相对模块的基础地址,默认是当前目录"paths": {"@/*": ["./src/*"] // 路径映射,相对于baseUrl
}

image.png

六、安装scss

  1. 安装指令:npm install sass -D
  2. 定义一个scss文件:global.scss

image.png

$theme-color: gray;
$main-width: 100px;
$main-height: 100px;
  1. 在配置文件中配置全局scss文件
import { fileURLToPath, URL } from 'node:url'export default defineConfig({plugins: [vue(),],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url)),},},css: {preprocessorOptions: {// scss全局文件引入scss: {// additionalData: '@import "@/styles/global.scss";' 这行代码可能会导致报错additionalData: '@use "@/styles/global.scss" as *;' //建议使用这行代码},},},
})
  1. 在App.vue文件中进行测试
<template><el-button type="primary">测试element plus</el-button><div class="demo-box"><div class="tips">111111</div></div>
</template><style lang="scss" scoped>
/* 测试scss代码 */
.demo-box {background-color: $theme-color;width: $main-width;height: $main-height;.tips {color: red;}
}
</style>

七、配置eslint(代码检查)

  1. 安装pnpm:npm i -g pnpm
  2. 安装eslint:npm i eslint -D
  3. 初始化eslint:pnpm eslint --init

image.png

  1. 在项目的根目录下找到eslint配置文件:.eslintrc.json
{"env": {"browser": true,"es2021": true},"extends": ["eslint:recommended","plugin:@typescript-eslint/recommended","plugin:vue/vue3-essential"],"parserOptions": {"ecmaVersion": "latest","parser": "@typescript-eslint/parser","sourceType": "module"},"plugins": ["@typescript-eslint","vue"],"rules": {//}
}

解析:

  • env:表示eslint 运行的环境
  • extends:表示继承的规则
  • parserOptions:指定解析器选项
  • plugins:用到的插件
  • rules:检验规则,参考eslint官网规则
  1. 配置规则
{"env": {"browser": true,"es2021": true},"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:vue/vue3-essential"],"parserOptions": {"ecmaVersion": "latest","parser": "@typescript-eslint/parser","sourceType": "module"},"plugins": ["@typescript-eslint", "vue"],"rules": {"vue/script-setup-uses-vars": "error","vue/no-reserved-component-names": "off","@typescript-eslint/ban-ts-ignore": "off","@typescript-eslint/explicit-function-return-type": "off","@typescript-eslint/no-explicit-any": "off","@typescript-eslint/no-var-requires": "off","@typescript-eslint/no-empty-function": "off","vue/custom-event-name-casing": "off","no-use-before-define": "off","@typescript-eslint/no-use-before-define": "off","@typescript-eslint/ban-ts-comment": "off","@typescript-eslint/ban-types": "off","@typescript-eslint/no-non-null-assertion": "off","@typescript-eslint/explicit-module-boundary-types": "off","@typescript-eslint/no-unused-vars": "error","no-unused-vars": "error","space-before-function-paren": "off","vue/attributes-order": "off","vue/one-component-per-file": "off","vue/html-closing-bracket-newline": "off","vue/max-attributes-per-line": "off","vue/multiline-html-element-content-newline": "off","vue/singleline-html-element-content-newline": "off","vue/attribute-hyphenation": "off","vue/require-default-prop": "off","vue/require-explicit-emits": "off","vue/html-self-closing": ["error",{"html": {"void": "always","normal": "never","component": "always"},"svg": "always","math": "always"}],"vue/multi-word-component-names": "off"}
}
  1. 在项目根目录新建.eslintignore文件,用于配置哪些文件不用检测
dist
node_modules
  1. 在package.json中添加脚本
"scripts": {"lint": "eslint src","fix": "eslint src --fix"
},
  1. 检测eslint是否生效:由下图可得eslint有效

image.png

八、配置prettier,代码格式化、美化工具

  1. 安装prettier相关的插件:npm install -D eslint-plugin-prettier prettier eslint-config-prettier
  2. 在项目根目录下新建prettier的配置文件:.prettierrc.json
  3. 新建忽略文件:.prettierignore
/dist/*
/html/*
.local
/node_modules/**
**/*.svg
**/*.sh
/public/*
  1. 编辑配置:参考prettier官网
{"printWidth": 100, //每行最多显示的字符数"tabWidth": 2, //tab的宽度 2个字符"useTabs": false,//使用tab代替空格"semi": false,//结尾使用分号"vueIndentScriptAndStyle": false,"singleQuote": true, "quoteProps": "as-needed","bracketSpacing": true, "trailingComma": "none","jsxSingleQuote": false,"arrowParens": "always","insertPragma": false,"requirePragma": false,"proseWrap": "never","htmlWhitespaceSensitivity": "strict","endOfLine": "auto","rangeStart": 0
}
  1. 更新.eslintrc.json中的配置

在extends中新增代码:"plugin:prettier/recommended"

"extends": ["eslint:recommended","plugin:@typescript-eslint/recommended","plugin:vue/vue3-essential",// 新增的配置"plugin:prettier/recommended"
],
  1. 添加脚本"format": "prettier --write \"./**/*.{html,vue,js,ts,json,md}\" "
"scripts": {"dev": "vite","build": "vue-tsc && vite build","preview": "vite preview","lint": "eslint src","fix": "eslint src --fix","format": "prettier --write \"./**/*.{html,vue,js,ts,json,md}\" "
},
  1. vscode中设置保存自动格式化

image.png

九、配置组件自动按需导入

  1. 安装插件:npm i unplugin-vue-components -D
  2. vite.config.ts中配置自动导入规则
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'export default defineConfig({plugins: [vue(),Components({// 要搜索组件的目录的相对路径dirs: ['src/components', 'src/layout'],// 组件的有效文件扩展名extensions: ['vue', 'md'],// 搜索子目录deep: true,// 在哪些文件下自动导入组件include: [/\.vue$/, /\.vue\?vue/],// 生成自定义 `auto-components.d.ts` 全局声明dts: 'src/types/auto-components.d.ts',// 自定义组件的解析器resolvers: [ElementPlusResolver({ importStyle: 'sass' })], // importStyle: "sass" ---  解决覆盖element plus 的sass变量不生效的bug// 在哪些目录下不自动导入组件exclude: [/[\\/]node_modules[\\/]/]})],
})
  1. 保存配置文件,重新运行项目后,会发现项目自动生成了如下文件:

image.png

  1. 检查效果
  • 在components中新建BaseLink/index.vue组件
<template><div class="base-link"><slot></slot></div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped>
.base-link {font-size: 14px;font-weight: 500;color: green;cursor: pointer;&:hover {text-decoration: underline;}
}
</style>
  • 保存组件后,会发现在auto-components.d.ts文件中多出了对应的代码
export {}declare module 'vue' {export interface GlobalComponents {BaseLink: typeof import('./../components/BaseLink/index.vue')['default']ElButton: typeof import('element-plus/es')['ElButton']HelloWorld: typeof import('./../components/HelloWorld.vue')['default']}
}
  • 在App中使用BaseLink组件
<script setup lang="ts"></script><template><el-button type="primary">测试element plus</el-button><div class="demo-box"><div class="tips">111111</div></div><base-link>测试组件自动按需导入</base-link>
</template><style lang="scss" scoped>
.demo-box {background-color: $theme-color;width: $main-width;height: $main-height;.tips {color: red;}
}
</style>

发现可以正确使用:
image.png

十、插件自动引入

  1. 安装插件:npm i unplugin-auto-import -D
  2. 在配置文件中配置自动导入规则
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'export default defineConfig({plugins: [vue(),AutoImport({// 在哪些文件下自动导入include: [/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx/\.vue$/,/\.vue\?vue/, // .vue/\.md$/ // .md],// 自动导入的内容imports: ['vue'],// 配置文件生成位置,默认是根目录dts: 'src/types/auto-imports.d.ts',// eslint检查eslintrc: {enabled: true, // Default `false`filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')},resolvers: [ElementPlusResolver()]}),],
})
  1. 保存配置文件,重新运行项目,会自动生成如下文件:

image.png

  1. .eslintrc.json中修改配置,保证eslint检查不会报错

在extends中新增配置:

"extends": ["eslint:recommended","plugin:@typescript-eslint/recommended","plugin:vue/vue3-essential","plugin:prettier/recommended",".eslintrc-auto-import.json"
],
  1. 在App.vue中检验效果
<script setup lang="ts">
// 这里并未导入ref,eslint也未提示报错
const number = ref(1)const handleNumberChange = () => {number.value = number.value++
}
</script><template><el-button type="primary">测试element plus</el-button><div class="demo-box"><div class="tips">111111</div></div><base-link>测试组件自动按需导入</base-link><div>这是number值:{{ number }}</div><el-button @click="handleNumberChange">改变number值</el-button>
</template><style lang="scss" scoped>
.demo-box {background-color: $theme-color;width: $main-width;height: $main-height;.tips {color: red;}
}
</style>

十一、安装vue-router

  1. 安装插件:pnpm add vue-router@4
  2. 在src目录下新建router文件夹,结构如下:

image.png

  1. index.ts是路由的根文件,modules下的文件是各个路由模块
import type { App } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import remainingRouter from './modules/remaining'// 创建路由实例
const router = createRouter({history: createWebHistory(import.meta.env.VITE_BASE_PATH), // createWebHashHistory URL带#,createWebHistory URL不带#strict: true,routes: remainingRouter as RouteRecordRaw[],scrollBehavior: () => ({ left: 0, top: 0 })
})export const setupRouter = (app: App<Element>) => {app.use(router)
}export default router
const remainingRouter = [{path: '/test',name: 'TestPage',component: () => import('@/views/test/index.vue'),mate: {title: '测试页面'}}
]export default remainingRouter
  1. 新建test页面组件
<template><div><h1>这是test页面</h1><base-link @click="handleToHome">跳转至首页</base-link></div>
</template>
<script setup lang="ts" name="">
const router = useRouter()
const handleToHome = () => {router.push('/')
}
</script>
<style lang="scss" scoped></style>
  1. 在入口文件main.ts中引入
import { createApp } from 'vue'
import './style.css'
import './styles/reset.scss'
import App from './App.vue'
import router, { setupRouter } from '@/router'// 创建实例
const setupAll = async () => {const app = createApp(App)setupRouter(app)await router.isReady()app.mount('#app')
}setupAll()
  1. App.vue中测试效果
<script setup lang="ts">
// 这里并未导入ref,eslint也未提示报错
const number = ref(1)const handleNumberChange = () => {number.value++
}const router = useRouter()
const handleToTest = () => {router.push('/test')
}
</script><template><el-button type="primary">测试element plus</el-button><div class="demo-box"><div class="tips">111111</div></div><base-link>测试组件自动按需导入</base-link><div>这是number值:{{ number }}</div><el-button @click="handleNumberChange">改变number值</el-button><base-link @click="handleToTest">跳转至test页面</base-link><router-view />
</template><style lang="scss" scoped>
.demo-box {background-color: $theme-color;width: $main-width;height: $main-height;.tips {color: red;}
}
</style>

image.pngimage.png

十二、安装vite-plugin-vue-setup-extend插件,解决在setup中定义name问题

  1. 安装:pnpm i vite-plugin-vue-setup-extend -D
  2. 在vite.config.ts中配置:
import vueSetupExtend from 'vite-plugin-vue-setup-extend'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),vueSetupExtend(),]
})
  1. 在vue组件中定义name
  2. 注意:必须要注意的是当组件的script标签中的内容为空时,name还是不会生效

十三、安装pinia状态管理

  1. 安装:pnpm install pinia
  2. 在src目录下新建stores文件夹,结构如下:

image.png

  1. index.ts为根文件,counter.ts中存储的是各个模块数据
import type { App } from 'vue'
import { createPinia } from 'pinia'const store = createPinia()export const setupStore = (app: App<Element>) => {app.use(store)
}export { store }
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', () => {/*** ref() 就是 state 属性* computed() 就是 getters* function() 就是 actions,action中可以使用异步函数*///state:const count = ref(0)//getter:const getCount = computed<number>(() => {return count.value})//actions:const increment = () => {count.value++}//暴露state、computed、actions;否则无法使用return { count, getCount, increment }
})
  1. 在入口文件main.ts中引入
import { createApp } from 'vue'
import { setupStore } from '@/stores'// 创建实例
const setupAll = async () => {const app = createApp(App)setupStore(app)app.mount('#app')
}setupAll()
  1. 使用方法
<template><div><h1>这是test页面</h1><div>这是count:{{ counterStore.count }}</div></div>
</template>
<script setup lang="ts" name="TestPage">
import { useCounterStore } from '@/stores/modules/counter'
const counterStore = useCounterStore()
</script>
<style lang="scss" scoped></style>

十四、安装Axios请求插件

  1. 安装axios插件pnpm install axios -D
  2. 配置axios

一、在src根目录下创建如下目录:
api存储接口
axios存储配置文件
image.png
config.ts:

import axios, {AxiosError,type InternalAxiosRequestConfig,type AxiosInstance,type AxiosResponse
} from 'axios'const base_url = import.meta.env.BASE_URL
const request_timeout = import.meta.env.VITE_REQUEST_TIMEOUT// 创建axios实例
const service: AxiosInstance = axios.create({baseURL: base_url, // api 的 base_urltimeout: request_timeout, // 请求超时时间withCredentials: false // 禁用 Cookie
})/*** 请求拦截器*/
service.interceptors.request.use((config: InternalAxiosRequestConfig) => {// 配置请求头const token = '.....'config.headers.authorization = 'Bearer ' + tokenreturn config},(error: AxiosError) => {console.error('网络错误,请稍后重试')return Promise.reject(error)}
)/*** 响应拦截器*/
service.interceptors.response.use((response: AxiosResponse<any>) => {// 响应处理,如状态码return response},(error: AxiosError) => {return Promise.reject(error)}
)export { service }

index.ts:

import { service } from '@/axios/config'type AxiosHeaders = 'application/json' | 'application/x-www-form-urlencoded' | 'multipart/form-data'interface IAxiosConfig {base_url: stringresult_code: number | stringdefault_headers: AxiosHeadersrequest_timeout: number
}const default_headers: IAxiosConfig = {/*** api请求基础路径*/base_url: import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL,/*** 接口成功返回状态码*/result_code: 200,/*** 接口请求超时时间*/request_timeout: import.meta.env.VITE_REQUEST_TIMEOUT,/*** 默认接口请求类型* 可选值:application/x-www-form-urlencoded multipart/form-data*/default_headers: 'application/json'
}const request = (option: any) => {const { url, method, params, data, headersType, responseType } = optionreturn service({url: url,method,params,data,responseType: responseType,headers: {'Content-Type': headersType || default_headers}})
}export default {get: async <T = any>(option: any) => {const res = await request({ method: 'GET', ...option })return res.data as unknown as T},post: async <T = any>(option: any) => {const res = await request({ method: 'POST', ...option })return res.data as unknown as T},postOriginal: async (option: any) => {const res = await request({ method: 'POST', ...option })return res},delete: async <T = any>(option: any) => {const res = await request({ method: 'DELETE', ...option })return res.data as unknown as T},put: async <T = any>(option: any) => {const res = await request({ method: 'PUT', ...option })return res.data as unknown as T},download: async <T = any>(option: any) => {const res = await request({ method: 'GET', responseType: 'blob', ...option })return res as unknown as Promise<T>},upload: async <T = any>(option: any) => {option.headersType = 'multipart/form-data'const res = await request({ method: 'POST', ...option })return res as unknown as Promise<T>}
}

test.ts:

import request from '@/axios'export interface ITestDataParamsType {pageNo: numberpageSize: number
}/*** 获取测试数据* @param params 分页参数* @returns*/
export const getTestData = async (params: ITestDataParamsType) => {return await request.get({url: '/test/page',params})
}
  1. 调用接口
// template
<el-button @click="handleRequest">发起请求</el-button>// script
import { getTestData, type ITestDataParamsType } from '@/api/test'
const loading = ref(false)const handleRequest = async () => {loading.value = truetry {const params: ITestDataParamsType = {pageNo: 1,pageSize: 10}await getTestData(params)} finally {loading.value = false}
}

十五、安装vite-plugin-svg-icon插件,用于使用svg

  1. 安装:pnpm i vite-plugin-svg-icons -D
  2. 在main.ts中引入:import 'virtual:svg-icons-register'
  3. 在vite.config.ts中配置:
import path from 'path'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'export default defineConfig({plugins: [// ...createSvgIconsPlugin({// 图标存放的地址iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],symbolId: 'icon-[dir]-[name]',svgoOptions: {// 解决svg图标不显示的问题plugins: [{name: 'removeAttrs',active: true,params: { elemSeparator: ',', attrs: [] }}]}})]
})
  1. 封装svg-icon组件,用于使用svg图标
<template><svg class="svg-icon" aria-hidden :style="`width: ${props.size}; height: ${props.size};`"><use :xlink:href="symbolId" :fill="props.color" /></svg>
</template>
<script setup lang="ts" name="SvgIcon">
const props = defineProps({prefix: {type: String,default: 'icon'},name: {type: String,required: true},color: {type: String,default: ''},size: {type: String,default: '1em'}
})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
</script>
<style lang="scss" scoped>
.svg-icon {display: inline-block;outline: none;width: 1em;height: 1em;/* 因 icon 大小被设置为和字体大小一致,而 span 等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果 */vertical-align: -0.15em;/* 定义元素的颜色,currentColor 是一个变量,其值就是当前元素的 color 值,如果当前元素未设置 color 值,则从父元素继承 */fill: currentColor;overflow: hidden;
}
</style>
  1. 存放svg文件

image.png

  1. 使用:<svg-icon name="vue" size="24px" />

十六、安装vite-plugin-compression插件,项目打包时压缩文件

  1. 安装:pnpm i vite-plugin-compression -D
  2. 在vite.config.ts中进行配置:
export default defineConfig({plugins: [// ...viteCompression({verbose: true, // 是否在控制台输出压缩结果disable: false, // 是否禁用threshold: 10240, // 体积大于 threshold 才会被压缩,单位 balgorithm: 'gzip', // 压缩算法,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw']ext: '.gz', // 生成的压缩包后缀deleteOriginFile: false //压缩后是否删除源文件})],
})
  1. 打包,在控制台中查看压缩结果:

image.png

十七、VITE环境基本配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
/** element plus 自动按需导入插件 start */
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
/** element plus 自动按需导入插件 end */
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
import { fileURLToPath, URL } from 'node:url'
import path from 'path'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'import viteCompression from 'vite-plugin-compression'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),vueSetupExtend(),/** element plus 自动按需导入插件配置 start */AutoImport({// 在哪些文件下自动导入include: [/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx/\.vue$/,/\.vue\?vue/, // .vue/\.md$/ // .md],// 自动导入的内容imports: ['vue', 'vue-router'],// 配置文件生成位置,默认是根目录dts: 'src/types/auto-imports.d.ts',// eslint检查eslintrc: {enabled: true, // Default `false`filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')},resolvers: [ElementPlusResolver()]}),Components({// 要搜索组件的目录的相对路径dirs: ['src/components', 'src/layout'],// 组件的有效文件扩展名extensions: ['vue', 'md'],// 搜索子目录deep: true,// 在哪些文件下自动导入组件include: [/\.vue$/, /\.vue\?vue/],// 生成自定义 `auto-components.d.ts` 全局声明dts: 'src/types/auto-components.d.ts',// 自定义组件的解析器resolvers: [ElementPlusResolver({ importStyle: 'sass' })], // importStyle: "sass" ---  解决覆盖element plus 的sass变量不生效的bug// 在哪些目录下不自动导入组件exclude: [/[\\/]node_modules[\\/]/]}),/** element plus 自动按需导入插件配置 end */createSvgIconsPlugin({iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],symbolId: 'icon-[dir]-[name]',svgoOptions: {// 解决svg图标不显示的问题plugins: [{name: 'removeAttrs',active: true,params: { elemSeparator: ',', attrs: [] }}]}}),viteCompression({verbose: true, // 是否在控制台输出压缩结果disable: false, // 是否禁用threshold: 10240, // 体积大于 threshold 才会被压缩,单位 balgorithm: 'gzip', // 压缩算法,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw']ext: '.gz', // 生成的压缩包后缀deleteOriginFile: false //压缩后是否删除源文件})],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}},css: {preprocessorOptions: {// scss全局文件引入scss: {additionalData: '@use "@/styles/global.scss" as *;'}}},// 打包配置build: {minify: 'terser', // 指定使用哪种混淆器outDir: 'dist', // 指定输出路径sourcemap: false, // 构建后是否生成 source map 文件terserOptions: {// 传递给 Terser 的更多 minify 选项compress: {drop_debugger: true, // 打包时去除debuggerdrop_console: true // 打包时去除console}},// 静态文件按类型分包rollupOptions: {output: {chunkFileNames: 'static/js/[name]-[hash].js',entryFileNames: 'static/js/[name]-[hash].js',assetFileNames: 'static/[ext]/[name]-[hash].[ext]'}}}
})

相关文章:

使用vite创建vue+ts项目,整合常用插件(scss、vue-router、pinia、axios等)和配置

一、检查node版本 指令&#xff1a;node -v 为什么要检查node版本&#xff1f; Vite 需要 Node.js 版本 18&#xff0c;20。然而&#xff0c;有些模板需要依赖更高的 Node 版本才能正常运行&#xff0c;当你的包管理器发出警告时&#xff0c;请注意升级你的 Node 版本。 二、创…...

泛型、Trait 和生命周期(上)

目录 1、提取函数来减少重复 2、在函数定义中使用泛型 3、结构体定义中的泛型 4、枚举定义中的泛型 5、方法定义中的泛型 6、泛型代码的性能 每一门编程语言都有高效处理重复概念的工具。在 Rust 中其工具之一就是 泛型&#xff08;generics&#xff09;。泛型是具体类型…...

<网络安全>《18 数据安全交换系统》

1 概念 企业为了保护核心数据安全&#xff0c;都会采取一些措施&#xff0c;比如做网络隔离划分&#xff0c;分成了不同的安全级别网络&#xff0c;或者安全域&#xff0c;接下来就是需要建设跨网络、跨安全域的安全数据交换系统&#xff0c;将安全保障与数据交换功能有机整合…...

Kafka 生产调优

Kafka生产调优 文章目录 Kafka生产调优一、Kafka 硬件配置选择场景说明服务器台数选择磁盘选择内存选择CPU选择 二、Kafka Broker调优Broker 核心参数配置服役新节点/退役旧节点增加副本因子调整分区副本存储 三、Kafka 生产者调优生产者如何提高吞吐量数据可靠性数据去重数据乱…...

springboot162基于SpringBoot的体育馆管理系统的设计与实现

体育馆管理系统 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本体育馆管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕…...

Interpolator:在Android中方便使用一些常见的CubicBezier贝塞尔曲线动画效果

说明 方便在Android中使用Interpolator一些常见的CubicBezier贝塞尔曲线动画效果。 示意图如下 import android.view.animation.Interpolator import androidx.core.view.animation.PathInterpolatorCompat/*** 参考* android https://yisibl.github.io/cubic-bezier* 实现常…...

Nacos安装,服务注册,负载均衡配置,权重配置以及环境隔离

1. 安装 首先从官网下载 nacos 安装包&#xff0c;注意是下载 nacos-server Nacos官网 | Nacos 官方社区 | Nacos 下载 | Nacos 下载完毕后&#xff0c;解压找到文件夹bin&#xff0c;文本打开startup.cmd 修改配置如下 然后双击 startup.cmd 启动 nacos服务&#xff0c;默认…...

Vue3导出数据为txt文件

在Vue3中&#xff0c;可以通过使用Blob对象以及URL.createObjectURL()方法导出txt文档。 首先&#xff0c;你需要在Vue组件中创建一个方法来生成txt文档的内容。 //res.value.code 数据源 //type&#xff1a;格式设置 //form.name是下载文件的自定义名字 const downLoad ()&…...

Simulink中getConfigSet用法

目录 语法 说明 示例 获取配置集 getConfigSet的功能是从模型中获取配置集或配置引用。 语法 myConfigObj getConfigSet(model, configObjName) 说明 myConfigObj getConfigSet(model, configObjName) 返回关联到 model 并命名为 configObjName 的配置集或配置引用。 …...

【Algorithms 4】算法(第4版)学习笔记 05 - 2.2 归并排序

文章目录 前言参考目录学习笔记1&#xff1a;归并排序的简单演示1.1&#xff1a;基本思路1.2&#xff1a;归并排序的 demo 演示1.3&#xff1a;代码实现2&#xff1a;自顶向下的归并排序2.1&#xff1a;比较次数与访问次数的证明2.2&#xff1a;代码优化2.3&#xff1a;优化后代…...

mybatis mapper sql include用法实现sql块复用

一、总SQL <select id"getxxxMonitorData"resultType"com.xxx.module.system.dal.dataobject.xxx.xxxDO"><include refid"getxxxMonitorDataBaseSql"></include><include refid"whereContent"></include&…...

正点原子--STM32通用定时器学习笔记(2)

1. 通用定时器输入捕获部分框图介绍 捕获/比较通道的输入部分&#xff08;通道1&#xff09; 采样频率&#xff1a;控制寄存器 1(TIMx_CR1)的CKD[1:0] ⬇⬇⬇​​​​​​​滤波方式选择&#xff1a; 捕获/ 比较模式寄存器 1(TIMx_CCMR1)的输入捕获部分⬇​​​​​​​⬇​…...

Flask实现异步调用sqlalchemy的模型类

事情是这样的&#xff0c;我这边需要在一次请求里面&#xff0c;搞一个异步不阻碍的任务&#xff0c;来执行耗时的操作。 一开始&#xff0c;我准备写的代码是这样的&#xff1a; from flask import Flask import time from concurrent.futures import ThreadPoolExecutorexec…...

Pocket2Mol + Generation of Atom Positions生成原子位置的方法有什么?联合概率是什么?

联合概率&#xff1a; 联合概率是统计学中的一个概念&#xff0c;用于描述两个或多个随机事件同时发生的概率。当我们谈论多个变量的联合概率时&#xff0c;我们是在探讨这些变量同时取特定值的概率。 让我们简化一下概念&#xff1a; 假设你有一个骰子&#xff08;六面&…...

区分手机小程序以及电脑小程序;左滑、导航键返回拦截

1、区分电脑小程序和手机小程序 //区分电脑小程序、手机小程序&#xff08;目标&#xff1a;手机小程序&#xff09; // #ifdef MP-WEIXIN uni.getSystemInfo({success: (res) > {// windows | mac为pc端// android | ios为手机端// console.log(getSystemInfo,, res.plat…...

Web APIs 2 事件

Web APIs 2 事件 事件监听案例&#xff1a;广告关闭案例&#xff1a;随机问答 事件监听版本事件类型案例&#xff1a;轮播图完整焦点事件键盘事件输入事件案例&#xff1a;评论字数统计 事件对象获取事件对象事件对象常用属性案例&#xff1a;评论回车发布 环境对象this回调函数…...

网易腾讯面试题精选----90道设计模式面试题及答案

介绍 设计模式是软件开发的重要组成部分,为常见设计问题提供经过验证的解决方案。就设计模式面试候选人可以帮助衡量他们对软件架构的理解、解决问题的能力以及编写可维护和可扩展代码的能力。以下是一些常见的设计模式面试问题和答案,可帮助评估候选人在该领域的知识和专业知…...

程序员的数字化工作台:理解不关机背后的逻辑与需求

目录 程序员为什么不喜欢关电脑&#xff1f; 电脑对程序员的重要性&#xff1a; 工作流程与需求&#xff1a; 数据安全与备份&#xff1a; 即时性与响应&#xff1a; 个人习惯等方面&#xff1a; 程序员为什么不喜欢关电脑&#xff1f; 电脑对程序员的重要性&#xff1a;…...

Java Socket Server TCP服务端向指定客户端发送消息

实现思路 首先需要知道java里如何创建一个Socket服务器端。 //创建一个服务器端对象ServerSocket server new ServerSocket(); //绑定启动的ip和端口号server.bind(new InetSocketAddress("127.0.0.1",8082));//启动成功后&#xff0c;调用accept()方法阻塞&#xf…...

java日志框架总结(五、logback日志框架)

一、logback概述 Logback是由log4j创始人设计的又一个开源日志组件。 Logback当前分成三个模块&#xff1a; 1、logback-core, 2、logback- classic 3、logback-access。 1&#xff09;logback-core是其它两个模块的基础模块。 2&#xff09;logback-…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...