babel宏是导出default函数的.macro文件,编译期同步执行并替换ast;无需配置、开箱即用,适用于环境变量注入、路径预解析等场景。

babel-plugin-macros 是一个轻量、零配置的 Babel 插件机制,它让你无需修改 Babel 配置就能在代码中“调用”自定义编译时逻辑——本质是把普通 JS 模块当宏用,Babel 在构建时自动识别并执行它们。
宏怎么写:一个函数 + 默认导出
宏就是一个导出默认函数的 Node.js 模块(通常用 .macro.js 后缀区分),函数接收两个参数:babel(Babel API 对象)和 config(可选配置)。函数需返回一个 Babel 插件对象(含 visitor)。
- 文件路径必须能被 import 路径解析到,例如
import { styled } from './styled.macro.js' - Babel 会自动识别后缀为
.macro.js(或.macro.ts等)的模块,并跳过常规加载,直接执行该函数 - 不需要在
babel.config.js中注册插件,也不需要 npm install 宏包(除非你用别人发布的宏)
一个真实例子:log.macro.js —— 编译时替换 console.log
假设你想把开发环境的 console.log('msg', val) 自动转成带文件名和行号的调试日志,且生产环境完全移除:
module.exports = function createMacro({ types: t }) {
return {
visitor: {
CallExpression(path) {
const { node } = path;
// 匹配 import 进来的 log 函数调用
if (
t.isIdentifier(node.callee) &&
node.callee.name === 'log' &&
path.parentPath.isExpressionStatement()
) {
const fileName = path.hub.file.opts.filename || '';
const line = node.loc?.start.line || '?';
const args = node.arguments;
// 开发环境:增强日志;生产环境:替换成空语句
if (process.env.NODE_ENV === 'production') {
path.replaceWith(t.expressionStatement(t.nullLiteral()));
} else {
const enhancedArgs = [
t.stringLiteral(`[${fileName}:${line}]`),
...args
];
path.replaceWith(
t.expressionStatement(
t.callExpression(t.identifier('console.log'), enhancedArgs)
)
);
}
}
}
}
};
};
使用时只需:
import { log } from './log.macro.js';
log('user loaded', user); // 编译后变成 console.log("[src/App.js:5]", "user loaded", user)
如何在项目中启用 macro
- 安装依赖:
npm install --save-dev babel-plugin-macros - 确保你的 Babel 配置(如
babel.config.js)里已包含它(Create React App / Next.js 等现代脚手架默认已内置) - 如果手动配置,加一行:
plugins: ['babel-plugin-macros'] - 不支持宏的打包器(如原生 Vite)需额外配置(Vite 可通过
@rollup/plugin-babel或vite-plugin-babel-macros支持)
常见误区与提示
- 宏运行在编译时,不能访问运行时变量或 this;所有逻辑必须基于 AST 分析和静态推断
- 不要在宏里做异步操作(如读文件、发请求),Babel 插件必须同步返回
- 调试宏可用
console.log+ 构建时加--verbose,或用@babel/traverse的hub.file.opts.filename定位上下文 - 想发布公共宏?导出为 npm 包,入口文件命名为
index.macro.js,用户import xxx from 'xxx/macro'即可(注意包内也要有"exports"正确指向)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











