返回归档

归档 2018

jsx-template:JSX 动态模板实践

jsx-template 项目实践:把 JSX 入口编译为运行时模板方法,动态执行返回 HTML 字符串;记录新旧两版 transform 流程与 babel 插件带 loader 的匹配方案。

JSXBabel模板引擎
本文目录3
  1. 新版动态模板流程
  2. 旧的 transform 流程(已废弃)
  3. babel 插件 transform-imports 带 loader 版本

jsx-template 是一个"用 JSX 写模板"的实践项目:借助 babel 把 JSX 语法编译成可执行的模板方法,服务端或浏览器端动态执行后返回 HTML 字符串。相比字符串拼接模板,JSX 拥有完整的 JavaScript 表达式能力与编译期校验。

新版动态模板流程

jsx-template 动态模板流程

  1. 传入 jsx 入口文件地址
  2. 调用 jsx-template-transform 处理入口文件:解析 JSX 并编译为方法字符串。
  3. 动态执行返回的方法字符串new Function / eval 一类方式加载编译产物)。
  4. 生成一个模板方法:接收参数并返回 HTML 字符串。调用方传入数据即可渲染,模板内可自由使用表达式、条件与循环。

这样模板与数据分离:模板方法只依赖传入参数,天然适合多份数据复用同一模板的场景。

旧的 transform 流程(已废弃)

jsx-template transform 旧流程

旧实现走的是 babel 标准转换管线:

  1. 传入要处理的文件地址并读取文件内容 code。
  2. 在 code 最前面注入 createElement(或 h)辅助函数,让 JSX 编译产物的调用有处可落。
  3. 使用 @babel/core 的 transform API 处理 code。
  4. 依次应用 @babel/preset-env@babel/plugin-transform-* 系列插件完成语法降级与 JSX 转换。
  5. 输出最终代码。

该版本已废弃,原因集中在灵活性不足:注入逻辑写死在入口、整个文件作为整体转换,难以按模块精细化控制。

babel 插件 transform-imports 带 loader 版本

babel-plugin-transform-imports with loader

为了支持"按 import 来源决定是否转换",实现了一个 babel 插件 + loader 的组合:

  1. 定义缓存变量,存储反序列化所用到的方法(unserializeFuncUUIDCache),避免重复解析。
  2. 插件监听 ImportDeclaration 节点,并验证用户传入的 LoaderOptions
  3. 根据当前 import 的文件,找到满足条件的 matchedLoader
    • 存在:对该 import 执行转换(改写导入路径 / 注入运行时方法);
    • 不存在:跳过,保留原始 import 不变。

该设计把"是否转换"的判定下放到 import 粒度,配合 webpack loader 在编译期完成,使同一份源码里可以混合"需要模板化的模块"与"保持原样的模块"。

返回首页
上一篇Docker下一篇loader-runner 执行机制

Discussion

留言与讨论

想法、补充和不同意见都欢迎。