Vite快速入门教程

2022-06-02 15:30:36
2023-03-21 22:24:55

完整配置(vite.config.js)

import { ConfigEnv, loadEnv, UserConfig } from "vite";
import { resolve } from "path";
import vue from "@vitejs/plugin-vue";

//自动导入组件
import Components from "unplugin-vue-components/vite";
import { VantResolver } from "unplugin-vue-components/resolvers";
import AutoImport from "unplugin-auto-import/vite";
//按需引入vant组件
import { createStyleImportPlugin, VantResolve } from "vite-plugin-style-import";

//提供压缩和基于 ejs 模板功能的 vite 插件
import { createHtmlPlugin } from "vite-plugin-html";
//复制插件
import copy from "rollup-plugin-copy";
//图片压缩
//import viteImagemin from "vite-plugin-imagemin";

//oss
import VitePluginOss from "vite-plugin-oss";

//打包分析
import { visualizer } from "rollup-plugin-visualizer";

function pathResolve(dir: string) {
  return resolve(process.cwd(), ".", dir);
}

const CWD = process.cwd();

export default ({ mode }: ConfigEnv): UserConfig => {
  // 环境变量
  const {
    VITE_OSS_URL,
    VITE_OSS_DIST,
    VITE_OSS_REGION,
    VITE_OSS_ACCESSKEYID,
    VITE_OSS_ACCESSKEYSECRET,
    VITE_OSS_BUCKET,
  } = loadEnv(mode, CWD);

  // console.log(VITE_OSS_DIST);

  const plugins = [
    vue(),

    //导入自定义组件
    Components({
      // 指定组件位置,默认是src/components
      dirs: ["src/components"],
      extensions: ["vue"],
      // 配置文件生成位置
      dts: "src/components.d.ts",
      // ui库解析器,也可以自定义
      resolvers: [VantResolver()],
    }),

    //导入vue函数
    AutoImport({
      imports: ["vue", "vue-router", "pinia"],
      // 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
      // dts: 'src/auto-import.d.ts'
    }),

    //按需引入vant组件样式
    createStyleImportPlugin({
      resolves: [VantResolve()],
    }),

    //ejs变量注入
    createHtmlPlugin({
      minify: true,
      // entry: "src/main.ts",
      // template: "index.html",
      inject: {
        data: {
          isProd: mode === "prod",
        },
      },
    }),
  ]; // 可将其他插件放入该数组

  if (mode === "prod" || mode === "test") {
    plugins.push(
      //复制插件
      copy({
        targets: [{ src: "assets/images/**/*", dest: "dist/public/images" }],
      }),

      //图片压缩
      // viteImagemin({
      //   gifsicle: {
      //     optimizationLevel: 7,
      //     interlaced: false,
      //   },

      //   //压缩有点慢,用处不大,经测试,前后压缩处理无差别
      //   // optipng: {
      //   //   optimizationLevel: 7
      //   // },
      //   mozjpeg: {
      //     quality: 20,
      //   },
      //   pngquant: {
      //     quality: [0.8, 0.9],
      //     speed: 4,
      //   },
      //   svgo: {
      //     plugins: [
      //       {
      //         name: "removeViewBox",
      //       },
      //       {
      //         name: "removeEmptyAttrs",
      //         active: false,
      //       },
      //     ],
      //   },
      // }),

      // //oss
      VitePluginOss({
        from: "./dist/**",
        dist: VITE_OSS_DIST,
        region: VITE_OSS_REGION,
        accessKeyId: VITE_OSS_ACCESSKEYID,
        accessKeySecret: VITE_OSS_ACCESSKEYSECRET,
        bucket: VITE_OSS_BUCKET,
        test: false,
        //上传日志
        verbose: false,
        setOssPath: (filePath) => {
          let index = filePath.lastIndexOf("dist");
          let Path = filePath.substring(index + 4, filePath.length);
          return Path.replace(/\\/g, "/");
        },
      }),

      visualizer()
    );
  }

  // console.log(plugins);

  return {
    //开发或生产环境服务的公共基础路径
    base: mode === "prod" || mode === "test" ? "./" : VITE_OSS_URL,
    resolve: {
      alias: [
        {
          find: /@\//,
          replacement: pathResolve("src") + "/",
        },
      ],
    },
    css: {
      preprocessorOptions: {
        //配置全局样式
        scss: {
          //设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息
          charset: false,
          additionalData: '@use "@/assets/css/globalstyle.scss" as *;',
        },
      },
    },
    server: {
      host: "0.0.0.0",
      port: 8080,
      open: false, // 设置服务启动时是否自动打开浏览器
      cors: true, // 允许跨域
      proxy: {
        "/api": {
          target: "http://127.0.0.1:4523/mock/720332",
          changeOrigin: true,
          secure: false,
          //删除/api
          rewrite: (path) => path.replace(/^\/api/, ""),
        },
      },
    },
    plugins: plugins,

    build: {
      minify: "terser",
      terserOptions: {
        compress: {
          //生产环境时移除console
          drop_console: true,
          drop_debugger: true,
        },
      },
      //指定生成静态资源的存放路径
      assetsDir: "/",

      rollupOptions: {
        //打包目录区分优化
        output: {
          chunkFileNames: "static/[name]-[hash].js",
          entryFileNames: "static/[name]-[hash].js",
          assetFileNames: "static/[name]-[hash].[ext]",
        },
      },
    },
  };
};

自动导入组件、hooks、样式

插件 作用
unplugin-vue-components 组件自动引入
unplugin-auto-import/vite vue3等插件 hooks 自动引入
vite-plugin-style-import 样式自动引入
vue-global-api eslint插件

1.1 自动导入ui库,该插件内置了大多数流行库解析器

npm install unplugin-vue-components -D
// vite.config.js,插件会生成一个ui库组件以及指令路径components.d.ts文件
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'
import {
  ElementPlusResolver,
  AntDesignVueResolver,
  VantResolver,
  HeadlessUiResolver,
  ElementUiResolver
} from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    Components({
      // ui库解析器,也可以自定义
      resolvers: [
        ElementPlusResolver(),
        AntDesignVueResolver(),
        VantResolver(),
        HeadlessUiResolver(),
        ElementUiResolver()
      ]
    })
  ]
})

1.2 自动导入自己的组件

// vite.config.js,插件会生成一个自己组件路径的components.d.ts文件
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'

export default defineConfig({
  plugins: [
    Components({
      // 指定组件位置,默认是src/components
      dirs: ['src/components'],
      // ui库解析器
      // resolvers: [ElementPlusResolver()],
      extensions: ['vue'],
      // 配置文件生成位置
      dts: 'src/components.d.ts'
    })
  ]
})

2. unplugin-auto-import/vite

支持vue, vue-router, vue-i18n, @vueuse/head, @vueuse/core等自动引入

// 引入前
import { ref, computed } from 'vue'
const count = ref(0)
const doubled = computed(() => count.value * 2)

//引入后
const count = ref(0)
const doubled = computed(() => count.value * 2)


// 引入前
import { useState } from 'react'
export function Counter() {
  const [count, setCount] = useState(0)
  return <div>{ count }</div>
}

//引入后
export function Counter() {
  const [count, setCount] = useState(0)
  return <div>{ count }</div>
}

安装

npm i -D unplugin-auto-import
// vite.config.js
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    AutoImport({
      imports: ['vue', 'vue-router', 'vue-i18n', '@vueuse/head', '@vueuse/core'],
      // 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
      // dts: 'src/auto-import.d.ts'
    })
  ]
})

原理: 安装的时候会自动生成auto-imports.d文件(默认是在根目录)

3.vue-global-api解决eslint报错

在页面没有引入的情况下,使用unplugin-auto-import/vite来自动引入hooks,在项目中肯定会报错的,这时候需要在eslintrc.js中的extends引入vue-global-api,这个插件是vue3hooks的,其他自己找找,找不到的话可以手动配置一下globals

安装

npm i vue-global-api -D
// .eslintrc.js
module.exports = {
  extends: [
    'vue-global-api'
  ]
};

它还为细粒度控制提供了相同的集合和单个 API 选项。

// .eslintrc.js
module.exports = {
  extends: [
    // collections
    'vue-global-api/reactivity',
    'vue-global-api/lifecycle',
    'vue-global-api/component',
    // single apis
    'vue-global-api/ref',
    'vue-global-api/toRef',
  ]
};

4.vite-plugin-style-import

当你使用unplugin-vue-components来引入ui库的时候

message, notification 等引入样式不生效 安装vite-plugin-style-import即可

这里以一些流行库为例

// vite.config.js
import { defineConfig } from 'vite'
import styleImport, {
  AndDesignVueResolve,
  VantResolve,
  ElementPlusResolve,
  NutuiResolve,
  AntdResolve
} from 'vite-plugin-style-import'

export default defineConfig({
  plugins: [
    styleImport({
      resolves: [
        AndDesignVueResolve(),
        VantResolve(),
        ElementPlusResolve(),
        NutuiResolve(),
        AntdResolve()
      ],
      // 自定义规则
      libs: [
        {
          libraryName: 'ant-design-vue',
          esModule: true,
          resolveStyle: (name) => {
            return `ant-design-vue/es/${name}/style/index`
          }
        }
      ]
    })
  ],
  // 引用使用less的库要配置一下
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true
      }
    }
  }
})

5. 注意点

1. element-plus默认是英文

方案: 在app.vue加上ElConfigProvider

<template>
  <div id="app">
    <el-config-provider :locale="locale">
      <router-view></router-view>
    </el-config-provider>
  </div>
</template>
<script setup>
import zhCn from 'element-plus/lib/locale/lang/zh-cn'
const locale = zhCn
</script>

日期相关组件设置中文:

<script setup>
// 日历等与dayjs相关的组件,不想显示中文可以不加
// 第一种方法 使用中国时区weekStart默认为1
import 'dayjs/locale/zh-cn'

// 第二种方法 使用 weekStart可配置(只能是0或者1)
import dayjs from 'dayjs'
// 引入英文即为英文
import cn from 'dayjs/locale/zh-cn'
dayjs.locale({
  ...cn,
  weekStart: 1
})


const locale = zhCn
</script>

vite-plugin-ali-oss

打包自动上传打包文件到oss

import vitePluginAliOss from 'vite-plugin-ali-oss';
  // 获取 .env 环境配置文件
const env = loadEnv(mode, process.cwd());

    //oss  plugins数组
vitePluginAliOss({
            region: env.VITE_OSS_REGION,
            accessKeyId: env.VITE_OSS_ACCESSKEYID,
            accessKeySecret: env.VITE_OSS_ACCESSKEYSECRET,
            bucket: env.VITE_OSS_BUCKET
    })

vite使用cdn

vite-plugin-cdn-import

import importToCDN from 'vite-plugin-cdn-import';
importToCDN({
    modules: [
        {
            name: 'vue',
            var: 'Vue',
            path: 'https://cdn.jsdelivr.net/npm/vue@3.2.25/dist/vue.global.prod.js'
        },
        {
            name: 'vue-i18n',
            var: 'VueI18n',
            path: 'https://cdn.bootcdn.net/ajax/libs/vue-i18n/9.1.10/vue-i18n.global.prod.min.js'
        },
        {
            name: 'vue-router',
            var: 'VueRouter',
            path: 'https://unpkg.com/vue-router@4.0.16/dist/vue-router.global.prod.js'
        },

        {
            name: 'element-plus',
            var: 'ElementPlus',
            path: `https://unpkg.com/element-plus@2.2.6/dist/index.full.js`,
            css: 'https://unpkg.com/element-plus/dist/index.css'
        },
        {
            name: 'vue-demi',
            var: 'VueDemi',
            path: 'https://cdn.bootcdn.net/ajax/libs/vue-demi/0.13.1/index.iife.js'
        },
        {
            name: 'pinia',
            var: 'Pinia',
            path: 'https://cdn.bootcdn.net/ajax/libs/pinia/2.0.14/pinia.iife.prod.min.js'
        },
        {
            name: '@smallwei/avue',
            var: 'AVUE',
            path: 'https://cdn.jsdelivr.net/npm/@smallwei/avue@3.0.17'
        }
    ]
}),
这上面的都有引用关系所以都需要通过cdn的方式引入
VueDemi这个是pinia用来判断是vue2还是vue3所需要的,要额外引入一下

第二种方案(通过rollup-plugin-external-globals)这个方式需要单独在index.html中引入cdn资源

import externalGlobals from 'rollup-plugin-external-globals';
let globals = externalGlobals({
    vue: 'Vue',
    'vue-i18n': 'VueI18n',
    'vue-router': 'VueRouter',
    'element-plus': 'ElementPlus',
    pinia: 'Pinia',
    '@smallwei/avue': 'AVUE'
});

//vite.config.ts(注意plugins的位置是在build下)

build:{
    rollupOptions:{
        // 忽略打包
        external: ['vue', 'vue-i18n', 'pinia', 'vue-router', 'element-plus','@smallwei/avue'],
    },
    plugins: [globals],
}

// index.html

<script src="https://cdn.jsdelivr.net/npm/vue@3.2.25/dist/vue.global.prod.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-i18n/9.1.10/vue-i18n.global.prod.min.js"></script>
<script src="https://unpkg.com/vue-router@4.0.16/dist/vue-router.global.prod.js"></script>
<script src="https://unpkg.com/element-plus@2.2.6/dist/index.full.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-demi/0.13.1/index.iife.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/pinia/2.0.14/pinia.iife.prod.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@smallwei/avue@3.0.17"></script>

网页重新部署,通知用户-最佳实践

安装插件

pnpm add @plugin-web-update-notification/vite -D

原理

以 git commit hash (也支持 package.json version、build timestamp、custom) 为版本号,打包时将版本号写入 json 文件。客户端轮询服务器上的版本号(浏览器窗口的 visibilitychange、focus 事件辅助),和本地作比较,如果不相同则通知用户刷新页面。

vite.config.ts

import { webUpdateNotice } from '@plugin-web-update-notification/vite'


export default defineConfig({
  plugins: [
    vue(),
    webUpdateNotice({
      notificationProps: {
        title: '更新通知',
        description: '网站内容有更新,请刷新页面,获取最新内容',
        buttonText: '刷新',
        dismissButtonText: '忽略'
      },
    }),
  ]
})
目录

运营需要亿点资金维持,您的支持,是小白龙创作的动力!!!