前言

如果你对vite基础还不是很了解,建议阅读我上一篇文章《Vite入门 基础知识》。

vite2构建工具优缺点

传统工具开发环境构建方式和vite对比

传统工具构建方式:

传统工具构建方式

当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。

vite 构建方式:

vite 构建方式

Vite通过在一开始将应用中的模块区分为依赖和源码两类,改进了开发服务器启动时间。

依赖 大多为在开发时不会变动的纯JavaScript。一些较大的依赖(例如有上百个模块的组件库)处理的代价也很高。依赖也通常会存在多种模块化格式(例如ESM或者CommonJS)

Vite将会使用esbuild预构建依赖。Esbuild使用Go编写,并且比以JavaScript编写的打包器预构建依赖快10-100倍。

源码 通常包含一些并非直接是JavaScript的文件,需要转换(例如JSX,CSS或者Vue/Svelte组件),时常会被编辑。同时,并不是所有的源码都需要同时被加载(例如基于路由拆分的代码模块)。

Vite以原生ESM方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。

更新对比

在传统的工具(webpack)更新:

基于打包器启动时,重建整个包的效率很低。原因显而易见:因为这样更新速度会随着应用体积增长而直线下降。

一些打包器的开发服务器将构建内容存入内存,这样它们只需要在文件更改时使模块图的一部分失活,但它也仍需要整个重新构建并重载页面。这样代价很高,并且重新加载页面会消除应用的当前状态,所以打包器支持了动态模块热重载(HMR):允许一个模块“热替换”它自己,而不会影响页面其余部分。这大大改进了开发体验——然而,在实践中我们发现,即使采用了HMR模式,其热更新速度也会随着应用规模的增长而显著下降。

vite更新:

在Vite中,HMR是在原生ESM上执行的。当编辑一个文件时,Vite只需要精确地使已编辑的模块与其最近的HMR边界之间的链失活[1](大多数时候只是模块本身),使得无论应用大小如何,HMR始终能保持快速更新。

Vite同时利用HTTP头来加速整个页面的重新加载(再次让浏览器为我们做更多事情):源码模块的请求会根据304 Not Modified进行协商缓存,而依赖模块请求则会通过Cache-Control:max-age=31536000,immutable进行强缓存,因此一旦被缓存它们将不需要再次请求。

vite一些缺点:

  1. vite 推出时间太短了,生态这块没有其他构建工具那么完善,同时很多问题和述求没有暴露出来
  2. 针对代码合并切割这块功能没有 webpack 强大(微前端, 代码切割)

resolve 解析

和 webpack 类似,resolve 字段用来表示如何来解析模块,首先我们看下常用的别名设置 alias

import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
  console.log(loadEnv(mode, process.cwd()).VITE_APP_BASE_PATH, 'base-path')
  return defineConfig({
    resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src'), // 设置 `@` 指向 `src` 目录
      }
    }
  })
}

[email protected][email protected]

import Pagination from '@/components/pagination/index.vue'

按需引入

我们在使用 element 时,经常会需要按需引入组件,在 vue-cli 中使用的是 babel 的一个插件 babel-plugin-component;vite 有自己的按需引入插件 vite-plugin-style-import,首先我们安装一下:

npm install vite-plugin-style-import -D

然后在 vite.config.js 中进行配置:

import styleImport from "vite-plugin-style-import";
export default defineConfig({
  plugins: [
    vue(),
    styleImport({
      libs: [
        {
          libraryName: "element-plus",
          esModule: true,
          ensureStyleFile: true,
          resolveStyle: (name) => {
            return `element-plus/lib/theme-chalk/${name}.css`;
          },
          resolveComponent: (name) => {
            return `element-plus/lib/${name}`;
          }
        }
      ]
    })
  ]
})

接下来如果我们只希望引入部分组件,就可以在 main.js 中加入:

import { ElButton, ElSelect } from 'element-plus'

const app = createApp(App)
app.component(ElButton.name, ElButton)
app.component(ElSelect.name, ElSelect)

gzip 压缩

插件安装:

npm install vite-plugin-compression -D

# or yarn
yarn add vite-plugin-compression -D

用法:

import viteCompression from 'vite-plugin-compression'
import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
  return defineConfig({
    plugins: [
      viteCompression()
    ],
  })
}

文件打包分析

插件安装:

npm install rollup-plugin-visualizer -D

# or yarn
yarn add rollup-plugin-visualizer -D

用法:

import { visualizer } from 'rollup-plugin-visualizer'
import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
  return defineConfig({
    build: {
      rollupOptions: {
        plugins: [
          visualizer({ open: true, gzipSize: true })
        ]
      }
    }
  })
}

将外部导入转换为全局变量,打包把模块排除

插件安装:

npm install -D rollup-plugin-external-globals

# or yarn
yarn add rollup-plugin-external-globals -D

用法:

import externalGlobals from 'rollup-plugin-external-globals'
import { defineConfig, loadEnv } from 'vite'
export default ({ mode, command }) => {
  return defineConfig({
    build: {
      rollupOptions: {
        external: ['vue', 'vuex', 'vue-router', 'axios', 'ElementPlus'],
        plugins: [
          externalGlobals({
            vue: 'Vue',
            'element-plus': 'ElementPlus',
            'vue-router': 'VueRouter',
            vuex: 'Vuex',
            axios: 'axios'
          })
        ]
      }
    }
  })
}

vite 使用 rollup 插件

一般来说,只要一个 Rollup 插件符合以下标准,那么它应该只是作为一个 Vite 插件:

  • 没有使用 moduleParsed 钩子。
  • 它在打包钩子和输出钩子之间没有很强的耦合。
  • 如果一个 Rollup 插件只在构建阶段有意义,则在 build.rollupOptions.plugins 下指定即可。

建议在不确定是否能用的情况下使用 Vite 专属的插件:

  • Vite 插件应该有一个带 vite-plugin- 前缀、语义清晰的名称。
  • 在 package.json 中包含 vite-plugin 关键字。
  • 在插件文档增加一部分关于为什么本插件是一个 Vite 专属插件的详细说明(如,本插件使用了 Vite 特有的插件钩子)。

热更新

热更新(hot module replacement) ,简称 hmr ,是一种无需刷新浏览器即可更新代码效果的技术,实现该技术的关键点是要建立 浏览器服务器 之间的联系,还好我们现成就有一种技术可以实现:websocket 协议,普通的 http 协议为短连接,一次会话结束就会关闭,这显然没法满足我们时刻都需要关联 浏览器服务器 的需求,而websocket 为长连接,可以一直保持 浏览器服务器 之间的会话不中断,通过事件来互相传送数据,vite 也用了 websocket 来实现 热更新

热更新主体流程如下:

  1. 服务端基于 watcher 监听文件改动,根据类型判断更新方式,并编译资源
  2. 客户端通过 WebSocket 监听到一些更新的消息类型
  3. 客户端收到资源信息,根据消息类型执行热更新逻辑

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有资源及文章均来源于网络及用户分享或为本站原创,仅限用于学习和研究,任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » vite2实战指北

发表评论

IT互联网行业相关广告投放 更专业 更精准

立即查看 联系我们