Top

constexpr.js allows you to execute some of the javascript in your website before it is deployed. I'll refer to such javascript as constepxr. You can use constexpr code for programmatically generating HTML in your website.

The constexpr code is stripped out by the compiler, so the runtime code must not depend on it. Hence, there has to be a clear boundary between the runtime code and compile time code. In this article I'll share some tips for managing code when building a site with constexpr.js.

This article requires some familiarity with constexpr.js. Read this guide to get up and running with constexpr.js.

A simple example

Set up the environment as described in the above linked guide. After that, put this in index.html:

<html> <head> <title>Dynamic Pages Example</title> </head> <body> <p>This page was rendered on: <span id="timestamp"></span></p> </body> <script constexpr> let d = new Date() document.querySelector('#timestamp').textContent = `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}` window._ConstexprJS_.compile() </script> </html>

And run the compiler:

constexprjs --input=. --output=_out --entry=index.htm

The compiler will emit the following static website:

<html> <head> <title>Dynamic Pages Example</title> </head> <body> <p>This page was rendered on: <span id="timestamp">1:58:5</span></p> </body> </html>

Let's add a button to this page that will add all the numbers in the timestamp and alert the result, just to demonstrate how to build non-static websites with constexpr.js. Let's first modify our rendering code to add a button to the page:

<script constexpr> let d = new Date() document.querySelector('#timestamp').textContent = `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}` let b = document.createElement('button') b.textContent = "Calculate" document.body.appendChild(b) window._ConstexprJS_.compile() </script>

After that, define a regular, non-constexpr function named runtime_bootstrap that will add an event listener to this button:

<script> function runtime_bootstrap() { document.querySelector('button').addEventListener('click', () => { let result = 0 document.querySelector('#timestamp').textContent.split(':') .forEach(s => result += parseInt(s)) alert(result) }) } </script>

Finally we'll modify the rendering code to add a script tag to our page that calls the bootstrap function:

<script constexpr> ... let s = document.createElement('script') s.textContent = 'runtime_bootstrap()' document.body.appendChild(s) window._ConstexprJS_.compile() </script>

Now when you run the compiler, you will get the following page as output:

<html> <head> <title>Dynamic Pages Example</title> <script> function runtime_bootstrap() { document.querySelector('button').addEventListener('click', () => { let result = 0 document.querySelector('#timestamp').textContent.split(':') .forEach(s => result += parseInt(s)) alert(result) }) } </script> </head> <body> <p>This page was rendered on: <span id="timestamp">2:32:13</span></p> <button>Calculate</button> <script>runtime_bootstrap()</script> </body> </html>

This page contains three things:

  1. Generated HTML (timestamp and button)
  2. Runtime bootstrap function
  3. A script tag that calls the bootstrap function

All the rendering code has been stripped out.

Implementation in this website

The mobile view transitions in this site use javascript. If you're on desktop, you can test it by enabling mobile emulation in devtools (Top left in chrome and top right in firefox).

In this website, the rendering code generates all the site global theming (navbar, sidebars, syntax highlighting etc). I've put this code in /static/js/constexpr/renderer.js. This script is included as constexpr in every page.

The code that bootstraps the dynamic behavior is contained in a separate file, /static/js/dynamic.js. The constexpr code in renderer.js adds this script tag to every page once it has finished rendering:

el = document.createElement('script') el.src = '/static/js/dynamic.js' document.body.appendChild(el)

This page also uses this technique. The rendering code generates the list of images at compile time and the bootstrap function initHover attaches hover event listeners to the images. You can find the source code of original page here here.

See pages tagged with constexpr.js for more guides.