{"id":12868,"library":"babel-plugin-macros","title":"Babel Plugin Macros","description":"babel-plugin-macros is a Babel plugin that enables the creation of compile-time code transformations through a standard, convention-based interface, eliminating the need for users to configure individual Babel plugins for each library that offers such optimizations. It allows libraries to provide compile-time benefits (like CSS-in-JS style extraction or GraphQL fragment compilation) by detecting imports ending with `.macro` and processing them. The current stable version is 3.1.0, released in May 2021. While not frequently updated, it remains a foundational tool, notably integrated into popular frameworks like Create React App. Its key differentiator is simplifying the developer experience by centralizing build-time transformations under a single Babel plugin configuration, making compile-time optimizations more accessible and easier to manage.","status":"maintenance","version":"3.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/kentcdodds/babel-plugin-macros","tags":["javascript","babel-plugin","macros","macro","babel-macro","babel-plugin-macro","babel-macros","babel-plugin-macros"],"install":[{"cmd":"npm install babel-plugin-macros","lang":"bash","label":"npm"},{"cmd":"yarn add babel-plugin-macros","lang":"bash","label":"yarn"},{"cmd":"pnpm add babel-plugin-macros","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"babel-plugin-macros is a Babel plugin and requires a Babel environment to function. While not a direct runtime dependency in the npm `dependencies` sense, `@babel/core` is a peer dependency of the Babel ecosystem and must be installed for Babel plugins to run. Macro authors also interact with `@babel/core`'s AST utilities.","package":"@babel/core","optional":false}],"imports":[{"note":"Users consume macros by importing them with a `.macro` suffix (e.g., `my.macro`, `my/macro`). This suffix signals `babel-plugin-macros` to intercept and transform the import at compile time. Omitting it will result in a standard module import, bypassing macro processing.","wrong":"import MyMacro from './path/to/my';","symbol":"MyMacro","correct":"import MyMacro from './path/to/my.macro';"},{"note":"Macro authors use `createMacro` to define their macro logic. While `require` works for CommonJS macro files, `import` is generally preferred in modern JavaScript. The `createMacro` function wraps the macro's core logic, providing it with Babel AST references, state, and a Babel instance.","wrong":"const { createMacro } = require('babel-plugin-macros');","symbol":"createMacro","correct":"import { createMacro } from 'babel-plugin-macros';"},{"note":"Macros can be configured via a `babel-plugin-macros.config.js` file or `babelMacros` entry in `package.json`. This allows macros to receive specific options without requiring per-macro Babel plugin configuration.","symbol":"ConfiguredMacro","correct":"import ConfiguredMacro from 'configured-lib.macro';"}],"quickstart":{"code":"/* .babelrc.js */\nmodule.exports = {\n  plugins: ['babel-plugin-macros'],\n};\n\n/* log.macro.js */\nconst { createMacro } = require('babel-plugin-macros');\n\nmodule.exports = createMacro(({ references, state, babel }) => {\n  // console.log('[log.macro] Running macro for file:', state.file.opts.filename);\n  references.default.forEach(referencePath => {\n    if (referencePath.parentPath.type === 'CallExpression') {\n      const args = referencePath.parentPath.node.arguments;\n      const messages = args.map(arg => {\n        // Only process string and numeric literals for simplicity in quickstart\n        if (babel.types.isStringLiteral(arg) || babel.types.isNumericLiteral(arg)) {\n          return arg.value;\n        } else if (babel.types.isIdentifier(arg)) {\n          return `[runtime_value: ${arg.name}]`; // Indicate it's a runtime value\n        }\n        return 'unknown_type';\n      });\n      console.log(`[log.macro] Compiling-time log: ${messages.join(', ')}`);\n      // Replace the macro call with `undefined` to remove it from runtime bundle\n      referencePath.parentPath.replaceWith(babel.types.valueToNode(undefined));\n    } else {\n      // Handle other types of references if necessary, or throw an error\n      throw new Error(`log.macro can only be called as a function.`);\n    }\n  });\n});\n\n/* app.js */\nimport log from './log.macro';\n\nlog('Hello', 'world', 123); // This will be logged at compile time\n\nconst runtimeVar = 'dynamic message';\nlog('This part is static:', runtimeVar); // `runtimeVar` will be treated as '[runtime_value: runtimeVar]'\n\nconsole.log('Runtime code runs after macro transformations.');\n\n// To run:\n// 1. npm install --save-dev @babel/cli @babel/core babel-plugin-macros\n// 2. npx babel app.js --out-file app-compiled.js\n// 3. node app-compiled.js","lang":"javascript","description":"This quickstart demonstrates how to define and use a simple `log.macro` to perform compile-time logging and remove the macro calls from the final bundle, showcasing the core concept of compile-time code transformation."},"warnings":[{"fix":"Upgrade Node.js to version 10 or higher, or pin `babel-plugin-macros` to a version below 3.0.0.","message":"Version 3.0.0 updated its Node.js engine requirement to `>=10`. Projects running on older Node.js versions will need to upgrade or remain on `babel-plugin-macros` v2.x.x.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Review macro configuration files (`.babel-plugin-macrosrc.*`, `babelMacros` in `package.json`) and ensure they are correctly resolved by `cosmiconfig`'s updated logic. Test thoroughly after upgrading.","message":"Updates to `cosmiconfig` in v2.6.2 and subsequent versions (including v3.0.0) might subtly change how macro configurations are resolved, particularly if custom `configName` options are used or if configuration files are in non-standard locations.","severity":"breaking","affected_versions":">=2.6.2"},{"fix":"Ensure all macro logic is synchronous and operates only on static values or the AST provided. For dynamic runtime data, process it outside the macro or pass it as static arguments.","message":"Macros run purely at *compile-time* and cannot access runtime values or perform asynchronous operations. Any logic within a macro must be synchronous and operate solely on the Abstract Syntax Tree (AST) available during the Babel transformation step. Attempting to use runtime variables will result in compile errors or unexpected `undefined` values.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"To force a recompile during development, add a 'cache busting' comment to the file using the macro (e.g., `// force recompile`). Alternatively, clear Babel's cache (e.g., `rm -rf node_modules/.cache/babel-loader`). This issue is being worked on by Babel core.","message":"Babel's caching mechanisms can sometimes prevent macros from re-running during development if the source file itself hasn't changed, even if the macro's internal logic or its dependencies have. This can lead to stale transformations.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure that any imports intended to be processed by `babel-plugin-macros` explicitly include the `.macro` suffix in their path, e.g., `import MyMacro from './my-macro.macro';`","cause":"The imported file is a macro, but the `.macro` suffix was omitted in the import path, preventing `babel-plugin-macros` from intercepting it.","error":"Module not found: Error: Can't resolve './my-macro'"},{"fix":"Install `babel-plugin-macros` (`npm install --save-dev babel-plugin-macros`) and add it to your Babel configuration's `plugins` array: `plugins: ['macros']`. If using Create React App, it often works out of the box.","cause":"The `babel-plugin-macros` plugin is not correctly installed or configured in the project's Babel configuration (`.babelrc`, `babel.config.js`).","error":"ReferenceError: myMacro is not defined"},{"fix":"Check the macro's documentation for any required configuration settings. Ensure the `configName` provided to `createMacro` (if applicable) matches the name used in your `babel-plugin-macros.config.js` or `package.json`'s `babelMacros` field. Verify the macro file itself is correctly located and exports a `createMacro` function.","cause":"While `babel-plugin-macros` is configured, the specific macro being used might require additional configuration parameters, or there's a typo in the macro's name or its configuration. (Note: this specific error string might be more generic like 'Error: 'macroName' macro does not exist' depending on the exact version and usage)","error":"Error: The macro 'my-macro' is not specified in your babel config"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null}