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

news2024/10/6 5:59:39

一、检查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_url
  timeout: request_timeout, // 请求超时时间
  withCredentials: false // 禁用 Cookie
})

/**
 * 请求拦截器
 */
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 配置请求头
    const token = '.....'
    config.headers.authorization = 'Bearer ' + token
    return 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: string
  result_code: number | string
  default_headers: AxiosHeaders
  request_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 } = option
  return 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: number
  pageSize: 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 = true
  try {
    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 才会被压缩,单位 b
      algorithm: '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 才会被压缩,单位 b
      algorithm: '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, // 打包时去除debugger
        drop_console: true // 打包时去除console
      }
    },
    // 静态文件按类型分包
    rollupOptions: {
      output: {
        chunkFileNames: 'static/js/[name]-[hash].js',
        entryFileNames: 'static/js/[name]-[hash].js',
        assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
      }
    }
  }
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1438384.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot:web开发

web开发demo&#xff1a;点击查看 LearnSpringBoot05Web 点击查看更多的SpringBoot教程 技术摘要 webjarsBootstrap模板引擎thymeleaf嵌入式Servlet容器注册web三大组件 一、webjars webjars官网 简介 简介翻译 WebJars 是打包到 JAR&#xff08;Java Archive&#xff09;…

Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】

Java线程是怎么实现run方法的执行的呢&#xff1f;【 多线程在JVM中的实现原理剖析】 查看naive state0 方法JVM_StartThread 方法创建操作系统线程操作系统线程执行 本文转载-极客时间 我们知道Java线程是通过行start()方法来启动的&#xff0c;线程启动后会执行run方法内的代…

【Spring基础】从0开始学习Spring(2)

前言 在上篇文章&#xff0c;我已经讲了Spring中最核心的知识点&#xff1a;IoC&#xff08;控制反转&#xff09;以及DI&#xff08;依赖注入&#xff09;。这篇文章&#xff0c;我将讲一下关于Spring框架中的其它比较琐碎但是又还是挺重要的知识点&#xff0c;因此&#xff…

Excel——有效性、二级菜单联动

一、录入规范数据 1.手动输入序列录入有效性信息 选择需要录入有效性的所有单元格 选择【数据】——【有效性】——【有效性】 在【允许】输入的值之间选择【序列】 在【序列】输入框中输入想要选择的值&#xff0c;中间用逗号&#xff08;必须是英文逗号&#xff09;隔开 。…

[C/C++] -- Boost库、Muduo库编译安装使用

1.Muduo库 Muduo 是一个基于 C11 的高性能网络库&#xff0c;其核心是事件驱动、非阻塞 I/O、线程池等技术&#xff0c;以实现高并发、高性能的网络通信。Muduo 库主要由陈硕先生开发维护&#xff0c;已经成为 C 服务器程序员的常用工具之一。 Muduo 库的主要特点&#xff1a…

NLP_循环神经网络(RNN)

文章目录 RNN结构RNN实战RNN小结 RNN结构 NPLM 在处理长序列时会面临一些挑战。首先&#xff0c;由于它仍然是基于词的模型&#xff0c;因此在处理稀有词汇或者词汇表外的词汇时效果不佳。其次&#xff0c;NPLM不能很好地处理长距离依赖关系。而上面这两个局限&#xff0c;恰恰…

Python进阶--爬取下载人生格言(基于格言网的Python3爬虫)

目录 一、此处需要安装第三方库: 二、抓包分析及Python代码 1、打开人生格言网&#xff08;人生格言-人生格言大全_格言网&#xff09;进行抓包分析 2、请求模块的代码 3、抓包分析人生格言界面 4、获取各种类型的人生格言链接 5、获取下一页的链接 6、获取人生格言的…

基于Java (spring-boot)的酒店管理系统

一、项目介绍 本系统的使用者一共有酒店管理员和用户这两种角色: 1、酒店管理员功能&#xff1a; 登录&#xff1a;管理员可以通过登录功能进入系统&#xff0c;确保只有授权人员可以访问系统。 用户管理&#xff1a;管理员可以添加、编辑和删除酒店的用户&#xff0c;包括前…

【React】如何使antd禁用状态的表单输入组件响应点击事件?

最近遇到一个需求&#xff0c;需要在<Input.textarea>组件中&#xff0c;设置属性disabled为true&#xff0c;使textarea响应点击事件&#xff0c;但直接绑定onClick并不会在禁用状态下被响应。 解决方法1 之后尝试了很多方法&#xff0c;比如设置csspointer-events:no…

python30-Python的运算符结合性和优先级

1&#xff09;所有的数学运算都是从左向右进行的&#xff0c;Python 语言中的大部分运算符也是从左向右结合的&#xff0c;只有单目运算符、赋值运算符和三目运算符例外&#xff0c;它们是从右向左结合的&#xff0c;也就是说&#xff0c;它们是从右向左运算的。 2&#xff09…

01动力云客之环境准备+前端Vite搭建VUE项目入门+引入Element PLUS

1. 技术选型 前端&#xff1a;Html、CSS、JavaScript、Vue、Axios、Element Plus 后端&#xff1a;Spring Boot、Spring Security、MyBatis、MySQL、Redis 相关组件&#xff1a;HiKariCP&#xff08;Spring Boot默认数据库连接池&#xff09;、Spring-Data-Redis&#xff08;S…

JVM Java虚拟机入门指南

文章目录 为什么学习JVMJVM的执行流程JVM的组成部分类加载运行时数据区本地方法接口执行引擎 垃圾回收什么样的对象是垃圾呢内存溢出和内存泄漏定位垃圾的方法对象的finalization机制垃圾回收算法分代回收垃圾回收器 JVM调优参数JVM调优工具Java内存泄漏排查思路CPU飙高排查方案…

力扣精选算法100道—— 连续数组(前缀和专题)

连续数组&#xff08;前缀和专题&#xff09; 目录 &#x1f6a9;了解题意 &#x1f6a9;算法原理 ❗为什么hash设置成<0,-1>键值对 ❗与和为K的子数组比较hash的键值对 &#x1f6a9;代码实现 &#x1f6a9;了解题意 我们看到给定数组里面只有0和1&#xff0c;我们…

【JMeter】使用技巧

在这此对新版本jmeter的学习温习的过程&#xff0c;发现了一些以前不知道的功能&#xff0c;所以&#xff0c;整理出来与大分享。本文内容如下。 如何使用英文界面的jmeter如何使用镜像服务器Jmeter分布式测试启动Debug 日志记录搜索功能线程之间传递变量 如何使用英文界面的…

VMware虚拟机清理瘦身

用了一段时间VMware虚拟机之后&#xff0c;发现内存越来越小&#xff0c;也没装什么软件。。。 1.查询磁盘空间分布 虚拟机中磁盘空间查询 先看一下哪些地方占用的空间大&#xff0c;进行排查。 2.排查VMware复制文件产生的缓存路径 VMware复制文件有一个特点&#xff0c;以…

4、ChatGPT 无法完成的 5 项编码任务

ChatGPT 无法完成的 5 项编码任务 这是 ChatGPT 不能做的事情的一个清单,但这并非详尽无遗。ChatGPT 可以从头开始生成相当不错的代码,但是它不能取代你的工作。 我喜欢将 ChatGPT 视为 StackOverflow 的更智能版本。非常有帮助,但不会很快取代专业人士。当 ChatGPT 问世时…

docker常用10条容器操作命令

Docker 中一些常用的容器操作命令&#xff0c;我们可以根据需要使用这些命令来管理和操作 Docker 容器。我们这次以Hell-world这个镜像为例来说明&#xff1a; 1. docker pull hello-world #拉取hell-world镜像 2. docker images # 查看本地拉取的镜像 3. docker run hello…

VM 虚拟机和容器技术之间有什么区别?

随着云计算技术的不断发展&#xff0c;虚拟机和容器技术作为两种常见的虚拟化技术&#xff0c;被广泛应用于云计算领域。虽然虚拟机和容器技术都是虚拟化技术&#xff0c;但它们之间存在一些重要的区别。本文将详细介绍虚拟机和容器技术的区别&#xff0c;以便读者更好地了解这…

Qt信号和槽机制(什么是信号和槽,connect函数的形式,按钮的常用信号,QWidget的常用槽,自定义槽函数案例 点击按钮,输出文本)

一.什么是信号和槽 信号槽式Qt中的一个很重要的机制。信号槽实际上是观察者模式,当发生了感兴趣的事件&#xff0c;某一个操作就会被自动触发。当某个事件发生之后&#xff0c;比如按钮检测到自己被点击了一下&#xff0c;它就会发出一个信号。这种发出类似广播。如果有对象对…

HubSpot x 小红书:MessageBox打破数据壁垒

在当今数字营销的快速发展环境中&#xff0c;企业面临着将多个系统平台整合在一起以实现更有效营销策略的挑战。然而&#xff0c;随着技术的不断进步&#xff0c;诸如MessageBox这样的工具正在成为解决这一挑战的关键。MessageBox作为一种能够对接多个系统平台的工具&#xff0…