一、vite的插件推荐

rollup-plugin-visualizer

打包分析插件

  • 安装
npm install rollup-plugin-visualizer -D
  • vite配置
// vite.config.js
import { defineConfig } from 'vite'
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
    plugins: [visualizer()]
})

打包后,会在根目录下生成一个 stats.html文件,可用浏览器打开查看

vite-plugin-restart

通过监听文件修改,自动重启 vite 服务

最常用的场景就是监听 vite.config.js 和 .env.development 文件,修改 vite 配置文件和环境配置文件,是需要重启 vite 才会生效,通过这个插件,在修改上述两个文件则不需要重新运行

  • 安装
npm i vite-plugin-restart -D
  • 配置:vite.config.js
import ViteRestart from 'vite-plugin-restart'
export default {
  plugins: [
    ViteRestart({
      restart: [
        'vite.config.js',
      ]
    })
  ],
};

unplugin-vue-components

组件自动按需导入

  • 安装:
npm i unplugin-vue-components -D
  • 配置:vite.config.js
import Components from 'unplugin-vue-components/vite'
// ui库解析器,也可以自定义,需要安装相关UI库,unplugin-vue-components/resolvers
// 提供了以下集中解析器,使用的时候,需要安装对应的UI库,这里以element为示例
// 注释的是包含的其他一些常用组件库,供参考
import {
  ElementPlusResolver,
  // AntDesignVueResolver,
  // VantResolver,
  // HeadlessUiResolver,
  // ElementUiResolver
} from 'unplugin-vue-components/resolvers'

export default  ({ mode }) => defineConfig({
  plugins: [
    Components({
      dirs: ['src/components'], // 目标文件夹
      extensions: ['vue','jsx'], // 文件类型
      dts: 'src/components.d.ts', // 输出文件,里面都是一些import的组件键值对
      // ui库解析器,也可以自定义,需要安装相关UI库
      resolvers: [
        VantResolver(),
          ElementPlusResolver(),
        // AntDesignVueResolver(),
        // HeadlessUiResolver(),
        // ElementUiResolver()
      ],
    })
  ]
})

原先引用组件的时候需要在目标文件里面import相关组件,现在就可以直接使用无需在目标文件import了,

注意大小写,组件都是大写开始的

vite-plugin-style-import

当你使用unplugin-vue-components来引入ui库的时候,message, notification,toast 等引入样式不生效

安装vite-plugin-style-import,实现message, notification,toast 等引入样式自动引入

  • 安装:
npm i vite-plugin-style-import -D
  • vite.config.js
import styleImport, {
  // AndDesignVueResolve,
  VantResolve,
  // ElementPlusResolve,
  // NutuiResolve,
  // AntdResolve
} from 'vite-plugin-style-import'


export default  ({ mode }) => defineConfig({
  plugins: [
    styleImport({
      resolves: [
        // AndDesignVueResolve(),
        VantResolve(),
        // ElementPlusResolve(),
        // NutuiResolve(),
        // AntdResolve()
      ],
    })
  ]
})

注释部分为常用的UI组件库,按照自己的需要引入

unplugin-auto-import

vue3等插件 hooks 自动引入

支持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)
  • 安装
npm i unplugin-auto-import -D
  • vite.config.js
import AutoImport from 'unplugin-auto-import/vite'
export default  ({ mode }) => defineConfig({
  plugins: [
    AutoImport({
      imports: ['vue', 'vue-router', 'vuex', '@vueuse/head'],
      // 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
      dts: 'src/auto-import.d.ts'
    }),
  ]
})

vite-plugin-svg-icons

方便在项目中使用 .svg 文件,为什么要使用svg而不使用icons,详见:

登录阿里巴巴矢量图标库使用 -https://www.iconfont.cn/,只需把下载好的 svg 文件统一放到指定assets/svg目录下

  • 安装:
npm i vite-plugin-svg-icons -D
  • vite.config.js配置
import { defineConfig,loadEnv } from 'vite'
import {createSvgIconsPlugin} from 'vite-plugin-svg-icons';
const path = require("path");
export default  ({ mode }) => defineConfig({
  plugins: [
    vue(),
    createSvgIconsPlugin({
   		// 指定要缓存的文件夹
      iconDirs: [resolve(process.cwd(), 'src/assets/svg')],
      // 指定symbolId格式
      symbolId: 'icon-[dir]-[name]' 
    })
  ]
})
// 更多配置说明
viteSvgIcons({
  // 指定图标文件夹,数组形式,可以有多个
  iconDirs: [path.resolve(process.cwd(), 'icons')],
  // 指定symbolId格式
  symbolId: 'icon-[dir]-[name]',

  // 自定义插入位置
  inject?: 'body-last' | 'body-first',

  // 设置图标样式类名
  className?: 'svg-icon',

  // 设置svg元素属性
  svgoOptions: {},
  
  // 指定标题内容
  title?: false,
  
  // 生成sprite 
  svgSprite: false, 
  
  // 导入图标接口
  runtimeIconImport: 'import-all' | 'async',
})
  • main.js添加
import 'virtual:svg-icons-register'
  • 模块中使用
<svg style="width: 30px; height: 30px" fill="red">
    <use xlink:href="#icon-order" fill="blue"></use>
  </svg>
  • 封装组件,新建SvgIcon.vue
<template>
    <svg aria-hidden="true" class="svg-icon" :fill="props.color" :width="width" :height="height">
        <use :xlink:href="symbolId"/>
    </svg>
</template>


<script setup  name='svg-icon'>
   //  import { computed } from 'vue'
    const props = defineProps({
        prefix: {
            type: String,
            default: 'icon'
        },
        name: {
            type: String,
            required: true
        },
        size: {
            type: String,
            default: '1em'
        },
        width: {
            type: String
        },
        height: {
            type: String
        },
        color: {
            type: String,
            default: 'currentColor'
        }
    })
    const symbolId  = computed(() => `#${props.prefix}-${props.name}`)
    const width = computed(() => (props.width ? props.width : props.size))
    const height = computed(() => (props.height ? props.height : props.size))



</script>

<style scope>
  .svg-icon {
    fill: currentColor;
    outline: none;
    font-size: 14px;

}
    
</style>
  • svg组件按需引入
<template>
  <SvgIcon name="order"></SvgIcon>
</template>
 
<script setup>
import svgIcon from 'comp/SvgIcons.vue'
</script>
  • svg组件全局引入使用
// 在main.js中加入
import svgIcon from 'comp/SvgIcons.vue'
createApp(App).component('svg-icon', svgIcon)

// 页面中使用
<svg-icon name="order" class="icon"></svg-icon>

小结: svg未正确显示

  • 解决方案:
iconDirs: [resolve(process.cwd(), '@/assets/svg')],

// 修改为:
iconDirs: [resolve(process.cwd(), 'src/assets/svg')],
// 加载插件之前别名还未生效,

vite-plugin-html

一个针对 index.html,提供压缩和基于 ejs 模板功能的 vite 插件

通过搭配 .env 文件,可以在开发或构建项目时,对 index.html 注入动态数据,例如替换网站标题

  • 安装:
npm i vite-plugin-html -D
  • index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="./favicon.ico" />
    <link rel="stylesheet" href="./public/reset.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <title><%- title %></title>
  </head>
  <body>
    <div id="app"></div>
    <%- injectScript %>
  </body>
</html>
  • vite.config.js
import { defineConfig,loadEnv} from 'vite'
import { createHtmlPlugin } from 'vite-plugin-html'
export default  ({ mode }) => defineConfig({
    // mode 环境变量名,若配置有.env.test,启动时 --mode test,这里的mode就是test
  plugins: [
    createHtmlPlugin({
      minify: true,
      /**
       * 在这里写entry后,你将不需要在`index.html`内添加 script 标签,原有标签需要删除
       * @default src/main.js
       */
      entry: '/src/main.js',
      /**
       * 需要注入 index.html ejs 模版的数据
       */
      inject: {
        data: {
          // 查找.env.test文件里面的VITE_PROJECT_TITLE,请以VITE_标识开头
          title: loadEnv(mode, process.cwd()).VITE_PROJECT_TITLE, 
          injectScript: `<script src="/inject.js"></script>`,
        },
      },
    })
  ]
})

vite-plugin-compression

使用 gzip 或者 brotli 来压缩资源

  • 安装:
npm i vite-plugin-compression -D
  • vite.config.js
import { defineConfig,loadEnv} from 'vite'
import viteCompression from 'vite-plugin-compression';
export default  ({ mode }) => defineConfig({
  plugins: [
    viteCompression()
  ]
})

vite-plugin-imagemin

打包压缩图片

  • 安装
npm install vite-plugin-minipic -D
  • 使用
// 此插件也行
import { defineConfig,loadEnv} from 'vite'
import viteImagemin from 'vite-plugin-imagemin'
export default  ({ mode }) => defineConfig({
  plugins: [
    viteImagemin({
      gifsicle: { // gif图片压缩
        optimizationLevel: 3, // 选择1到3之间的优化级别
        interlaced: false, // 隔行扫描gif进行渐进式渲染
        // colors: 2 // 将每个输出GIF中不同颜色的数量减少到num或更少。数字必须介于2和256之间。
      },
      optipng: { // png
        optimizationLevel: 7, // 选择0到7之间的优化级别
      },
      mozjpeg: {// jpeg
        quality: 20, // 压缩质量,范围从0(最差)到100(最佳)。
      },
      pngquant: {// png
        quality: [0.8, 0.9], // Min和max是介于0(最差)到1(最佳)之间的数字,类似于JPEG。达到或超过最高质量所需的最少量的颜色。如果转换导致质量低于最低质量,图像将不会被保存。
        speed: 4, // 压缩速度,1(强力)到11(最快)
      },
      svgo: { // svg压缩
        plugins: [
          {
            name: 'removeViewBox',
          },
          {
            name: 'removeEmptyAttrs',
            active: false,
          },
        ],
      },
    }),
  ]
})

vite-plugin-purge-icons

此插件是可以让我们很方便高效的使用Iconify中所有的图标(待验证使用..)

@vitejs/plugin-vue-jsx

此插件支持在vue3中使用jsx/tsx语法

  • 安装
npm i @vitejs/plugin-vue-jsx
  • vite.config.js
import { defineConfig,loadEnv} from 'vite'
import vuejsx from "@vitejs/plugin-vue-jsx"
export default  ({ mode }) => defineConfig({
  plugins: [
    vuejsx()
  ]
})
  • jsx文件:
    (jsx组件中自动跳过生命周期,即jsx中没有生命周期,在父组件onBeforeMount后执行)
const component = (props:any,context:any) => {
  console.log(props)
  const onClick = () => { 
    context.emit('update')
  }
  return <div
    style={{
      fontSize: 12,
      color: '#999'
    }}
    onClick={()=>onClick()}
  >
    我是jsx函数组件{props.text}
  </div>
}

export default component

vite-plugin-vue-setup-extend

setup语法糖name增强,使vue3语法糖支持name属性

vue3语法糖默认是没有name属性的,在我们使用keep-alive的时候需要用到name

  • 安装
npm i vite-plugin-vue-setup-extend -D
  • vite.config.js
import { defineConfig} from 'vite'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
export default  ({ mode }) => defineConfig({
  plugins: [
    vueSetupExtend()
  ]
}
  • 使用
<script setup lang="ts" name="home">
</script>

vitejs-plugin-legacy

Vite默认的浏览器支持基线是原生ESM。该插件为不支持原生ESM的传统浏览器提供支持

@vitejs/plugin-vue

vite支持vue开发

vite-plugin-vue-images

自动导入图像,同级目录的文件名不能重复!

  • 安装
npm i vite-plugin-vue-images -D
  • vite.config.js
import { defineConfig,loadEnv} from 'vite'
import ViteImages from 'vite-plugin-vue-images'
export default  ({ mode }) => defineConfig({
  plugins: [
    ViteImages({
      dirs: ['src/assets'], // 图像目录的相对路径
      extensions: ['jpg', 'jpeg', 'png', 'svg', 'webp'], // 有效的图像扩展
      customResolvers:[], // 覆盖名称->图像路径解析的默认行为
      customSearchRegex: '([a-zA-Z0-9]+)', // 重写搜索要替换的变量的Regex。
    }),
  ]

假设有以下文件及路径

logo.png: src/assets/logo.png

name1.jpg: src/assets/test/name1.jpg

  • 使用方式:
<template>
  <div class="home">
    <img :src="Logo"  />
    <img :src="TestName1"  /> 
  </div>
</template>

<script setup lang="ts">
</script>

<style lang="less" scoped>
</style>
  • 插件将转换为:
<template>
  <div class="home">
    <img :src="Logo"  />
    <img :src="TestName1"  /> 
  </div>
</template>

<script setup lang="ts">
import Logo from '@/assets/logo.png'
import TestName1 from '@/assets/test/name1.jpg'
</script>

<style lang="less" scoped>
</style>

vue-global-api

unplugin-auto-import插件的继承者,解决因为它的自动导入导致的eslint报错

  • 安装
npm i vue-global-api
  • main.js添加
import 'vue-global-api'

二、vite环境基本配置

import { defineConfig } from "vite";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import vue from "@vitejs/plugin-vue";
import postcssPxToViewport from 'postcss-px-to-viewport'
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import path from "path";
 
export default defineConfig({
  plugins: [
    vue(),
    //页面自动引入vue 插件
    AutoImport({
      imports: ["vue"],
      dts: "src/auto-import.d.ts",
    }),
    //element plus按需自动引入
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    //element plus按需自动引入
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  css: {
    postcss: {
      plugins: [
        postcssPxToViewport({
          viewportWidth: 1920 //---基于1920宽度为100vw
        })
      ]
    }
  },
  build: {
    minify: "terser", // 必须开启:使用terserOptions才有效果
    terserOptions: {
      compress: {
        //生产环境时移除console
        drop_console: true,
        drop_debugger: true,
      },
    },
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"), 
      "comp": resolve(__dirname, "src/components"),
      // 配置图片要这样引用也可以自定义方法引入图片静态资源
      "/img": "./src/assets",
    },
  },
  // 跨域
  server: {
    host: "0.0.0.0",
    hmr: true,
    strictPort: false,
    //自定义代理规则
    proxy: {
      // 选项写法
      "/api": {
        target: "",
        changeOrigin: true,
        rewrite: (path) => path.replace(/^/api/, ""),
      },
    },
  },
});

三、vite常用基本配置

{
  root: process.cwd(), // 项目根目录(index.html 文件所在的位置),
  base: '/', // 开发或生产环境服务的公共基础路径 配置引入相对路径
  mode: 'development', // 模式
  plugins: [vue()], // 需要用到的插件数组
  publicDir: 'public', // 静态资源服务的文件夹
  cacheDir: 'node_modules/.vite', // 存储缓存文件的目录
  resolve: {
    alias: [ // 文件系统路径别名
      {
        find: //@//,
        replacement: pathResolve('src') + '/'
      }
    ],
    dedupe: [], // 强制 Vite 始终将列出的依赖项解析为同一副本
    conditions: [], // 解决程序包中 情景导出 时的其他允许条件
    mainFields: [], // 解析包入口点尝试的字段列表
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'], // 导入时想要忽略的扩展名列表
    preserveSymlinks: false, // 启用此选项会使 Vite 通过原始文件路径确定文件身份
  },
  css: {
    modules: {
      scopeBehaviour: 'global' | 'local',
      // ...
    },
    postcss: '', // 内联的 PostCSS 配置 如果提供了该内联配置,Vite 将不会搜索其他 PostCSS 配置源
    preprocessorOptions: { // css的预处理器选项
      scss: {
        additionalData: `$injectedColor: orange;`
      }
    }
  },
  json: {
    namedExports: true, // 是否支持从.json文件中进行按名导入
    stringify: false, //  开启此项,导入的 JSON 会被转换为 export default JSON.parse("...") 会禁用按名导入
  },
  esbuild: { // 最常见的用例是自定义 JSX
    jsxFactory: 'h',
    jsxFragment: 'Fragment'
  },
  assetsInclude: ['**/*.gltf'], // 指定额外的 picomatch 模式 作为静态资源处理
  logLevel: 'info', // 调整控制台输出的级别 'info' | 'warn' | 'error' | 'silent'
  clearScreen: true, // 设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息
  envDir: '/', // 用于加载 .env 文件的目录
  envPrefix: [], // 以 envPrefix 开头的环境变量会通过 import.meta.env 暴露在你的客户端源码中
  server: {
    host: '127.0.0.1', // 指定服务器应该监听哪个 IP 地址
    port: 5000, // 指定开发服务器端口
    strictPort: true, // 若端口已被占用则会直接退出
    https: false, // 启用 TLS + HTTP/2
    open: true, // 启动时自动在浏览器中打开应用程序
    proxy: { // 配置自定义代理规则
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^/api/, '')
      }
    },
    cors: true, // 配置 CORS
    force: true, // 强制使依赖预构建
    hmr: { // 禁用或配置 HMR 连接
      // ...
    },
    watch: { // 传递给 chokidar 的文件系统监听器选项
      // ...
    },
    middlewareMode: '', // 以中间件模式创建 Vite 服务器
    fs: {
      strict: true, // 限制为工作区 root 路径以外的文件的访问
      allow: [], // 限制哪些文件可以通过 /@fs/ 路径提供服务
      deny: ['.env', '.env.*', '*.{pem,crt}'], // 用于限制 Vite 开发服务器提供敏感文件的黑名单
    },
    origin: 'http://127.0.0.1:8080/', // 用于定义开发调试阶段生成资产的 origin
  },
  build: {
    target: ['modules'], // 设置最终构建的浏览器兼容目标
    polyfillModulePreload: true, // 是否自动注入 module preload 的 polyfill
    outDir: 'dist', // 指定输出路径
    assetsDir: 'assets', // 指定生成静态文件目录
    assetsInlineLimit: '4096', // 小于此阈值的导入或引用资源将内联为 base64 编码
    cssCodeSplit: true, // 启用 CSS 代码拆分
    cssTarget: '', // 允许用户为 CSS 的压缩设置一个不同的浏览器 target 与 build.target 一致
    sourcemap: false, // 构建后是否生成 source map 文件
    rollupOptions: {}, // 自定义底层的 Rollup 打包配置
    lib: {}, // 构建为库
    manifest: false, // 当设置为 true,构建后将会生成 manifest.json 文件
    ssrManifest: false, // 构建不生成 SSR 的 manifest 文件
    ssr: undefined, // 生成面向 SSR 的构建
    minify: 'esbuild', // 指定使用哪种混淆器
    terserOptions: {}, // 传递给 Terser 的更多 minify 选项
    write: true, // 启用将构建后的文件写入磁盘
    emptyOutDir: true, // 构建时清空该目录
    brotliSize: true, // 启用 brotli 压缩大小报告
    chunkSizeWarningLimit: 500, // chunk 大小警告的限制
    watch: null, // 设置为 {} 则会启用 rollup 的监听器
  },
  preview: {
    port: 5000, // 指定开发服务器端口
    strictPort: true, // 若端口已被占用则会直接退出
    https: false, // 启用 TLS + HTTP/2
    open: true, // 启动时自动在浏览器中打开应用程序
    proxy: { // 配置自定义代理规则
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^/api/, '')
      }
    },
    cors: true, // 配置 CORS
  },
  optimizeDeps: {
    entries: [], // 指定自定义条目——该值需要遵循 fast-glob 模式
    exclude: [], // 在预构建中强制排除的依赖项
    include: [], // 可强制预构建链接的包
    keepNames: false, // true 可以在函数和类上保留 name 属性
  },
  ssr: {
    external: [], // 列出的是要为 SSR 强制外部化的依赖,
    noExternal: '', // 列出的是防止被 SSR 外部化依赖项
    target: 'node', // SSR 服务器的构建目标
  }
}

四、vite构建打包优化

前置工具

rollup官网: https://cn.rollupjs.org/configuration-options/#manualchunks

安装插件 rollup-plugin-visualizer 它是一个打包体积分析插件,对应webpack中的webpack-bundle-analyzer,可以看到打包后的所有文件大小

rollupOptions 对象允许配置 Rollup 的大多数核心选项,常见的有:

  • input - 输入文件地址
  • output - 输出配置
  • strict //确保所有导出的模块使用严格模式
  • intro: '/* my-lib version 1.0.0 */', // 在输出的文件顶部添加注释,包括包名和版本号
  • file - 输出文件的路径和名称
  • format - 输出格式,常用的有 esm、cjs、umd 等
  • name - umd 模式下的模块名称 // 生成的代码是否应该使用命名函数
  • globals - umd 模式下外部模块的全局变量名称
  • plugins - 需要使用的 Rollup 插件数组
  • external - 外部化不需要打包的依赖模块
  • watch - 是否开启 watch 模式

配置打包文件分类输出

build: {
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
        entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
        assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
      }
    }
}

// 不建议配置

js最小拆分包

  • 配置vite.config 的 output 属性
  • 让打开那个页面,加载那个页面的js ,让之间的关联足够小
output: {
    // 最小化拆分包
    manualChunks(id) {
      if (id.includes('node_modules')) {
        return id.toString().split('node_modules/')[1].split('/')[0].toString();
      }
    }
  },

  // 不建议配置,未来此配置将废弃

代码压缩+剔除console+debugger

esbuild or terser, 默认启动的是 esbuild, esbuild比terser快 20-40 倍,压缩率只差 1%-2%

esbuild

只删除 console.logdebugger

import {defineConfig} from "vite";
export default defineConfig({
    esbuild:{
        pure: ['console.log'], // 删除 console.log
        drop: ['debugger'], // 删除 debugger
    }
})
// 建议配置

删除所有的console语句和debugger,包括console.log、console.warn、console.error等

import {defineConfig} from "vite";
export default defineConfig({
    esbuild:{
        drop: ['console,'debugger'], // 删除 所有的console 和 debugger
    }
})

terser

vite 4.X 版本已经不集成 terser,需要自行下载

npm i terser -D

只删除 console.logdebugger

import { defineConfig } from "vite";  
export default defineConfig({  
    build: {  
        minify: 'terser', // 启用 terser 压缩  
        terserOptions: {  
            compress: {  
                pure_funcs: ['console.log'], // 只删除 console.log  
                drop_debugger: true, // 删除 debugger  
            }  
        }  
    }  
})

删除所有的console语句和debugger,包括console.log、console.warn、console.error等

import {defineConfig} from "vite";
export default defineConfig({
    build: {
        minify: 'terser', // 启用 terser 压缩
        terserOptions: {
            compress: {
                drop_console: true, // 删除所有 console
                drop_debugger: true,// 删除 debugger
            }
        }
    }
})

文件压缩

npm i vite-plugin-compression -D

当请求静态资源时,服务端发现请求资源为gzip的格式时,应该设置响应头 content-encoding: gzip 。因为浏览器解压也需要时间,所以代码体积不是很大的话不建议使用 gzip 压缩

// build.rollupOptions.plugins[]
viteCompression({
  verbose: true, // 是否在控制台中输出压缩结果
  disable: false,
  threshold: 10240, // 如果体积大于阈值,将被压缩,单位为b,体积过小时请不要压缩,以免适得其反
  algorithm: 'gzip', // 压缩算法,可选['gzip',' brotliccompress ','deflate ','deflateRaw']
  ext: '.gz',
  deleteOriginFile: true // 源文件压缩后是否删除(我为了看压缩后的效果,先选择了true)
})

图片资源压缩

npm i vite-plugin-imagemin -D

在vite.config.js里面配置

import viteImagemin from 'vite-plugin-imagemin'
plugin: [
    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
          }
        ]
      }
    })
]

按需加载优化一些第三方包的体积

比如loadsh,项目中只用到了{cloneDeep 、throttle、debouce}这个几个函数,但是由于lodash是common.js版本不支持按需引入,500多k全部打包进来了

import _ from 'lodash-es'; // 将会把整个lodash的库引入到项目
import { cloneDeep } from 'lodash-es'; // 将只会把cloneDeep引入到项目

lodash-es 是 lodash 的 es modules 版本 ,是着具备 ES6 模块化的版本,支持按需导入,使用loadsh-es代替lodash,按需引入,减少打包体积

CDN加速

安装插件

npm install rollup-plugin-external-globals -D

vite.config.js里面配置

import externalGlobals from 'rollup-plugin-external-globals';

const globals = externalGlobals({
  moment: 'moment',
  // 'video.js': 'videojs',
  // jspdf: 'jspdf',
  // xlsx: 'XLSX',
  react:react,
  react-dom:refact-dom
});

export default defineConfig({
    build: {
        rollupOptions: {
            external: ['moment', 'react,react-dom'],
            plugins: [globals],
        }
    }
});

eg: 在 index.html 模版中引入对应库的CDN。

<script src="//cdn.haier.net/assets/overlay/dts-fe/common-assets/es5-shim/4.5.14/es5-shim.min.js"></script>
    <script src="//cdn.haier.net/assets/overlay/dts-fe/common-assets/es5-shim/4.5.14/es5-sham.min.js"></script>
    <script src="//cdn.haier.net/assets/overlay/dts-fe/common-assets/@babel/polyfill/7.21.1/polyfill.min.js"></script>
    <!--前端框架调试版本-->
    <script src="//cdn.haier.net/assets/overlay/dts-fe/common-assets/react/16.13.1/react.development.js"></script>
    <script src="//cdn.haier.net/assets/overlay/dts-fe/common-assets/react-dom/16.13.1/react-dom.development.js"></script>
    <!--组件市场工具-->
    <script src="//cdn.haier.net/assets/daily/dts-fe/hiui-react-component-show-tools/0.1.0/index.js"></script>

具体的CDN链接可到cdn网站查看:cdnjs.com/

这里请注意:请勿直接使用cdn站点的链接,严格意义上使用自己公司的甲方提供的为主

SEO优化,vite实现预渲染(未验证!感兴趣的可自行体验)

npm i vite-plugin-prerender -D

在vite.config.js中使用

import vitePrerender from 'vite-plugin-prerender'
import path from 'path'

export default () => {
  return {
    plugins: [
      vitePrerender({
        // Required - The path to the vite-outputted app to prerender.
        staticDir: path.join(__dirname, 'dist'),
        // Required - Routes to render.
        routes: ['/', '/chat', '/design'],
      }),
    ],
  }
}

打包完成后,会根据配置的路由地址,在dist文件中生成对应的index.html文件

【在dist根目录下、dist/chat、dist/design 目录下都会生成index.html文件】

五、错误详解

控制台出现Content-Security-Policy 安全策略报警,此时配置禁止访问外部的资源,仅引用本地资源

渲染进程页面添加如下

<meta http-equiv="Content-Security-Policy" content="script-src 'self'" />

更多关于Electron的搭建及学习请前往:https://www.yuque.com/donsoft/qknibo/vweongdlmblc5s8g

六、总结

vite SSR 支持不及 webpack成熟, 生态及插件市场不及webpack丰富,但vite配置较简单,也满足约定大于配置,上手较快,vite对于HMR 是基于浏览器原生模块热更新实现,对一些复杂场景支持可能不够灵活。