286 - 《手撕源码 31:magicast》

发布于 2023年4月14日

1、magicast 是最近比较火的库,感觉 Umi 里也会有地方需要用到,于是翻了翻。作者是「pi0」和「antfu」。从初始 commit 来看,想法源于「pi0」,同时一开始是叫「paneer」,基于 recast 做 ast 操作,然后被「antfu」发扬光大了。

2、盲猜这个库是给 nuxt devtools 用的,通过 ast 的方式修改用户配置。几年前做 umi ui 也做过一版,即 umi config 命令,umi 4 也有,但还不够完善。当前,很明显 magicast 基于 proxy 的方式写起来会更优雅。除了 umi config,另外想到可以应用的场景是 codemod 脚本,但不知道用深了之后坑多不多,因为 ast 操作边界场景实在是比较多,用户指不定会怎么写代码。

3、通过 README 文档,发现 API 层有 loadFile、writeFile、parseModule、generateCode、builders,属性层有 .$ast.$type.$args,同时还有些 helpers 方法在 magicast/helpers 下。

4、简单上手是这样。

a)新建 config.js,内容是 export default {foo: ['a']}
b)新建 test.mjs,内容如下。

import { loadFile, writeFile } from "magicast";
const mod = await loadFile("config.js");
mod.exports.default.foo.push("b");
await writeFile(mod);

c)pnpm i magicast -D
d)node test.mjs
e)此时会生成 output.js,内容是 export default {foo:["a","b"]

但是好像不支持 scope bindings。比如用户用了赋值的方式写,const foo = ["a"]; export default { foo };,简单试了下,发现并不支持。如果不支持的话,会有很多边界场景的坑。感觉可以完善下,增加一个配置项,可以在遇到遇到 identifier,顺着 scope 往上找 bindings。

5、源码方面依赖了 @babel/parser、@babel/types 和 recast。你可能会有疑问,为啥 @babel/parser 和 recast 会同

内容预览已结束

此内容需要会员权限。请先登录以查看完整内容。