🚀两个简单的自定义插件,探究Vite的插件机制

简介: 🚀两个简单的自定义插件,探究Vite的插件机制


🚀 Vite 插件机制

Vite 的插件机制是基于 Rollup 的插件机制实现的,但是又进行了一些扩展。Vite 的插件机制是通过钩子函数实现的,当 Vite 运行时,会通过钩子函数调用插件中的方法,插件可以在这些方法中干预 Vite 的构建过程。

我们主要讨论插件的机制,Api详情请看官网介绍

通用的钩子:https://cn.vitejs.dev/guide/api-plugin.html#universal-hooks

Vite 独有的钩子:https://cn.vitejs.dev/guide/api-plugin.html#vite-specific-hooks

下面我们看看插件的原理。

🚗 Rollup 插件机制

Rollup 的插件机制实现主要基于两点:

  • Rollup 维护了各个插件接口的 Hook 列表,插件可以向这些列表中添加回调函数。
  • 在执行对应过程时,Rollup 会依次触发这些 Hook 列表中的回调函数。
const hookLists = {
  load: [] // load hook 列表
}
function addHook(hookName, hook) {
  hookLists[hookName].push(hook)  // 向 hook 列表中添加回调函数
}
function load(id) {
  for (const hook of hookLists.load) { // 触发所有 load 钩子函数
    const result = hook(id)  // 调用钩子函数
    if (result) return result  // 使用第一个结果并返回
  }
}

插件可以通过 Rollup 提供的 addHook 方法相对应的 Hook 列表中添加回调函数:

export function myPlugin() {
  addHook('load', id => {  // 向 load 列表添加回调函数
    // ...
  })
}

🚗 Vite 的巧妙之处

Vite 主要将用户插件排序,然后和内置的插件配置合并,传递给了 Rollup 打包。

关键的部分源码如下:

// vite/node/config.ts
export async function resolveConfig() {
  // ...
  // resolve plugins
  const rawUserPlugins = (
    (await asyncFlatten(config.plugins || [])) as Plugin[]
  ).filter(filterPlugin)
  const [prePlugins, normalPlugins, postPlugins] =
    sortUserPlugins(rawUserPlugins)
  // run config hooks
  const userPlugins = [...prePlugins, ...normalPlugins, ...postPlugins]
  // ...
}
// vite/node/build.ts 
export async function build() {
  const config = await resolveConfig(
    inlineConfig,
    'build',
    'production',
    'production',
  )
  //...
  const plugins = (
    ssr ? config.plugins.map((p) => injectSsrFlagToHooks(p)) : config.plugins
  ) as Plugin[]
  const rollupOptions: RollupOptions = {
    context: 'globalThis',
    preserveEntrySignatures: ssr
      ? 'allow-extension'
      : libOptions
      ? 'strict'
      : false,
    cache: config.build.watch ? undefined : false,
    ...options.rollupOptions,
    input,
    plugins,
    external,
    onwarn(warning, warn) {
      onRollupWarning(warning, warn, config)
    },
  }
  // ...
  // write or generate files with rollup
  const { rollup } = await import('rollup')
  bundle = await rollup(rollupOptions)
  // ...
}

Vite 使用插件时,需要将插件放入 plugins 的数组中如下:

🚀 实践得真知

接下来我们自定义几个插件,感受下 Vite 的插件机制。

写这几个插件是为了理解插件机制,官方已经提供了相关的配置或者现成的插件

🚗 自动切换端口,默认8080

Vite 默认的端口不是 8080了,有点不太习惯,所以自己写个插件自动切换端口。

import net from 'net'
function getNextPort(port: number) {
  return new Promise((resolve) => {
    const server = net.createServer()
    server.unref()
    server.on('error', () => {
      resolve(getNextPort(port + 1))
    })
    server.listen(port, () => {
      server.close(() => {
        resolve(port)
      })
    })
  })
}
function autoSwitchPortPlugin() {
  let port = 8080
  return {
    name: 'auto-switch-port',
    async configResolved(config: any) {
      port = await getNextPort(port) as number
      config.server.port = port
    },
  }
}
export default autoSwitchPortPlugin

🚗 为文件加上版本号

由于这个操作是转换 index.html文件,所以需要使用专用钩子transformIndexHtml

import { createHash } from "crypto"
export default function autoVersionPlugin() {
  return {
    name: 'auto-version',
    async transformIndexHtml(html: string) {
      const hash = createHash('md5').update(html).digest('hex')
      return html.replace(/(src|href)="(.*?)"/g, `$1="$2?v=${hash}"`)
    },
  }
}

🎉 总结

Vite 插件机制主要在整个构建过程的不同时机暴露出钩子函数供开发者灵活自定义构建过程。所以理解构建流程,才能更好的开发一个优秀的插件。

好了今天的分享就到这了,如果文中有纰漏的地方,欢迎指正!!!

相关文章
|
开发框架 小程序 JavaScript
基于mpvue框架的小程序项目搭建入门教程一
基于mpvue框架的小程序项目搭建入门教程一
176 0
|
7月前
|
JavaScript
vue中的插件概念是什么?新手小白如何在Vue中引入插件
【8月更文挑战第21天】vue中的插件概念是什么?新手小白如何在Vue中引入插件
108 1
vue中的插件概念是什么?新手小白如何在Vue中引入插件
|
缓存 前端开发 JavaScript
浅浅阅读umi中InitialState插件源码 - 杨磊
InitialState插件源码的简要介绍
1086 0
浅浅阅读umi中InitialState插件源码 - 杨磊
|
7月前
|
存储 JavaScript
这一定是最有用的vite插件入门教程了!
【8月更文挑战第3天】 vite插件核心在于几个钩子函数的理解与使用,想开发vite插件,掌握这几个插件即可。本文中探讨了**config钩子**和**transformIndexHtml钩子**,相信大家看完对插件开发一定有了最基本的认识与方向!
205 3
|
10月前
|
资源调度 JavaScript 开发者
插件使用:扩展Vue功能与第三方插件
【4月更文挑战第23天】Vue凭借其轻量级和灵活性在Web开发中备受青睐,而插件则进一步增强了其功能。本文探讨了如何在Vue项目中选择、安装、配置和管理插件,以适应不同需求。要点包括:选择可靠且兼容的插件,使用npm或yarn安装,根据文档配置,以及注意性能影响。明智使用插件能提升开发效率,但需避免过度依赖,确保与项目目标和技术栈匹配。不断学习新插件,可保持技术领先并优化项目实践。
110 0
|
10月前
|
资源调度 JavaScript 前端开发
深度剖析 Vite 配置
深度剖析 Vite 配置
280 1
|
10月前
|
存储 JavaScript 前端开发
【Vue原理解析】之插件系统
Vue是一款流行的JavaScript框架,它提供了一个强大的插件系统,使开发者能够轻松扩展Vue的能力与功能。在Vue中,插件是一种可复用的功能模块,可以扩展或修改全局功能。它可以添加全局方法、指令、过滤器、混入等,并在每个Vue实例中都可用。通过使用插件,我们可以轻松地添加第三方库、自定义指令或过滤器等功能到我们的应用程序中。
80 0
|
JavaScript 前端开发 API
Vue.js入门指南:从基础到进阶,掌握现代JavaScript框架的核心概念与高级特性(2W字小白教程)
Vue.js入门指南:从基础到进阶,掌握现代JavaScript框架的核心概念与高级特性(2W字小白教程)
230 0
|
JavaScript
【Vue 开发实战】实战篇 # 44:如何高效地构建打包发布
【Vue 开发实战】实战篇 # 44:如何高效地构建打包发布
195 0
【Vue 开发实战】实战篇 # 44:如何高效地构建打包发布
|
JavaScript 测试技术 API
深入解析 Vue 的热更新原理,尤大是如何巧用源码中的细节?
大家都用过 Vue-CLI 创建 vue 应用,在开发的时候我们修改了 vue 文件,保存了文件,浏览器上就自动更新出我们写的组件内容,非常的顺滑流畅,大大提高了开发效率。想知道这背后是怎么实现的吗,其实代码并不复杂。