Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live mode -- allows one to change non-code parts of diet templates and render at runtime #70

Merged
merged 8 commits into from
Mar 23, 2020
86 changes: 80 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,92 @@ enabled by defining the version constant `DietUseCache` (
dub.sdl). It is not recommended to use this feature outside of the usual
edit-compile-run development cycle, especially not for release builds.

Once enabled, the template compiler will look for `_cached_*.d` files in the
"views/" folder, where the `*` consists of the file name of the Diet template
and a unique hash value that identifies the contents of the template, as well
as included/extended ones. If found, it will simply use the contents of that
file instead of going through the whole compilation process.
Once enabled, the template compiler will look for `*_cached_#####.d` files in the
"views/" folder, where the `*` consists of the full path of the Diet template
and `#####` represents a unique hash value that identifies the contents of the
template, as well as included/extended ones. If found, it will simply use the
contents of that file instead of going through the whole compilation process.

At runtime, during initialization, the program will then output the contents of
all newly compiled templates to the "views/" folder. For that reason it is
currently **important that the program is run with the current working directory
set to the package directory!** A drawback of this method is that outdated
cached templates will not be deleted automatically. It is necessary to clear all
`_cached_*` files by hand from time to time.
`*_cached_*.d` files by hand from time to time.

*Note that hopefully this feature will be obsoleted soon by the [work of Stefan
Koch on DMD's CTFE engine](https://github.com/UplinkCoder/dmd/commits/newCTFE).*

Experimental HTML Live Mode
----------------------------------

Building a diet template at compile-time can be slow, as mentioned above. A
major drawback of this is that during development, any single change to any
diet file requires a complete rebuild of the entire project.

The library now supports a "Live Mode", where any changes to the templates that
are strictly HTML related will be rendered on a page refresh, instead of
requiring a recompilation. This works by replacing output of the HTML portions
of the template with output from a lookup table of strings. Then the strings
are rebuilt whenever the file changes. So for example, adding or removing a
class from an html element, or fixing `herf` to `href` in an anchor element
does not require a recompile.

Changes to code portions of the template (i.e. string interpolations such as
`#{expression}` or `!{expression}`, or any D code escapes such as `- foreach(x;
range)`) will throw an exception, and force you to recompile your project before
continuing. This is because the diet engine can deal with changes to string
data, but cannot recompile your project for you. And obviously, changing code
outside the templates will not change the rendered pages without a recompile.
Even adding new lines or inserting lines where HTML did not exist is supported.

For example:

```pug
- if(cond)
- auto a = foobar();
```

changed to the following will not require a recompile

```pug
- if(cond)
a(href="/") Home
- auto a = foobar();
```

The mode is enabled by defining the version constant `DietUseLive` (
`"versions": ["DietUseLive"]` in dub.json or `versions "DietUseLive"` in
dub.sdl). It is not recommended to use this in production for the same reasons
listed for the caching mode.

To be as efficient as possible, the templates are only parsed on first access,
and re-parsed only when a modification in any template or dependent template is
detected. Note that it still will not be as efficient as the normal mode which
doesn't require any file i/o to render templates.

There are a few limitations to this approach. Like `DietUseCache`, this
REQUIRES the views directory to be accessible to the running executable. In
addition, to keep the code generation simple (and avoid a full D parser),
certain features do not work with Live Mode. Two such features are type
definitions (i.e. structs, unions, or classes), and static functions. There is
no escape mechanism to allow these, so you will have to ensure that they are not
present in your diet templates, or you will get probably very strange compiler
errors.

Any other problems, please report them in github.

This mode and the `DietUseCache` mode can be combined. Just define both
versions in your project's dub configuration.

Examples Directory
------------------

The examples directory contains 2 projects showcasing the features of diet.

* `htmlgenerator` - Uses diet-ng to generate static html files from diet
templates.
* `htmlserver` - Simple vibe.d project that shows some features of diet
template parsing. Note that there are multiple configurations that show how
the caching and live mode work. Please see the README.md file for more details
in that directory.
35 changes: 35 additions & 0 deletions examples/htmlserver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# HTML Server Example

In this subdirectory, you will find an example HTML server. There are several
configurations you can run to see how they work.

## Normal mode

If you just run with `dub`, you will get the standard diet-ng build for the
templates. This build uses the diet-ng compiler to build the dynamically
generated code. Changing the view template during runtime does not alter the
produced page, as the view file is not reprocessed.

## Live Mode

Using `dub --config=dietLive` will build this project in "live" mode. In live
mode, changes to the template only related to HTML will be rendered without a
recompile. Any string interpolations or D code escapes must remain the same, as
changing these items would require a recompile of the server.

Note that live mode is intended for development purposes to avoid a full
compile cycle for front-end changes. It will not perform as well as the normal
build, and it requires access to the views directory to display any templates.

## Cached mode

Using `dub --config=dietCache` will build this project in "cached" mode. On the
first execution of this build, the mixin generated by the compiler is cached
inside the views directory. Upon supsequent builds, as long as the template
source has not changed, the cached version is used.

This is much faster as the library does not need to build the DOM of the diet
file at compile time and process it.

Please see the main README file inside the diet-ng project for more information
about these features.
11 changes: 11 additions & 0 deletions examples/htmlserver/dub.sdl
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
name "htmlserver"
dependency "diet-ng" path="../.."
dependency "vibe-d" version="~>0.8.5"
configuration "application" {
targetType "executable"
}
configuration "dietLive" {
targetType "executable"
versions "DietUseLive"
}
configuration "dietCache" {
targetType "executable"
versions "DietUseCache"
}
2 changes: 1 addition & 1 deletion source/diet/defs.d
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ alias DietParserException = Exception;
Throws a `DietParserException` when called with a `false` condition at
run time.
*/
void enforcep(bool cond, lazy string text, in ref Location loc)
void enforcep(bool cond, lazy string text, in ref Location loc) @safe
{
if (__ctfe) {
import std.conv : to;
Expand Down
1 change: 1 addition & 0 deletions source/diet/dom.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module diet.dom;

import diet.internal.string;

@safe:

string expectText(const(Attribute) att)
{
Expand Down
Loading