likes
comments
collection
share

十七.vite之浅析插件篇

作者站长头像
站长
· 阅读数 15

前言

最近使用vite在写项目时,遇到vue3中给setup添加name的问题,本来是打算直接使用插件进行实现的,但是评论说是会有各种各样的问题,看了下vite插件介绍后,突发奇想要不自己写一个?说干就干,下面来讲解Vite插件的基本概念。

vue3-basic-admin,该项目是一款开源开箱即用的中后台管理系统。基于 Vue3ViteElement-PlusTypeScriptPinia 等主流技术开发,内置许多开箱即用的组件,能快速构建中后台管理系统。

Vite和Rollup

有了解过Vite的都知道,Vite开发用的 ESBuild,而生产打包的时候使用的 Rollup进行打包,可能有人会有疑问,为什么生产不直接用 ESBuild 打包而是用 Rollup,对此Vite官方是这样回复的:

虽然 esbuild 快得惊人,并且已经是一个在构建库方面比较出色的工具,但一些针对构建 应用 的重要功能仍然还在持续开发中 —— 特别是代码分割和 CSS 处理方面。就目前来说,Rollup 在应用打包方面更加成熟和灵活。尽管如此,当未来这些功能稳定后,我们也不排除使用 esbuild 作为生产构建器的可能。

可以理解为 Vite用Esbuild来干活,干完活就不用它了,换成Rollup进行打包。

Vite之所以能开发和生产使用两套不同的构建工具,是因为他在dev环境下,其实是通过插件容器,除了使用Vite独有特性的插件,其他插件会进行模拟 Rollup插件行为,等到打包的时候,会将这一块替换成 Rollup 打包,所以其实不管是开发环境还是生产环境其实共享的同一套 Rollup插件机制,Vite插件 相当于是对 Rollup插件 做了一层兼容,或者换一个说法,Vite插件对Rollup插件做了扩展,加上了一些Vite独有的属性。

Vite插件概念

命名规范

如不使用Vite独有特性,可当做兼容Rollup的插件,推荐以推荐使用 Rollup 插件名称约定,反之,推荐以 vite-plugin- 开头,如果专属于某个框架,推荐格式:

  • vite-plugin-vue-  前缀作为 Vue 插件
  • vite-plugin-react-  前缀作为 React 插件

插件结构

一般插件结构由 nameenforce钩子组成。

  • name:即插件名字。
  • enforce: 通过该属性来调整插件加载顺序,可选值:pre | post
  • 钩子:不同状态下对应的处理函数,类似于生命周期。

十七.vite之浅析插件篇

插件加载顺序

插件结构中 enforce属性可调整插件加载顺序,Vite 插件加载顺序如下:

  • Alias
  • 带有 enforce: 'pre' 的用户插件
  • Vite 核心插件(解析vue文件等)
  • 没有 enforce 值的用户插件
  • Vite 构建用的插件
  • 带有 enforce: 'post' 的用户插件
  • Vite 后置构建插件(最小化,manifest,报告)

十七.vite之浅析插件篇

这里借用一张rollup的执行顺序:

十七.vite之浅析插件篇

Vite插件钩子

通用钩子

服务器启动钩子:

options

options 钩子主要是获取Rollup的配置,由于vite开发的时候使用的是EsBuild,所以开发环境下该属性为空,主要包含一些使用的 plugin,input入口文件等。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        options(options) {
            //可设置options.input修改入口文件
            console.log(options)
        }
    }
}

十七.vite之浅析插件篇

buildStart

buildStart 钩子执行顺序在options钩子后,主要是获取options钩子配置后的Rollup 配置和一些默认值,这个钩子开发和生产环境值都存在,不同于options,通过该钩子可以清楚看到Vite开发环境下对Rollup做的兼容模拟。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        buildStart(options) {
            console.log(options)
        }
    }
}

开发环境下:

十七.vite之浅析插件篇

生产环境时:

十七.vite之浅析插件篇

加载模块请求时钩子:

resolveId

resolveId 钩子可以获取文件路径,在该钩子下可以对文件路径进行重写或其他操作。

设置 enforce 不同值所打印的也不同哦

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        resolveId(id) {
            console.log(id)
        }
    }
}

十七.vite之浅析插件篇

load

load钩子可拦截文件读取,模块引入读取操作,参数和resolveId钩子类似,如需替换模块读取内容,返回对应codemap即可。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        load(id) {
            console.log(id)
            if(id==='xxxx'){
               return {
                   code:'<template>xxxxx</template>',
                   map:''
               }
            }
        }
    }
}

十七.vite之浅析插件篇

transform

transform钩子可以转换单个模块对应的代码,和load钩子不同的是,他有两个参数,codeid,这里的id和上面一样,这个code就是他对应的代码 ,简单情况下可直接修改 code去实现,复杂情况还是需要通过解析工具去解析vue。给setup加name就是用这个钩子实现的,这个我们在下一篇详细讲解。

这里注意,enforce设置的不同会导致code不同,如设置成pre这是编译前源代码,为空或post则是编译后的代码。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        transform(code,id){
            if(id.includes('HelloWorld')){
                console.log(code)
            }
            console.log(id)
        }
    }
}

pre:

十七.vite之浅析插件篇

空或post:

十七.vite之浅析插件篇

服务器关闭钩子:

buildEnd

buildEnd钩子是打包代码生成之前触发的钩子,仅在生产环境生效。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        buildEnd(){
        }
    }
}

closeBundle

closeBundle 钩子是打包后最后执行的钩子,他和buildEnd的区别是,它是打包代码生成后触发的钩子。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        closeBundle(){
        }
    }
}

Vite独有钩子(以下钩子会被Rollup忽略)

config

config钩子是解析Vite默认配置前钩子,它返回了Vite的一些默认配置,可以在这里修改配置,它有两个参数,第一个参数config是Vite的基本配置,第二个参数包括当前modecommand

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        config:(config,{mode,command})=>{
             console.log(config)
             console.log(mode)
             console.log(command)
        }
    }
}

十七.vite之浅析插件篇

configResolved

configResolved钩子是解析Vite默认配置后钩子,返回的是最终的Vite配置(自定义配置合并后的),可用于获取当前的一些配置,根据不同配置做不同的事情。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        configResolved(config) {
            console.log(config)
        },
    }
}

十七.vite之浅析插件篇

configureServer

configureServer 是配置开发服务器钩子,仅在开发环境下才会执行,他会返回当前开发服务器的配置。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        configureServer(config) {
            console.log(config)
        },
    }
}

十七.vite之浅析插件篇

configurePreviewServer

configurePreviewServer钩子和configureServer类似,但是configurePreviewServer是预览服务器,仅在执行npm run preview时触发该钩子。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        configureServer(config) {
            console.log(config)
        },
    }
}

十七.vite之浅析插件篇

transformIndexHtml

transformIndexHtml钩子主要是操作index.html文件,它会返回当前的html文件,修改index.htmltitle就可以在该钩子中修改。

示例代码:

export function testPlugin(){
    return {
        //插件名字
        name:'vite-plugin-test',
        transformIndexHtml(html) {
          console.log(html)
        },
    }
}

十七.vite之浅析插件篇

handleHotUpdate

handleHotUpdate 钩子主要是热更新钩子,感兴趣可以去看下Vite热更新原理,这里就略过。

总结

以上就是Vite插件的一些基本概念,实际开发中可以根据这些不同的钩子去实现很多很有意义的功能,下一篇我们开始对这些钩子进行实战,敬请期待。

其他文章