rollup的插件初体验

接触了一段时间的rollup,简单的记录下。

一、简单介绍

rollup的插件是一个对象,包含了名称和一些钩子函数。

在rollup打包过程中,会根据不同的钩子函数依次执行。

1.1 两个阶段

1.构建期:这个阶段是对源文件的转化,转换好的文件没有输出,放在内存中。

大概会经历  options -->buildStart -->resolvedId -->load -->transform -->moduleParsed -->buildEnd。

如果同一个钩子被不同的插件实现,会根据插件的顺序依次执行钩子函数。

2.输出期:这个阶段主要是对转换好的文件进行拼凑整合,可能加上统一的banner,footer等,生成chunk。然后再bundle输出到硬盘上。

大概会经过 outputOptions -->renderStart -->renderChunk -->genderateBundle -->writeBundle -->closeBundle.

列出了大部分,如果有import引用的话可能会循环执行某些步骤,这里不展开。

其实还有一个watch阶段,它可以在任一阶段触发和结束。它有两个钩子函数: watchChange,closeWatcher。

当你使用 rollup --watch 指令或者在配置文件配有watch: true的属性时,会在文件变化时重新构建。

有点HMR的意思,估计热更新也用到了这一特性。


1.2 钩子执行时机

rollup钩子根据执行时机又分为同步,异步;并行,串行。

同步,异步区别就是结果会不会返回promise。

并行(parallel):如果有多个插件实现此钩子,则所有这些钩子将按指定的插件顺序运行。如果钩子是 async,则此类后续钩子将并行运行,而不是等待当前钩子。

串行(sequential):如果有多个插件实现此钩子,则所有这些钩子将按指定的插件顺序运行。如果钩子是 async,则此类后续钩子将等待当前钩子解决后再运行。

并行串行主要是对异步有了进一步的区分。


1.3 相同钩子函数的顺序

钩子函数可以是一个函数,像这样load

function myPlugin1(){
    name: 'test-plugin1',
    // 默认顺序
    load(id){
        // xxx
    }
}

 也可以是一个load对象

function myPlugin2(){
    name: 'test-plugin2',
    load: {
        // 可以配置更丰富的选项
        order: 'pre',
        // 具体的执行函数变到这儿
        handler(id){
            // xxx
        }
    }
}

配置成一个对象可以更灵活的使用插件。

这里 order 属性分为 pre,post。pre先执行,默认配置的再执行,post后执行。

二、插件使用

选取了 load 和 transform 两个钩子函数进行测试。

2.1 load

先看下load钩子的具体作用:

即传入一个文件名(id),看对该文件做不做修改。这会影响到下一步 transform 拿到的参数。

比如可以在 load 阶段生成js代码的ast,返回该ast。

这里以vite插件为例,因为vite插件保留了rollup插件的一些钩子函数,很类似。

在@vitejs/plugin-vue中,我们可以看到该插件在load阶段,对sfc文件的不同阶段,输出不同的结果。最终返回了code和sourcemap。


       这里我在自己的项目中做个简单测试。这里当load钩子return null时,说明交给下一个load钩子继续执行,返回值不为null,对于这个文件后面相同的load钩子就不执行了。(这里不是绝对的,对于load,transform等钩子来说,一旦成功返回非null值,后面的就不执行了。对于renderChunk等钩子,即使前面的钩子返回结果,后面的钩子也有可能改变这次的结果,具体要看rollup的官方文档)

 

可以看到打印了所有的用到的文件名称。从我们的入口文件开始(vite默认项目根目录下的index.html)。这里我们就可以根据不同的文件类型,做出不同的处理

2.2 transform

这个阶段会真正的处理文件的内容。比如对sfc文件,template进行加工,转成js函数。对css内容,就转成引用。

在@vitejs/plugin-vue中,我们可以看到该插件在transform阶段,会分别对template、style、script文件进行处理。也是在这一步,template内容会转化成我们熟知的render函数。

以我的项目为例,在transform中我打印app.vue的内容。

 可以看到,因为我的 testPlugin 在 vue插件后面执行,我这里拿到的就是经过vue插件转换后的文件,能看到此时的 _sfc_main 函数。 

 当我修改了transform的order属性时:(testPlugin报错是ts的,先忽略)

可以看到虽然testPlugin排在vue插件之后,却是在vue插件之前执行的,因为我们拿到的是还没有被转化的文件内容。

 三、小结

我们简单的测试了下rollup插件的几个钩子。在rollup中所有的插件都是顺序执行,不同的钩子在不同的生命周期中发挥作用。对同一种钩子不同的插件可以写不同的处理,执行的顺序要看他们的排列顺序和order。另外rollup内置了一些方法,可以在钩子中获取到当前文件的状态,meta数据等,比如getModuleInfo 在构建期间,此对象表示有关模块的当前可用信息。这里不展开。

我只是粗略的了解rollup的插件机制,大家想深入的话,可以看看其他的著名插件,结合rollup官网,定能有所收获。

后续有其他深入理解,会再更新rollup相关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值