Constexpr.js
What is constexpr?
Constexpr is a feature in programming languages that allows evaluation of parts of code at compile time.
What is constexpr.js?
constexpr.js is a static site generator which doesn't force you to learn a domain specific language.
When using this tool, you use javascript and usual DOM manipulation methods to generate the website. The tool
will render the page using chrome, and once it has finished rendering, it will save the rendered state of the
page as a new html file. This new html file will look exactly like the original page after it has finished rendering.
For example, the tool converts this page into this page.
It also strips the constexpr javascript out, potentially reducing download size for the website users drastically. Any piece of javascript
code that just generates some html can be made constexpr.
The generated page doesn't have to be completely static. In the above example, the heading is being animated
with javascript.
How to use it?
You will have to divide the javascript being used in your page into two groups. Runtime javascript and
compile time javascript, and annotate all compile time script tags with
Runtime code must not depend on the compile time code, since that code will be stripped out before writing the output file.
Once the HTML generation code has finished rendering, it must call the
The compiler can be installed like this:
Command line usage:
This is what an invocation looks like:
$ ./build.sh Using port:------------------------------------------------- 9046 Found path:------------------------------------------------- /404.html Found path:------------------------------------------------- /_template.html Ignoring path:---------------------------------------------- /demos/constexpr.js/input.html Ignoring path:---------------------------------------------- /demos/constexpr.js/output.html Found path:------------------------------------------------- /index.html Found path:------------------------------------------------- /posts/constexpr.js.html Found path:------------------------------------------------- /posts/intellij_logos.html Found path:------------------------------------------------- /posts/modifying_idea.html Found path:------------------------------------------------- /projects.html Using job count:-------------------------------------------- 5 Using job timeout:------------------------------------------ 999999999 Queued file #1:--------------------------------------------- /404.html Queued file #2:--------------------------------------------- /_template.html Queued file #3:--------------------------------------------- /index.html Queued file #4:--------------------------------------------- /posts/constexpr.js.html Queued file #5:--------------------------------------------- /posts/intellij_logos.html Page /_template.html signalled an abortion, message:-------- "is a template" (1/7) (abortion):------------------------------------------- /_template.html Queued file #6:--------------------------------------------- /posts/modifying_idea.html (2/7) Finished:--------------------------------------------- /index.html Queued file #7:--------------------------------------------- /projects.html (3/7) Finished:--------------------------------------------- /404.html (4/7) Finished:--------------------------------------------- /posts/intellij_logos.html (5/7) Finished:--------------------------------------------- /posts/modifying_idea.html (6/7) Finished:--------------------------------------------- /posts/constexpr.js.html (7/7) Finished:--------------------------------------------- /projects.html Copying resource:------------------------------------------- /static/css/global_styles.css Excluding resource:----------------------------------------- /collections/nav.json Copying resource:------------------------------------------- /static/css/prism.css Excluding resource:----------------------------------------- /static/js/constexpr/third_party/prism.js Excluding resource:----------------------------------------- /collections/posts.json Excluding resource:----------------------------------------- /collections/intellij_logos.json Copying resource:------------------------------------------- /static/img/intellij_logos/2009.09.01.png Copying resource:------------------------------------------- /static/img/intellij_logos/2009.09.09.png Copying resource:------------------------------------------- /static/img/intellij_logos/2009.09.13.png Copying resource:------------------------------------------- /static/img/intellij_logos/2009.11.03.png Copying resource:------------------------------------------- /static/img/intellij_logos/2010.00.11.png Copying resource:------------------------------------------- /static/img/intellij_logos/2010.06.22.png Copying resource:------------------------------------------- /static/img/intellij_logos/2010.10.16.png Copying resource:------------------------------------------- /static/img/intellij_logos/2010.10.30.png Copying resource:------------------------------------------- /static/img/intellij_logos/2011.00.14.png Copying resource:------------------------------------------- /static/img/intellij_logos/2011.06.19.png Copying resource:------------------------------------------- /static/img/intellij_logos/2011.06.22.png Copying resource:------------------------------------------- /static/img/intellij_logos/2011.08.05.png Copying resource:------------------------------------------- /static/img/intellij_logos/2011.10.15.png Copying resource:------------------------------------------- /static/img/intellij_logos/2011.11.01.png Copying resource:------------------------------------------- /static/img/intellij_logos/2012.00.10.png Copying resource:------------------------------------------- /static/img/intellij_logos/2012.03.23.png Copying resource:------------------------------------------- /static/img/intellij_logos/2012.05.27.png Copying resource:------------------------------------------- /static/img/intellij_logos/2012.10.07.png Copying resource:------------------------------------------- /static/img/intellij_logos/2012.10.28.png Copying resource:------------------------------------------- /static/img/intellij_logos/2012.10.30.png Copying resource:------------------------------------------- /static/img/intellij_logos/2012.11.26.png Copying resource:------------------------------------------- /static/img/intellij_logos/2013.00.14.png Copying resource:------------------------------------------- /static/img/intellij_logos/2013.04.15.png Copying resource:------------------------------------------- /static/img/intellij_logos/2013.04.22.png Copying resource:------------------------------------------- /static/img/intellij_logos/2013.10.04.png Copying resource:------------------------------------------- /static/img/intellij_logos/2013.10.27.png Copying resource:------------------------------------------- /static/img/intellij_logos/2014.00.21.png Copying resource:------------------------------------------- /static/img/intellij_logos/2014.01.07.png Copying resource:------------------------------------------- /static/img/intellij_logos/2014.02.05.png Copying resource:------------------------------------------- /static/img/intellij_logos/2014.02.11.png Copying resource:------------------------------------------- /static/img/intellij_logos/2014.03.07.png Copying resource:------------------------------------------- /static/img/intellij_logos/2014.08.28.png Copying resource:------------------------------------------- /static/img/intellij_logos/2014.09.20.png Copying resource:------------------------------------------- /static/img/intellij_logos/2015.03.29.png Copying resource:------------------------------------------- /static/img/intellij_logos/2015.04.13.png Copying resource:------------------------------------------- /static/img/intellij_logos/2015.04.19.png Copying resource:------------------------------------------- /static/img/intellij_logos/2015.08.04.png Copying resource:------------------------------------------- /static/img/intellij_logos/2015.09.21.png Copying resource:------------------------------------------- /static/img/intellij_logos/2015.11.03.png Copying resource:------------------------------------------- /static/img/intellij_logos/2015.11.17.png Copying resource:------------------------------------------- /static/img/intellij_logos/2016.04.11.png Copying resource:------------------------------------------- /static/img/intellij_logos/2016.06.19.png Copying resource:------------------------------------------- /static/img/intellij_logos/2016.11.13.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.03.18.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.05.26.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.05.27.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.05.28.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.05.30.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.08.05.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.08.06.png Copying resource:------------------------------------------- /static/img/intellij_logos/2017.09.24.png Copying resource:------------------------------------------- /static/img/intellij_logos/2018.00.22.png Copying resource:------------------------------------------- /static/img/intellij_logos/2018.04.14.png Copying resource:------------------------------------------- /static/img/intellij_logos/2018.08.08.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.00.14.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.03.04.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.04.07.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.04.10.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.04.29.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.05.08.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.05.12.png Copying resource:------------------------------------------- /static/img/intellij_logos/2019.08.02.png Copying resource:------------------------------------------- /static/img/intellij_logos/2020.00.21.png Copying resource:------------------------------------------- /static/img/intellij_logos/2020.04.21.png Copying resource:------------------------------------------- /static/img/intellij_logos/2020.08.16.png Copying resource:------------------------------------------- /static/img/intellij_logos/2021.00.21.png Copying resource:------------------------------------------- /static/css/pivot.css Copying resource:------------------------------------------- /static/css/asciinema-player.css Copying resource:------------------------------------------- /static/files/tips.csv Copying resource:------------------------------------------- /static/files/build.cast Excluding resource:----------------------------------------- /collections/projects.json ~/src/fctorial.github.io.src $ ~/src/fctorial.github.io.src $
A json object with the command line args, compilation results and dependencies will be written to the path specified by
Notes
-
You can use any web development technology (and any number of technologies) to generate the html without any fear
of bloat. Just make sure that
window._ConstexprJS_.compile() is called after the page has finished rendering.
Pivottable.js demo:
day Fri Sat Sun Thur Totals sex smoker Female No 6.25 35.42 46.61 61.49 149.77 Yes 18.78 43.03 14.00 20.93 96.74 Male No 5.00 104.21 133.96 58.83 302.00 Yes 21.93 77.74 52.82 30.58 183.07 Totals 51.96 260.40 247.39 171.83 731.58
This page also uses prism.js for syntax highlighting and asciinema-player for the./build.sh output, along with jquery and papaparse. A total of 1.1mb of javascript that you don't have to download because it's constexpr. -
You can mark tags other than
script withconstexpr as well. In the above example, the box at the top is marked constexpr, so it isn't present in the output page. This can be used to differentiate original website from generated website:<style constexpr> body { border: 2px solid red; } </style> -
Client code in the page can signal the compiler to skip the current file by calling
window._ConstexprJS_.abort(message) . -
In the original webpage, you'll see a console error when the code tries to call the compilation trigger functions,
since those functions are injected by the compiler. You can add this snippet near the top to fix that error:
<script constexpr> if (!window._ConstexprJS_) { window._ConstexprJS_ = { compile: () => {}, abort: () => {} } } </script> -
There might be multiple rendering tasks running in your page. You can manage all those tasks using this
refcounting mechanism.
All the tasks will call
startLoading() when they begin loading, andendLoading() when they've finished loading. The compilation will be triggered when all the tasks have finished. -
You should keep all list data separate from the html in json files.
constexpr code in the html will fetch these json files and render the page using them. The directory containing this data should be excluded using--exclusions flag, so that the resources inside it aren't copied over. - You can include dev utilites like this in the original website. It reloads the page whenever it's focused. It won't be in the output since it's used as constexpr.
-
This whole website is rendered using javascript and constexpr.js The html files contains only the page specific stuff.
All the styling and theming is done by constexpr code. Nothing other than the demo uses runtime javascript:
$ tokei -t=javascript =============================================================================== Language Files Lines Code Comments Blanks =============================================================================== JavaScript 1 2 1 0 1 =============================================================================== Total 1 2 1 0 1 =============================================================================== The original sources can be found here.