前端工程化之vite

vite常用的插件有哪些?

  1. @vitejs/plugin-vue:用于支持 Vue.js 单文件组件(.vue 文件)

  2. @vitejs/plugin-react:用于支持 React 和 JSX 语法

  3. **rollup-plugin-visualizer:**用于打包分析

  4. **vite-plugin-restart:**文件修改时自动重启vite

  5. **vite-plugin-components:**组件按需自动导入

  6. vite-plugin-svg-icons: 将 SVG 图标批量导入并转化为 Vue 组件

  7. vite-plugin-ssr:用于构建服务器端渲染(SSR)应用程序

vite配置项

javascript 复制代码
{
  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 文件
    lib: {}, // 构建为库
    manifest: false, // 当设置为 true,构建后将会生成 manifest.json 文件
    ssrManifest: false, // 构建不生成 SSR 的 manifest 文件
    ssr: undefined, // 生成面向 SSR 的构建
    write: true, // 启用将构建后的文件写入磁盘
    emptyOutDir: true, // 构建时清空该目录
    brotliSize: true, // 启用 brotli 压缩大小报告
    chunkSizeWarningLimit: 500, // chunk 大小警告的限制
    watch: null, // 设置为 {} 则会启用 rollup 的监听器
    // minify:false, // 表示打包后的文件内容不进行压缩,方便阅读
    minify: "terser", // esbuild | terser 指定使用哪种混淆器
    terserOptions: {
        compress: {
            // 打包的时候可以移除console和debugger
            drop_console: true,
            drop_debugger: true,
       },
    }, // 传递给 minify: "terser" 的更多 minify 选项
    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 服务器的构建目标
  },
  rollupOptions: { // 自定义底层的 Rollup 打包配置
      output: {
        chunkFileNames: 'js/[name]-[hash].js', // 打包后的文件名称
        entryFileNames: 'js/[name]-[hash].js', // 打包后的入口文件名称
        // assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等 指定静态资源文件名(不含导出的代码)
        // assetFileNames:"[name][extname]",
        // 对打包出来的资源文件进行分类,分别放到不同的文件夹内
        // assetFileNames(chunk) {
        //   console.log(chunk.name);
          
        //   // css
        //   if (chunk.name?.endsWith('.css')) {
        //     return 'css/[name]-[hash].[ext]';
        //   }
        //   // image
        //   if (/.(png|jpg|gif|jpeg|webp|svg)$/.test(chunk.name || '')) {
        //     return 'images/[name]-[hash].[ext]';
        //   }

        //   return `other/[name]-[hash].[ext]`;
        // },

        // 对打包出来的资源文件进行分类,分别放到不同的文件夹内
        assetFileNames(assetsInfo) {
          //  css样式文件
          if (assetsInfo.name?.endsWith(".css")) {
            return "css/[name]-[hash].css";
          }
          //  字体文件
          const fontExts = [".ttf", ".otf", ".woff", ".woff2", ".eot"];
          if (fontExts.some((ext) => assetsInfo.name?.endsWith(ext))) {
            return "font/[name]-[hash].[ext]";
          }

          //  图片文件
          const imgExts = [".png", ".jpg", ".jpeg", ".webp", ".gif", ".icon"];
          if (imgExts.some((ext) => assetsInfo.name?.endsWith(ext))) {
            return "img/[name]-[hash].[ext]";
          }

          //  SVG类型的图片文件
          const imgSvg = [".svg",];
          if (imgSvg.some((ext) => assetsInfo.name?.endsWith(ext))) {  
            return "assest/icons/[name].[ext]";
          }

          //  视频文件
          const videoExts = [".mp4", ".avi", ".wmv", ".ram", ".mpg", "mpeg"];
          if (videoExts.some((ext) => assetsInfo.name?.endsWith(ext))) {
            return "video/[name]-[hash].[ext]";
          }
          //  其它文件: 保存在 assets/图片名-哈希值.扩展名  
          return "assets/[name]-[hash].[ext]";
        },
        // 打包的文件进行拆包处理/静态资源分拆打包
        manualChunks:(id)=>{
          // 这个ID,就是所有文件的绝对路径
          if(id.includes("node_modules")){
            // 因为 node_modules 中的依赖通常是不会改变的
            // 所以直接单独打包出去
            // 这个return 的值就是打包的名称
            return "vendor";
          }
       },
       // 或者 
       manualChunks(id) { //静态资源分拆打包
          if (id.includes('node_modules')) {
            return id.toString().split('node_modules/')[1].split('/')[0].toString();
          }
       }
  }, 
}

为什么vite比webpack快

开发构建模式不同:Vite 使用原生 ES 模块(ESM),在开发过程中仅处理应用所需的代码,而不是对整个应用进行打包。这样,Vite 可以提供近乎即时的热模块替换(HMR),因为它只重新加载修改过的模块,而不是重建整个应用;Webpack 在开发过程中通常需要对整个应用进行打包,然后通过内存中的 Bundle 提供服务

Webpack热更新 是全量更新 ,即使修改一个小文件,也会重新编译整个应用,这在大型应用中可能会导致编译速度变慢。Vite热更新 是增量更新 ,只更新修改的文件,所以即使在大型应用中也能保持极快的编译速度

模块解析方式不同:Vite使用浏览器原生的 ES 模块 ,浏览器会根据导入的模块需求,仅请求更新的模块;Webpack 需要在开发服务器启动时分析所有的模块并构建完整的模块图,启动速度慢

打包优化手段

js最小化拆分包

javascript 复制代码
//vite.config中配置
   output: {
    // 最小化拆分包
    manualChunks(id) {
      if (id.includes('node_modules')) {
        return id.toString().split('node_modules/')[1].split('/')[0].toString();
      }
    }
  },

代码压缩

javascript 复制代码
//在vite.config中配置
import {defineConfig} from "vite";
export default defineConfig({
    esbuild:{
        pure: ['console.log'], // 删除 console.log
        drop: ['debugger'], // 删除 debugger
    }
})

文件压缩

javascript 复制代码
//npm i vite-plugin-compression -D
viteCompression({
  verbose: true, // 是否在控制台中输出压缩结果
  disable: false,
  threshold: 10240, // 如果体积大于阈值,将被压缩,单位为b,体积过小时请不要压缩,以免适得其反
  algorithm: 'gzip', // 压缩算法,可选['gzip',' brotliccompress ','deflate ','deflateRaw']
  ext: '.gz',
  deleteOriginFile: true // 源文件压缩后是否删除
})

图片压缩

javascript 复制代码
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
          }
        ]
      }
    })
]

按需加载第三方包

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

使用CDN加速

javascript 复制代码
import importToCDN, { autoComplete } from "vite-plugin-cdn-import";

 plugins: [
    importToCDN({
      modules: [
        {
          name: "vue",
          var: "Vue",
          path: "https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.31/vue.global.prod.min.js",
        },
        {
          name: "vuex",
          var: "Vuex",
          path: "https://cdnjs.cloudflare.com/ajax/libs/vuex/4.0.2/vuex.global.prod.min.js",
        },
        {
          name: "vue-router",
          var: "VueRouter",
          path: "https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.12/vue-router.global.prod.min.js",
        },
        {
          // 引入cdn element-plus
          name: "element-plus",
          var: "ElementPlus",
          path: "https://unpkg.com/element-plus",
          css: "https://unpkg.com/element-plus/dist/index.css",
        },
      ],
    }),
  ],
相关推荐
栈老师不回家9 分钟前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙15 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠19 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds39 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
阿伟来咯~1 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端2 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱2 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨2 小时前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking3 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js