ToC
前言
rollup 从 第一次提交代码 到现在已经七年多了,算不上新奇,但即便是在现在各种打包工具百花齐放(Vite、swc、tsup、unbuild、esbuild 等)的时代,仍占据着不可或缺的一席之地,虽然在下载量这方面还远不及同类的 webpack,但这和两者的应用场景有很大关系。rollup 主要适用于插件、库的打包,而 webpack 主要适用于项目开发。但虽然在用户方面没有什么优势,但 rollup 依然创造且实装了许多非常实用且新颖的功能,比如这一次的主题:virtual module
。
据我所知,virtual module
在 web 开发中的第一次露面是在五年前 Rich Harris 对 [仓库](initial commit · rollup/rollup-plugin-virtual@6d7f6d0 · GitHub 进行的代码提交。可能在其他语言中这个概念早就有了,甚至已经运行了很久,但对于 web 来说,这是个先河。
Anton Medvedev 是一名非常优秀的程序员,他编写了 zx、fx、expr 和 很多很酷且有趣的东西 ,比如他将 公元日期 发布为单独的 npm 包,从 1970 年到 2038 ,每一年都有一个单独的 npm 包,虽然 2038 年只有 1 月份,但这已经足够让人感到震撼了(感到笑死 :D),你甚至可以在 npm 上找到自己的生日(const birthday = require('@year/1970/01/01')
),并在项目中使用它(:D)。非常有趣,但同时这工作量也非常庞大,手动维护它太不方便了,如果我们使用虚拟模块来做的话,则非常简单。
Vite 虚拟模块
Vite 中的虚拟模块其实是沿用了 rollup 中的概念,它本身类型 alias
别名,但模块的内容本身并不是直接存储在磁盘中,而是内存中,因为它本身并不存在,而是在编译的时候动态生成的,这也是为什么说他是一个潜力被低估的原因之一。
在 Vite 文档中对虚拟模块的描述 是从这开始的:
虚拟模块是一种很实用的模式,使你可以对使用 ESM 语法的源文件传入一些编译时信息。
而在官网中也有一个现成的例子:
从例子中我们可以看出以上行为创建了一个虚拟模块,并将 export const msg = "from virtual module"
作为模块的内容返回了出来,这样就可以在项目中任意地方引入这个 msg
变量来使用了。虚拟模块的详细限制在文档中已经详细有写,文中就不赘述了,我们完全可以根据以上的这个例子来实现上文中讲到的 【公元日期】的虚拟模块,Let’s dance!
实现一个虚拟模块
在实现 Vite 虚拟模块之前,我们先创建一个 Vite 项目吧:
会询问:
Need to install the following packages: create-vite Ok to proceed? (y)
按回车确认即可。因为我们只是想创建一个 Vite 项目来测试插件而已,所以我们选 vanilla
这个选项,即原生js,在安装以后没有什么框架的其他依赖,选择完 vanilla
以后还会出现两个选项,分别为:vanilla
和 vanilla-ts
,如果想写 ts 的,则选 ts,懒得定义的则选 vanilla
即可。插件的实现如下:
这样我们就完成了这个插件的开发,但如果使用了 ts,那么在导入的时候肯定是会有类型报错的,因为找不到这个模块的类型声明,这时候就需要我们去定义它。
定义 TS 模块类型声明
在 src
下有一个 vite-env.d.ts
文件,我们只需要在里面追加一下内容即可:
完整代码
完整的代码在这里:GitHub - libondev/https://github.com/libondev/learning-vite-virtual-module-plugin.git ,当然还可以通过在线地址来试试:Vitejs - Vite (forked) - StackBlitz
以上.