preval.macro: Build-Time Code Evaluation
preval.macro is a Babel macro designed to pre-evaluate code at build-time, embedding the results directly into the JavaScript bundle. It leverages `babel-plugin-preval` under the hood, offering a streamlined way to achieve static code evaluation without direct Babel plugin configuration, thanks to its integration with `babel-plugin-macros`. The current stable version is 5.0.0. This package is particularly useful for tasks like inlining static file contents, injecting environment variables known at build time, or pre-calculating complex values, thereby reducing runtime computations and potentially optimizing bundle size. Its release cadence is generally aligned with updates to the broader Babel ecosystem and its upstream dependencies, `babel-plugin-preval` and `babel-plugin-macros`.
Common errors
-
ReferenceError: preval is not defined
cause The `babel-plugin-macros` plugin is not installed or incorrectly configured in your Babel setup, preventing the macro from being processed.fixInstall `babel-plugin-macros` as a `devDependency` (`npm install --save-dev babel-plugin-macros`) and add it to your Babel configuration (e.g., `plugins: ['macros']` in `.babelrc.js` or `babel.config.js`). -
TypeError: preval is not a function
cause Attempting to call `preval` as a regular function (e.g., `preval('some code')`) or passing arguments directly, instead of using it as a tagged template literal.fixEnsure `preval` is used as a tagged template literal: `preval`module.exports = 'your_value'`. -
Error: ENOENT: no such file or directory, open '/path/to/your/file.txt'
cause A file path referenced within the `preval` tagged template literal (e.g., using `fs.readFileSync`) is incorrect or the specified file does not exist at the time the Babel build process runs.fixVerify that the file path is correct and accessible relative to the file containing the `preval` macro during the build process. Use `path.resolve(__dirname, 'your-file.txt')` for more robust, absolute path resolution. -
SyntaxError: Unexpected token '{'cause Incorrectly using destructuring for the `preval` import or require, e.g., `import { preval } from 'preval.macro'`.fixUse the default import for `preval`: `import preval from 'preval.macro'` for ESM or `const preval = require('preval.macro')` for CommonJS.
Warnings
- gotcha `preval.macro` operates at build-time, meaning the code inside the tagged template literal is executed by Node.js during your Babel compilation step, not in the browser or Node.js runtime. This implies browser-specific globals like `window` or DOM APIs are unavailable within preval'd code.
- breaking Older versions of `babel-plugin-macros` (and indirectly `preval.macro`) might behave differently or require specific configuration. As the Babel ecosystem evolves, ensure your `babel-plugin-macros` setup is current.
- gotcha The values generated by `preval.macro` are hardcoded into your bundle at compile time. If the source of these values (e.g., environment variables, static files) changes after compilation, your application will continue to use the stale, embedded data.
- gotcha Executing complex or I/O-heavy operations (e.g., reading very large files, extensive computations) within `preval` can significantly increase your build times. Overuse can also lead to larger bundle sizes if substantial data structures or files are embedded directly.
Install
-
npm install preval.macro -
yarn add preval.macro -
pnpm add preval.macro
Imports
- preval
import { preval } from 'preval.macro'import preval from 'preval.macro'
- preval (CommonJS)
const { preval } = require('preval.macro')const preval = require('preval.macro') - Code Block (Tagged Template Literal)
preval('module.exports = "some_value"')preval`module.exports = 'some_value'`
Quickstart
/*
1. Install dependencies:
npm install --save-dev @babel/cli @babel/core babel-plugin-macros preval.macro
2. Create `.babelrc.js` in your project root:
module.exports = {
plugins: ['macros'],
};
3. Create `src/index.js`:
*/
import preval from 'preval.macro';
// Pre-evaluate a simple arithmetic expression during build
const sum = preval`module.exports = 10 + 20`;
console.log('The sum is:', sum); // During build, 'sum' becomes 30
// Pre-evaluate and embed an environment variable (e.g., BUILD_ID=abc)
// To see this in action, run Babel with an environment variable:
// BUILD_ID=123 babel src --out-dir dist
const buildId = preval`module.exports = process.env.BUILD_ID || 'N/A'`;
console.log('Build ID:', buildId); // 'buildId' becomes '123' at build time
// Read a file at build-time and embed its content
// Create a file `src/data.txt` with content: 'Hello Preval World!'
const fileContent = preval`
const fs = require('fs');
const path = require('path');
module.exports = fs.readFileSync(path.resolve(__dirname, 'data.txt'), 'utf8');
`;
console.log('File Content:', fileContent); // 'fileContent' becomes 'Hello Preval World!'
/*
4. Create `src/data.txt` in the same directory as `src/index.js`
with content: `Hello Preval World!`
5. Compile with Babel from your project root:
BUILD_ID=123 babel src --out-dir dist
6. Run the compiled output:
node dist/index.js
// Expected output:
// The sum is: 30
// Build ID: 123
// File Content: Hello Preval World!
*/