Vite相关

Vite工作原理

Vite是一种现代化的前端开发工具,其工作原理主要分为以下几个步骤:

  • 基于ESM构建:Vite作为一款基于ESM的前端构建工具,通过ES模块提供的动态导入功能来实现快速的开发和构建。
  • 零配置开发:Vite允许开发者在不需要任何配置的情况下启动一个服务器进行开发,通过对文件的即时编译和缓存,来提高开发效率。
  • 基于浏览器原生的ESM加载:Vite将所有文件视为ES模块,并且在开发时会直接从源代码加载模块,而不是打包后的文件,从而可以避免打包的过程带来的性能损失。
  • 按需编译和缓存:Vite会按需编译和缓存依赖项,只有当需要更新时才会进行重新编译,缓存让开发者可以忽略无关的代码变化。
  • 插件化架构:Vite的插件化架构可以方便地扩展其功能,例如使用插件来处理CSS、处理图片、压缩源代码等等。

通过以上几个步骤,Vite实现了快速、高效的前端开发和构建。

Vite 和 Webpack区别

区别如下:

  1. 构建原理: Webpack 是一个静态模块打包器,通过对项目中的 JavaScript、CSS、图片等文件进行分析,生成对应的静态资源,并且可以通过一些插件和加载器来实现各种功能;Vite 则是一种基于浏览器原生 ES 模块解析的构建工具。
  2. 打包速度: Webpack 的打包速度相对较慢,Vite 的打包速度非常快。
  3. 配置难度: Webpack 的配置比较复杂,因为它需要通过各种插件和加载器来实现各种功能;Vite 的配置相对简单,它可以根据不同的开发场景自动配置相应的环境变量和配置选项。
  4. 插件和加载器: Webpack 有大量的插件和加载器可以使用,可以实现各种复杂的构建场景,例如代码分割、按需加载、CSS 预处理器等;Vite 的插件和加载器相对较少
  5. Vite是按需加载,webpack是全部加载: 在HMR(热更新)方面,当改动了一个模块后,vite仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。
  6. webpack是先打包再启动开发服务器,vite是直接启动开发服务器,然后按需编译依赖文件 由于vite在启动的时候不需要打包,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快。当浏览器请求某个模块时,再根据需要对模块内容进行编译,这种按需动态编译的方式,极大的缩减了编译时间。

Vite核心原理

  • Vite其核心原理是利用浏览器现在已经支持ES6的import,碰见import就会发送一个HTTP请求去加载文件。
  • Vite整个过程中没有对文件进行打包编译,做到了真正的按需加载,所以其运行速度比原始的webpack开发编译速度快出许多!
  • 快速的冷启动:基于Esbuild的依赖进行预编译优化 (Esbuild 打包速度太快了,比类似的工具快10~100倍 )
  • 增加缓存策略:源码模块使用协商缓存,依赖模块使用强缓;因此一旦被缓存它们将不需要再次请求。
  • HMR(热更新):当修改代码时,HMR 能够在不刷新页面的情况下,把页面中发生变化的模块,替换成新的模块,同时不影响其他模块的正常运作
    • 所有的 HMR 原理: 目前所有的打包工具实现热更新的思路都大同小异:主要是通过WebSocket创建浏览器和服务器的通信监听文件的改变,当文件被修改时,服务端发送消息通知客户端修改相应的代码,客户端对应不同的文件进行不同的操作的更新。

为什么说vite比webpack更快

  • webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。
  • vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。
  • vite在启动的时候不需要打包,意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快。
  • 当浏览器请求某个模块时,再根据需要对模块内容进行编译。这种按需动态编译的方式,极大的缩减了编译时间,项目越复杂、模块越多,vite的优势越明显。
  • 在HMR方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。
  • 当需要打包到生产环境时,vite使用传统的rollup进行打包,因此,vite的主要优势在开发阶段。另外,由于vite利用的是ES Module,因此在代码中不可以使用CommonJS

基础配置

import { defineConfig, loadEnv } from 'vite'
import { fileURLToPath, URL } from 'node:url'
import process from 'node:process'
import vue from '@vitejs/plugin-vue'
// 打包体积分析
import { visualizer } from 'rollup-plugin-visualizer'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
  return {
    base: loadEnv(mode, process.cwd()).VITE_BASE_URL, // .env.development 中的VITE_BASE_URL
    server: {
      host: '0.0.0.0',
      port: 20000
      /* proxy: {
        '/api': {
          target: 'http://10.8.0.13:1234',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, '')
        }
      } */
    },
    plugins: [
      vue(),
      visualizer({ open: true }) // 完成打包后自动打开打包分析
    ],
    esbuild: {
      drop: ['console', 'debugger'] //去除生产环境下的console.xxxx和debugger
    },
    build: {
      rollupOptions: {
        output: {
          entryFileNames: 'js/[name]-[hash].js',
          chunkFileNames: 'js/[name]-chunk-[hash].js',
          assetFileNames: (assetInfo) => {
            if (assetInfo.name.endsWith('.css')) {
              return 'css/[name]-[hash].css'
            }
            const imgExts = ['.jpg', '.jpeg', '.png', '.webp', '.gif', '.svg', '.ico']
            if (imgExts.some((ext) => assetInfo.name.endsWith(ext))) {
              return 'img/[name]-[hash].[ext]'
            }
            return 'assets/[name]-[hash].[ext]'
          },
					manualChunks(modulePath) {
            if (modulePath.includes('node_module')) {
              return 'vendor'
            }
          }
        }
      }
    },
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url))
      }
    }
  }
})

vite

去除打包后的console.xxx 和 debugger

esbuild: {
	drop: ['console', 'debugger']
}

默认配置所有的项目文件都集中在assets目录中,配置后所有的文件按照类型文件夹区分,因为vite打包依赖的是rollup,因此在build配置相中配置rollupOptions的output

build: {
    rollupOptions: {
      output: {
        entryFileNames: 'js/[name]-[hash].js',
        chunkFileNames: 'js/[name]-chunk-[hash].js',
        assetFileNames: (assetInfo) => {
          if (assetInfo.name.endsWith('.css')) {
            return 'css/[name]-[hash].css'
          }
          const imgExts = ['.jpg', '.jpeg', '.png', '.webp', '.gif', '.svg', '.ico']
          if (imgExts.some((ext) => assetInfo.name.endsWith(ext))) {
            return 'img/[name]-[hash].[ext]'
          }
          return 'assets/[name]-[hash].[ext]'
        }
      }
    }
  }
对你有帮助?请作者喝杯咖啡~
lauyimou 支付宝 支付宝
lauyimou 微信 微信
0%