目录
文章目录隐藏
  1. 前言
  2. vite2 构建工具优缺点
  3. resolve 解析
  4. 按需引入
  5. gzip 压缩
  6. 文件打包分析
  7. 将外部导入转换为全局变量,打包把模块排除
  8. vite 使用 rollup 插件
  9. 热更新

前言

如果你对 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` 目录
      }
    }
  })
}

这样我们就能用@替换相对路径了,可以通过@来引入组件:

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实战指北

发表回复