实现一个简单的rollup插件

108 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

1. rollup介绍

  • Rollup是一个JavaScript模块打包器,可以将小块代码编译成大块复杂的代码,例如library或应用程序
  • webpack打包非常繁琐,打包体积比较大
  • rollup主要是用来打包JS库的
  • vue/react/angular都在用rollup作为打包工具
//rollup.config.js
rollup的五种输出格式
export default { 
    input:'src/main.js', 
    output:{ 
        file:'dist/bundle.cjs.js',//输出文件的路径和名称
        format:'cjs',//五种输出格式:amd/es6/iife/umd/cjs 
        name:'bundleName'//当format为iife和umd时必须提供,将作为全局变量挂在window下 
    },
    plugins:[]
 }

  • AMD: - Asynchronous Module Definition异步模块定义
  • es6: - ES6 module是es6提出了新的模块化方案
  • IIFE: (Immediately Invoked Function Expression)即立即执行函数表达式,所谓立即执行,就是声明一个函数,声明完了立即执行
  • UMD: Universal Module Definition,也就是通用模块定义
  • cjs: 是nodejs采用的模块化标准,commonjs使用方法require来引入模块,这里require()接收的参数是模块名或者是模块文件的路径

2. rollup打包流程

  • 打包阶段,通过传入的inputOptions来处理模块,返回一个bundle,
  • 生成阶段,返回的bundle生成打包后的代码
  • 写入阶段,写入文件系统

3. rollup插件

  • Rollup 插件是一个具有以下描述的一个或多个属性构建钩子输出生成钩子的对象,它遵循我们的约定。插件应该作为一个包分发,该包导出一个可以使用插件特定选项调用的函数并返回这样一个对象
  • 插件需要注意以下规范
    • 插件需要有一个清晰的名称
    • 尽可能使用异步方法
    • 插件应该经过测试

插件的钩子:

  • 为了与构建过程交互,你的插件对象包括“钩子”
  • 钩子是在构建的不同阶段调用的函数
  • 钩子可以影响构建的运行方式,提供关于构建的信息,或者在构建完成后修改构建
function build() {
  return {
    name: "build",
    async watchChange(id, change) {
      console.log("watchChange", id, change);
    },
    async closeWatcher() {
      console.log("closeWatcher");
    },
    async options(inputOptions) {
      console.log("options");
      //inputOptions.input = './src/main.js';
    },
    async buildStart(inputOptions) {
      console.log("buildStart");
    },
    async resolveId(source, importer) {
      if (source === "virtual") {
        console.log("resolveId", source);
        //如果resolveId钩子有返回值了,那么就会跳过后面的查找逻辑,以此返回值作为最终的模块ID
        return source;
      }
    },
    //加载此模块ID对应的内容
    async load(id) {
      if (id === "virtual") {
        console.log("load", id);
        return `export default "virtual"`;
      }
    },
    async shouldTransformCachedModule({ id, code, ast }) {
      console.log("shouldTransformCachedModule");
      //不使用缓存,再次进行转换
      return true;
    },
    async transform(code, id) {
      console.log("transform");
    },
    async moduleParsed(moduleInfo) {
      console.log("moduleParsed");
    },
    async resolveDynamicImport(specifier, importer) {
      console.log("resolveDynamicImport", specifier, importer);
    },
    async buildEnd() {
      console.log("buildEnd");
    },
  };
}