x9.preval lets you generate code at compile-time.

Note: We shamelessly borrowed the name preval from babel-plugin-preval because we believe it is a brilliant naming choice and works well with JS developers (hat tip to @kentcdodds). While it shares similarities with the original babel-based preval, x9.preval is a different beast and, thanks to deep integration with the compiler and the IDE, provides a much better developer experience. A more accurate name would be “transparent, ergonomic, inline macros”. But that is a mouthful.

Overview

Let’s look at x9.preval in action!

If you write the following code (within any file in your project)

const numbers = x9.preval(() => [2, 3, 1].sort());

The compiler will notice the x9.preval expression and will “expand” it at compile-time into something like this:

const numbers = [1, 2, 3];

This example is practically useless, but it helps illustrate the fundamental idea: All x9.preval() expressions will be replaced, at compile time, with their output.

This “replacement” (also known as expansion, as in “macro expansion”) is not visible to you (the author) during editing. But the expanded version of the file is the one that ends up being bundled, executed, etc.

<aside> 💡 Tip: If you want to see the output of a preval expression, you can hover over it in the IDE

</aside>

x9.preval expressions are not limited to simple code like [2,1,3].sort(). They can execute full-blown functions.

Here’s a more realistic example that reads a markdown file from the filesystem, transforms it, and generates a string constant that can be later used by a vanilla React component:

// Poem.tsx

// this is a react component with a beautiful poem
// it takes its content from a separate file: "poem.md"
export const Poem = () => <div dangerouslySetInnerHTML={{ __html: poemHTML }}></div>

// we use x9.preval to read and process poem.md at compile time
const poemHTML = x9.preval(async () => {
  const file = resolve(__dirname, 'poem.md')
  const contents = await readFile(file)
  return marked(contents.toString())
});

// Note: we only moved these imports to the end
// of the file to make this example easier to understand
// there's nothing special about them
import { readFile } from from 'fs-extra';
import { resolve } from 'path';
import marked from "marked";

As soon as you save your code, the compiler will notice the x9.preval expression and will “expand” it behind the scenes into something like this:

export const Poem = () => <div dangerouslySetInnerHTML={{ __html: poemHTML }}></div>;const poemHTML = 'this is my <b>beautiful</b> poem';