template
# *template*: Templating Engine (HTML) für Lua und nginx-module-lua
## Installation
Wenn Sie das RPM-Repository-Abonnement noch nicht eingerichtet haben, [melden Sie sich an](https://www.getpagespeed.com/repo-subscribe). Dann können Sie mit den folgenden Schritten fortfahren.
### CentOS/RHEL 7 oder Amazon Linux 2
```bash
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-template
CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-template
Um diese Lua-Bibliothek mit NGINX zu verwenden, stellen Sie sicher, dass nginx-module-lua installiert ist.
Dieses Dokument beschreibt lua-resty-template v2.0, das am 24. Februar 2020 veröffentlicht wurde.
lua-resty-template ist eine kompilierende (1) (HTML) Templating-Engine für Lua und OpenResty.
(1) Mit Kompilierung meinen wir, dass Vorlagen in Lua-Funktionen übersetzt werden, die Sie aufrufen oder string.dump als binäre Bytecode-Blobs auf die Festplatte speichern können, die später mit lua-resty-template oder den grundlegenden load- und loadfile-Standard-Lua-Funktionen verwendet werden können (siehe auch Template-Vorkompilierung). Obwohl Sie das im Allgemeinen nicht tun müssen, da lua-resty-template dies im Hintergrund erledigt.
Hello World mit lua-resty-template
local template = require "resty.template" -- ODER
local template = require "resty.template.safe" -- gibt nil, err bei Fehlern zurück
-- Verwendung von template.new
local view = template.new "view.html"
view.message = "Hallo, Welt!"
view:render()
-- Verwendung von template.render
template.render("view.html", { message = "Hallo, Welt!" })
view.html
<!DOCTYPE html>
<html>
<body>
<h1>{{message}}</h1>
</body>
</html>
Ausgabe
<!DOCTYPE html>
<html>
<body>
<h1>Hallo, Welt!</h1>
</body>
</html>
Das gleiche kann mit einer Inline-Vorlagenzeichenfolge gemacht werden:
-- Verwendung der Vorlagenzeichenfolge
template.render([[
<!DOCTYPE html>
<html>
<body>
<h1>{{message}}</h1>
</body>
</html>]], { message = "Hallo, Welt!" })
Inhalte
- Template-Syntax
- Beispiel
- Reservierte Kontextschlüssel und Anmerkungen
- Installation
- Verwendung des OpenResty-Paketmanagers (opm)
- Verwendung von LuaRocks
- Nginx / OpenResty-Konfiguration
- Lua-API
- template.root
- template.location
- table template.new(view, layout)
- boolean template.caching(boolean oder nil)
- function, boolean template.compile(view, cache_key, plain)
- function, boolean template.compile_string(view, cache_key)
- function, boolean template.compile_file(view, cache_key)
- template.visit(func)
- string template.process(view, context, cache_key, plain)
- string template.process_string(view, context, cache_key)
- string template.process_file(view, context, cache_key)
- template.render(view, context, cache_key, plain)
- template.render_string(view, context, cache_key)
- template.render_file(view, context, cache_key)
- string template.parse(view, plain)
- string template.parse_string(view, plain)
- string template.parse_file(view, plain)
- string template.precompile(view, path, strip)
- string template.precompile_string(view, path, strip)
- string template.precompile_file(view, path, strip)
- string template.load(view, plain)
- string template.load_string(view)
- string template.load_file(view)
- template.print
- Template-Vorkompilierung
- Template-Helfer
- Eingebaute Helfer
- Andere Möglichkeiten zur Erweiterung
- Verwendungsbeispiele
- Template-Einbindung
- Views mit Layouts
- Verwendung von Blöcken
- Großvater-Vater-Sohn-Vererbung
- Makros
- Methoden in Vorlagen aufrufen
- Einbetten von Angular oder anderen Tags / Templating innerhalb der Vorlagen
- Einbetten von Markdown innerhalb der Vorlagen
- Lua Server Pages (LSP) mit OpenResty
- FAQ
- Alternativen
- Benchmarks
- Änderungen
- Roadmap
- Siehe auch
- Lizenz
Template-Syntax
Sie können die folgenden Tags in Vorlagen verwenden:
{{expression}}, schreibt das Ergebnis des Ausdrucks - HTML-escaped{*expression*}, schreibt das Ergebnis des Ausdrucks{% lua code %}, führt Lua-Code aus{(template)}, schließt dietemplate-Datei ein, Sie können auch einen Kontext für die eingeschlossene Datei bereitstellen{(file.html, { message = "Hallo, Welt" })}(HINWEIS: Sie können kein Komma (,) infile.htmlverwenden, verwenden Sie in diesem Fall{["file,with,comma"]}stattdessen){[expression]}, schließt dieexpression-Datei ein (das Ergebnis des Ausdrucks), Sie können auch einen Kontext für die eingeschlossene Datei bereitstellen{["file.html", { message = "Hallo, Welt" }]}{-block-}...{-block-}, wickelt innerhalb eines{-block-}einen Wert ein, der in einerblocks-Tabelle mit einem Schlüsselblockgespeichert ist (in diesem Fall), siehe Verwendung von Blöcken. Verwenden Sie keine vordefinierten Blocknamenverbatimundraw.{-verbatim-}...{-verbatim-}und{-raw-}...{-raw-}sind vordefinierte Blöcke, deren Inhalt nicht vonlua-resty-templateverarbeitet wird, sondern der Inhalt wird unverändert ausgegeben.{# Kommentare #}alles zwischen{#und#}wird als auskommentiert betrachtet (d.h. nicht ausgegeben oder ausgeführt)
Von Vorlagen aus können Sie auf alles in der context-Tabelle und alles in der template-Tabelle zugreifen. In Vorlagen können Sie auch auf context und template zugreifen, indem Sie die Schlüssel mit einem Präfix versehen.
<h1>{{message}}</h1> == <h1>{{context.message}}</h1>
Kurze Escape-Syntax
Wenn Sie möchten, dass ein bestimmtes Vorlagentag nicht verarbeitet wird, können Sie das Start-Tag mit einem Backslash \ escapen:
<h1>\{{message}}</h1>
Dies wird ausgegeben (anstatt die Nachricht auszuwerten):
<h1>{{message}}</h1>
Wenn Sie ein Backslash-Zeichen direkt vor dem Vorlagentag hinzufügen möchten, müssen Sie das ebenfalls escapen:
<h1>\\{{message}}</h1>
Dies wird ausgegeben:
<h1>\[message-variables-content-here]</h1>
Ein Wort zu komplexen Schlüsseln in der Kontexttabelle
Angenommen, Sie haben diese Art von Kontexttabelle:
local ctx = {["foo:bar"] = "foobar"}
Und Sie möchten den Wert foobar von ctx["foo:bar"] in Ihrer Vorlage rendern. Sie müssen dies explizit angeben, indem Sie auf den context in Ihrer Vorlage verweisen:
{# {*["foo:bar"]*} wird nicht funktionieren, Sie müssen verwenden: #}
{*context["foo:bar"]*}
Oder insgesamt:
template.render([[
{*context["foo:bar"]*}
]], {["foo:bar"] = "foobar"})
Ein Wort zur HTML-Escaping
Nur Strings werden escaped, Funktionen werden ohne Argumente (rekursiv) aufgerufen und die Ergebnisse werden unverändert zurückgegeben, andere Typen werden tostring-ifiziert. nils und ngx.nulls werden in leere Strings "" umgewandelt.
Escaped HTML-Zeichen:
&wird zu&<wird zu<>wird zu>"wird zu"'wird zu'/wird zu/
Beispiel
Lua
local template = require "resty.template"
template.render("view.html", {
title = "Testing lua-resty-template",
message = "Hallo, Welt!",
names = { "James", "Jack", "Anne" },
jquery = '<script src="js/jquery.min.js"></script>'
})
view.html
{(header.html)}
<h1>{{message}}</h1>
<ul>
{% for _, name in ipairs(names) do %}
<li>{{name}}</li>
{% end %}
</ul>
{(footer.html)}
header.html
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
{*jquery*}
</head>
<body>
footer.html
</body>
</html>
Reservierte Kontextschlüssel und Anmerkungen
Es wird empfohlen, dass Sie diese Schlüssel nicht in Ihren Kontexttabellen verwenden:
___, hält die kompilierte Vorlage, wenn gesetzt, müssen Sie{{context.___}}verwendencontext, hält den aktuellen Kontext, wenn gesetzt, müssen Sie{{context.context}}verwendenecho, hält die Echo-Helferfunktion, wenn gesetzt, müssen Sie{{context.echo}}verwendeninclude, hält die Include-Helferfunktion, wenn gesetzt, müssen Sie{{context.include}}verwendenlayout, hält das Layout, mit dem die Ansicht dekoriert wird, wenn gesetzt, müssen Sie{{context.layout}}verwendenblocks, hält die Blöcke, wenn gesetzt, müssen Sie{{context.blocks}}verwenden (siehe: Verwendung von Blöcken)template, hält die Template-Tabelle, wenn gesetzt, müssen Sie{{context.template}}verwenden
Darüber hinaus sollten Sie mit template.new nicht überschreiben:
render, die Funktion, die eine Ansicht rendert, offensichtlich ;-)
Sie sollten auch nicht {(view.html)} rekursiv verwenden:
Lua
template.render "view.html"
view.html
{(view.html)}
Sie können Vorlagen auch aus "Unterverzeichnissen" mit {(syntax)} laden:
view.html
{(users/list.html)}
Bitte beachten Sie, dass Sie die Vorlage entweder als Dateipfad oder als Zeichenfolge bereitstellen können. Wenn die Datei existiert, wird sie verwendet, andernfalls wird die Zeichenfolge verwendet. Siehe auch template.load.
Nginx / OpenResty-Konfiguration
Wenn lua-resty-template im Kontext von Nginx / OpenResty verwendet wird, gibt es einige Konfigurationsanweisungen, die Sie beachten sollten:
template_root(set $template_root /var/www/site/templates)template_location(set $template_location /templates)
Wenn keine dieser Optionen in der Nginx-Konfiguration gesetzt ist, wird der Wert von ngx.var.document_root (auch bekannt als root-Direktive) verwendet. Wenn template_location gesetzt ist, wird es zuerst verwendet, und wenn der Standort alles andere als 200 als Statuscode zurückgibt, fallen wir entweder auf template_root (wenn definiert) oder document_root zurück.
Mit lua-resty-template 2.0 ist es möglich, $template_root und $template_location mit Lua-Code zu überschreiben:
local template = require "resty.template".new({
root = "/templates",
location = "/templates"
})
Verwendung von document_root
Dies versucht, den Dateiinhalt mit Lua-Code aus dem html-Verzeichnis (relativ zum Nginx-Präfix) zu laden.
http {
server {
location / {
root html;
content_by_lua '
local template = require "resty.template"
template.render("view.html", { message = "Hallo, Welt!" })
';
}
}
}
Verwendung von template_root
Dies versucht, den Dateiinhalt mit Lua-Code aus dem Verzeichnis /usr/local/openresty/nginx/html/templates zu laden.
http {
server {
set $template_root /usr/local/openresty/nginx/html/templates;
location / {
root html;
content_by_lua '
local template = require "resty.template"
template.render("view.html", { message = "Hallo, Welt!" })
';
}
}
}
Verwendung von template_location
Dies versucht, Inhalte mit ngx.location.capture aus dem Standort /templates zu laden (in diesem Fall wird dies mit dem ngx_static-Modul bereitgestellt).
http {
server {
set $template_location /templates;
location / {
root html;
content_by_lua '
local template = require "resty.template"
template.render("view.html", { message = "Hallo, Welt!" })
';
}
location /templates {
internal;
alias html/templates/;
}
}
}
Siehe auch template.load.
Lua-API
template.root
Sie können das Template-Root-Verzeichnis festlegen, indem Sie diese Variable setzen, nach der nach Vorlagendateien gesucht wird:
local template = require "resty.template".new({
root = "/templates"
})
template.render_file("test.html")
Diese Eigenschaft überschreibt die in der Nginx-Konfiguration gesetzte (set $template_root /my-templates;)
template.location
Dies ist das, was Sie mit OpenResty verwenden können, da es ngx.location.capture verwendet, um Vorlagendateien nicht blockierend abzurufen.
local template = require "resty.template".new({
location = "/templates"
})
template.render_file("test.html")
Diese Eigenschaft überschreibt die in der Nginx-Konfiguration gesetzte (set $template_location /my-templates;)
table template.new(view, layout)
Erstellt eine neue Template-Instanz, die als (Standard-) Kontext verwendet wird, wenn sie gerendert wird. Eine Tabelle, die erstellt wird, hat nur eine Methode render, aber die Tabelle hat auch eine Metatabelle mit __tostring, die definiert ist. Siehe das folgende Beispiel. Sowohl die Argumente view als auch layout können entweder Strings oder Dateipfade sein, aber das Layout kann auch eine zuvor mit template.new erstellte Tabelle sein.
Mit 2.0 kann new auch ohne Argumente verwendet werden, was eine neue Template-Instanz erstellt:
local template = require "resty.template".new()
Sie können auch eine Tabelle übergeben, die dann modifiziert wird, um ein Template zu sein:
local config = {
root = "/templates"
}
local template = require "resty.template".new(config)
Dies ist praktisch, da das mit new erstellte template den Cache nicht mit dem globalen Template teilt, das von require "resty.template" zurückgegeben wird (dies wurde mit dem Problem #25 gemeldet).
Sie können auch einen booleschen Wert true oder false als view-Parameter übergeben, was bedeutet, dass entweder die safe- oder die un-safe-Version des Templates zurückgegeben wird:
local unsafe = require "resty.template"
local safe = unsafe.new(true)
Es gibt auch eine Standardimplementierung safe:
local safe = require "resty.template.safe"
-- Sie können auch eine Instanz von safe erstellen:
local safe_instance = safe.new()
Die safe-Version verwendet das Lua-Fehlerbehandlungs-Muster return nil, err und unsafe wirft einfach die Fehler, die Sie mit pcall, xpcall oder coroutine.wrap abfangen können.
Hier sind Beispiele für die Verwendung von new mit Argumenten:
local view = template.new"template.html" -- oder
local view = template.new("view.html", "layout.html") -- oder
local view = template.new[[<h1>{{message}}</h1>]] -- oder
local view = template.new([[<h1>{{message}}</h1>]], [[
<html>
<body>
{*view*}
</body>
</html>
]])
Beispiel
local template = require "resty.template"
local view = template.new"view.html"
view.message = "Hallo, Welt!"
view:render()
-- Sie können auch den Kontext beim Rendern ersetzen
view:render{ title = "Testing lua-resty-template" }
-- Wenn Sie den Ansichts-Kontext im Ersatzkontext einfügen möchten
view:render(setmetatable({ title = "Testing lua-resty-template" }, { __index = view }))
-- Um die gerenderte Vorlage als String zu erhalten, können Sie tostring verwenden
local result = tostring(view)
boolean template.caching(boolean oder nil)
Diese Funktion aktiviert oder deaktiviert das Caching von Vorlagen oder gibt, wenn keine Parameter übergeben werden, den aktuellen Zustand des Template-Cachings zurück. Standardmäßig ist das Template-Caching aktiviert, aber Sie möchten es möglicherweise in Entwicklungs- oder speichersensitiven Situationen deaktivieren.
local template = require "resty.template"
-- Aktuellen Zustand des Template-Cachings abrufen
local enabled = template.caching()
-- Template-Caching deaktivieren
template.caching(false)
-- Template-Caching aktivieren
template.caching(true)
Bitte beachten Sie, dass, wenn die Vorlage bereits im Cache war, als eine Vorlage kompiliert wurde, die zwischengespeicherte Version zurückgegeben wird. Sie möchten möglicherweise den Cache mit template.cache = {} leeren, um sicherzustellen, dass Ihre Vorlage wirklich neu kompiliert wird.
function, boolean template.compile(view, cache_key, plain)
Parst, kompiliert und cached (wenn Caching aktiviert ist) eine Vorlage und gibt die kompilierte Vorlage als Funktion zurück, die den Kontext als Parameter annimmt und die gerenderte Vorlage als String zurückgibt. Optional können Sie cache_key übergeben, der als Cache-Schlüssel verwendet wird. Wenn kein Cache-Schlüssel angegeben ist, wird view als Cache-Schlüssel verwendet. Wenn der Cache-Schlüssel no-cache ist, wird der Template-Cache nicht überprüft und die resultierende Funktion wird nicht zwischengespeichert. Sie können auch optional plain mit einem Wert von true übergeben, wenn die view eine einfache Textzeichenfolge ist (dies überspringt template.load und die binäre Chunk-Erkennung in der template.parse-Phase). Wenn plain false ist, wird die Vorlage als Datei betrachtet, und alle Probleme mit dem Lesen von Dateien werden als Fehler betrachtet. Wenn plain auf nil (der Standardwert) gesetzt ist, betrachtet die Vorlage keine Fehler beim Lesen von Dateien als fatal und gibt die view (normalerweise den Pfad der Vorlage) zurück.
local func = template.compile("template.html") -- oder
local func = template.compile([[<h1>{{message}}</h1>]])
Beispiel
local template = require "resty.template"
local func = template.compile("view.html")
local world = func{ message = "Hallo, Welt!" }
local universe = func{ message = "Hallo, Universum!" }
print(world, universe)
Beachten Sie auch den zweiten Rückgabewert, der ein boolescher Wert ist. Sie können ihn verwerfen oder verwenden, um festzustellen, ob die zurückgegebene Funktion zwischengespeichert wurde.
function, boolean template.compile_string(view, cache_key)
Dies ruft einfach template.compile(view, cache_key, true) auf.
function, boolean template.compile_file(view, cache_key)
Dies ruft einfach template.compile(view, cache_key, false) auf.
template.visit(func)
Erlaubt es Ihnen, Besucherfunktionen für den Vorlagenparser zu registrieren. Besucher werden in der Reihenfolge aufgerufen, in der sie registriert sind. Und einmal registriert, können sie nicht mehr aus dem Parser entfernt werden. Vielleicht ist es einfacher zu zeigen, wie es funktioniert:
local template = require "resty.template.safe".new()
local i = 0
template.visit(function(content, type, name)
local trimmed = content:gsub("^%s+", ""):gsub("%s+$", "")
if trimmed == "" then return content end
i = i + 1
print(" visit: ", i)
if type then print(" type: ", type) end
if name then print(" name: ", name) end
print("content: ", trimmed)
print()
return content
end)
local func = template.compile([[
Wie geht es dir, {{user.name}}?
Hier ist ein neues Kochrezept für dich!
{% for i, ingredient in ipairs(ingredients) do %}
{*i*}. {{ingredient}}
{% end %}
{-ad-}`lua-resty-template` die Templating-Engine für OpenResty!{-ad-}
]])
local content = func{
user = {
name = "bungle"
},
ingredients = {
"Kartoffeln",
"Würstchen"
}
}
print(content)
Dies wird Folgendes ausgeben:
visit: 1
content: Wie geht es dir,
visit: 2
type: {
content: user.name
visit: 3
content: ?
Hier ist ein neues Kochrezept für dich!
visit: 4
type: %
content: for i, ingredient in ipairs(ingredients) do
visit: 5
type: *
content: i
visit: 6
content: .
visit: 7
type: {
content: ingredient
visit: 8
type: %
content: end
visit: 9
type: -
name: ad
content: `lua-resty-template` die Templating-Engine für OpenResty!
visit: 10
content: `lua-resty-template` die Templating-Engine für OpenResty!
Wie geht es dir, bungle?
Hier ist ein neues Kochrezept für dich!
1. Kartoffeln
2. Würstchen
Die Besucherfunktionen sollten diese Signatur haben:
string function(content, type, name)
Wenn die Funktion den content nicht ändert, sollte sie den content zurückgeben, wie der Besucher oben macht.
Hier ist ein etwas fortgeschritteneres Besucherbeispiel, das Laufzeitfehler bei Ausdrücken behandelt:
local template = require "resty.template".new()
template.render "Berechnung: {{i*10}}"
Dies wird zur Laufzeit einen Fehler mit folgendem Inhalt erzeugen:
ERROR: [string "context=... or {}..."]:7: Versuch, arithmetische Operationen auf global 'i' (ein nil-Wert) durchzuführen
stack traceback:
resty/template.lua:652: in function 'render'
a.lua:52: in function 'file_gen'
init_worker_by_lua:45: in function <init_worker_by_lua:43>
[C]: in function 'xpcall'
init_worker_by_lua:52: in function <init_worker_by_lua:50>
Jetzt fügen wir einen Besucher hinzu, der diesen Fehler behandelt:
local template = require "resty.template".new()
template.visit(function(content, type)
if type == "*" or type == "{" then
return "select(3, pcall(function() return nil, " .. content .. " end)) or ''"
end
return content
end)
template.render "Berechnung: {{i*10}}\n"
template.render("Berechnung: {{i*10}}\n", { i = 1 })
Dies wird Folgendes ausgeben:
Berechnung:
Berechnung: 10
string template.process(view, context, cache_key, plain)
Parst, kompiliert, cached (wenn Caching aktiviert ist) und gibt die Ausgabe als String zurück. Sie können optional auch cache_key übergeben, der als Cache-Schlüssel verwendet wird. Wenn plain auf true ausgewertet wird, wird die view als einfache String-Vorlage betrachtet (template.load und die binäre Chunk-Erkennung werden in template.parse übersprungen). Wenn plain false ist, wird die Vorlage als Datei betrachtet, und alle Probleme mit dem Lesen von Dateien werden als Fehler betrachtet. Wenn plain auf nil (der Standardwert) gesetzt ist, betrachtet die Vorlage keine Fehler beim Lesen von Dateien als fatal und gibt die view zurück.
local output = template.process("template.html", { message = "Hallo, Welt!" }) -- oder
local output = template.process([[<h1>{{message}}</h1>]], { message = "Hallo, Welt!" })
string template.process_string(view, context, cache_key)
Dies ruft einfach template.process(view, context, cache_key, true) auf.
string template.process_file(view, context, cache_key)
Dies ruft einfach template.process(view, context, cache_key, false) auf.
template.render(view, context, cache_key, plain)
Parst, kompiliert, cached (wenn Caching aktiviert ist) und gibt die Vorlage entweder mit ngx.print, wenn verfügbar, oder print aus. Sie können optional auch cache_key übergeben, der als Cache-Schlüssel verwendet wird. Wenn plain auf true ausgewertet wird, wird die view als einfache String-Vorlage betrachtet (template.load und die binäre Chunk-Erkennung werden in template.parse übersprungen). Wenn plain false ist, wird die Vorlage als Datei betrachtet, und alle Probleme mit dem Lesen von Dateien werden als Fehler betrachtet. Wenn plain auf nil (der Standardwert) gesetzt ist, betrachtet die Vorlage keine Fehler beim Lesen von Dateien als fatal und gibt die view zurück.
template.render("template.html", { message = "Hallo, Welt!" }) -- oder
template.render([[<h1>{{message}}</h1>]], { message = "Hallo, Welt!" })
string template.render_string(view, context, cache_key)
Dies ruft einfach template.render(view, context, cache_key, true) auf.
string template.render_file(view, context, cache_key)
Dies ruft einfach template.render(view, context, cache_key, false) auf.
string template.parse(view, plain)
Parst die Vorlagendatei oder -zeichenfolge und generiert eine geparste Vorlagenzeichenfolge. Dies kann nützlich sein, wenn Sie Vorlagen debuggen. Sie sollten beachten, dass, wenn Sie versuchen, einen binären Chunk (z.B. einen, der mit template.compile zurückgegeben wird) zu parsen, template.parse diesen binären Chunk unverändert zurückgibt. Wenn plain auf true ausgewertet wird, wird die view als einfache String-Vorlage betrachtet (template.load und die binäre Chunk-Erkennung werden in template.parse übersprungen). Wenn plain false ist, wird die Vorlage als Datei betrachtet, und alle Probleme mit dem Lesen von Dateien werden als Fehler betrachtet. Wenn plain auf nil (der Standardwert) gesetzt ist, betrachtet die Vorlage keine Fehler beim Lesen von Dateien als fatal und gibt die view zurück.
local t1 = template.parse("template.html")
local t2 = template.parse([[<h1>{{message}}</h1>]])
string template.parse_string(view, plain)
Dies ruft einfach template.parse(view, plain, true) auf.
string template.parse_file(view, plain)
Dies ruft einfach template.parse(view, plain, false) auf.
string template.precompile(view, path, strip, plain)
Vorkompiliert die Vorlage als binären Chunk. Dieser binäre Chunk kann als Datei ausgegeben werden (und Sie können ihn direkt mit Lua's load und loadfile verwenden). Zur Bequemlichkeit können Sie optional das path-Argument angeben, um den binären Chunk in eine Datei auszugeben. Sie können auch den strip-Parameter mit dem Wert false angeben, um sicherzustellen, dass vorkompilierte Vorlagen auch Debug-Informationen enthalten (Standardwert ist true). Der letzte Parameter plain bedeutet, dass die Kompilierung die view als string (plain = true) oder als file path (plain = false) behandeln soll oder zuerst als Datei versuchen soll und dann auf string zurückfällt (plain = nil). Im Falle von plain=false (eine Datei) und es gibt einen Fehler mit file io, wird die Funktion auch mit einem Assertion-Fehler fehlschlagen.
local view = [[
<h1>{{title}}</h1>
<ul>
{% for _, v in ipairs(context) do %}
<li>{{v}}</li>
{% end %}
</ul>]]
local compiled = template.precompile(view)
local file = io.open("precompiled-bin.html", "wb")
file:write(compiled)
file:close()
-- Alternativ könnten Sie einfach schreiben (was dasselbe tut wie oben)
template.precompile(view, "precompiled-bin.html")
template.render("precompiled-bin.html", {
title = "Namen",
"Emma", "James", "Nicholas", "Mary"
})
string template.precompile_string(view, path, strip)
Dies ruft einfach template.precompile(view, path, strip, true) auf.
string template.precompile_file(view, path, strip)
Dies ruft einfach template.precompile(view, path, strip, false) auf.
string template.load(view, plain)
Dieses Feld wird verwendet, um Vorlagen zu laden. template.parse ruft diese Funktion auf, bevor es mit dem Parsen der Vorlage beginnt (vorausgesetzt, dass das optionale plain-Argument in template.parse auf false oder nil (der Standardwert) ausgewertet wird). Standardmäßig gibt es zwei Loader in lua-resty-template: einen für Lua und den anderen für Nginx / OpenResty. Benutzer können dieses Feld mit ihrer eigenen Funktion überschreiben. Zum Beispiel möchten Sie möglicherweise eine Vorlagenladefunktion schreiben, die Vorlagen aus einer Datenbank lädt.
Der Standard-template.load für Lua (angehängt als template.load, wenn direkt mit Lua verwendet):
function(view, plain)
if plain == true then return view end
local path, root = view, template.root
if root and root ~= EMPTY then
if byte(root, -1) == SOL then root = sub(root, 1, -2) end
if byte(view, 1) == SOL then path = sub(view, 2) end
path = root .. "/" .. path
end
return plain == false and assert(read_file(path)) or read_file(path) or view
end
Der Standard-template.load für Nginx / OpenResty (angehängt als template.load, wenn im Kontext von Nginx / OpenResty verwendet):
function(view, plain)
if plain == true then return view end
local vars = VAR_PHASES[phase()]
local path = view
local root = template.location
if (not root or root == EMPTY) and vars then
root = var.template_location
end
if root and root ~= EMPTY then
if byte(root, -1) == SOL then root = sub(root, 1, -2) end
if byte(path, 1) == SOL then path = sub(path, 2) end
path = root .. "/" .. path
local res = capture(path)
if res.status == 200 then return res.body end
end
path = view
root = template.root
if (not root or root == EMPTY) and vars then
root = var.template_root
if not root or root == EMPTY then root = var.document_root or prefix end
end
if root and root ~= EMPTY then
if byte(root, -1) == SOL then root = sub(root, 1, -2) end
if byte(path, 1) == SOL then path = sub(path, 2) end
path = root .. "/" .. path
end
return plain == false and assert(read_file(path)) or read_file(path) or view
end
Wie Sie sehen können, versucht lua-resty-template standardmäßig immer, eine Vorlage aus einer Datei (oder mit ngx.location.capture) zu laden, selbst wenn Sie die Vorlage als Zeichenfolge bereitgestellt haben. lua-resty-template. Aber wenn Sie wissen, dass Ihre Vorlagen immer Strings sind und keine Dateipfade, können Sie das plain-Argument in template.compile, template.render und template.parse verwenden ODER template.load mit dem einfachsten möglichen Vorlagenloader ersetzen (aber beachten Sie, dass, wenn Ihre Vorlagen {(file.html)}-Einschlüsse verwenden, diese auch als Strings betrachtet werden, in diesem Fall wird file.html die Vorlagenzeichenfolge sein, die geparst wird) - Sie könnten auch einen Loader einrichten, der Vorlagen in einem Datenbanksystem wie Redis findet:
local template = require "resty.template"
template.load = function(view, plain) return view end
Wenn der plain-Parameter false ist ( nil wird nicht als false behandelt), werden alle Probleme mit dem Datei-IO als Assertionsfehler betrachtet.
string template.load_string(view)
Dies ruft einfach template.load(view, true) auf.
string template.load_file(view)
Dies ruft einfach template.load(view, false) auf.
template.print
Dieses Feld enthält eine Funktion, die bei template.render() oder template.new("example.html"):render() verwendet wird, um die Ergebnisse auszugeben. Standardmäßig enthält dies entweder ngx.print (wenn verfügbar) oder print. Sie möchten dieses Feld möglicherweise (und dürfen es) überschreiben, wenn Sie Ihre eigene Ausgabefunktion stattdessen verwenden möchten. Dies ist auch nützlich, wenn Sie ein anderes Framework verwenden, z.B. Turbo.lua (http://turbolua.org/).
local template = require "resty.template"
template.print = function(s)
print(s)
print("<!-- Ausgabe durch meine Funktion -->")
end
Template-Vorkompilierung
lua-resty-template unterstützt die Vorkompilierung von Vorlagen. Dies kann nützlich sein, wenn Sie das Parsen von Vorlagen (und die Lua-Interpretation) in der Produktion überspringen möchten oder wenn Sie nicht möchten, dass Ihre Vorlagen als einfache Textdateien auf Produktionsservern verteilt werden. Durch die Vorkompilierung können Sie auch sicherstellen, dass Ihre Vorlagen nichts enthalten, das nicht kompiliert werden kann (sie sind syntaktisch gültiges Lua). Obwohl Vorlagen gecached werden (auch ohne Vorkompilierung), gibt es einige Leistungs- (und Speicher-) Gewinne. Sie könnten die Vorkompilierung von Vorlagen in Ihre Build- (oder Bereitstellungs-) Skripte integrieren (vielleicht als Gulp-, Grunt- oder Ant-Aufgaben).
Vorkompilieren der Vorlage und Ausgabe als binäre Datei
local template = require "resty.template"
local compiled = template.precompile("example.html", "example-bin.html")
Laden der vorkompilierten Vorlagendatei und Ausführen mit Kontextparametern
local template = require "resty.template"
template.render("example-bin.html", { "Jack", "Mary" })
Template-Helfer
Eingebaute Helfer
echo(...)
Gibt die Ausgabe aus. Dies ist nützlich mit {% .. %}:
require "resty.template".render[[
begin
{%
for i=1, 10 do
echo("\tline: ", i, "\n")
end
%}
end
]]
Dies wird ausgeben:
begin
line: 1
line: 2
line: 3
line: 4
line: 5
line: 6
line: 7
line: 8
line: 9
line: 10
end
Dies kann auch so geschrieben werden, aber echo könnte in einigen Fällen nützlich sein:
require "resty.template".render[[
begin
{% for i=1, 10 do %}
line: {* i *}
{% end %}
end
]]
include(view, context)
Dies wird hauptsächlich intern mit {(view.hmtl)}, {["view.hmtl"]} und mit Blöcken {-block-name-}..{-block-name-} verwendet. Wenn context nicht angegeben ist, wird der Kontext verwendet, der zum Kompilieren der übergeordneten Ansicht verwendet wurde. Diese Funktion kompiliert die view und ruft die resultierende Funktion mit context (oder dem Kontext der übergeordneten Ansicht, wenn nicht angegeben) auf.
Andere Möglichkeiten zur Erweiterung
Während lua-resty-template nicht viel Infrastruktur oder Möglichkeiten zur Erweiterung hat, haben Sie dennoch einige Möglichkeiten, die Sie ausprobieren können.
- Methoden zu den globalen
string- undtable-Typen hinzufügen (nicht empfohlen) - Ihre Werte vor dem Hinzufügen in den Kontext mit etwas umschließen (z.B. Proxy-Tabelle)
- Globale Funktionen erstellen
- Lokale Funktionen entweder zur
template-Tabelle oder zurcontext-Tabelle hinzufügen - Metamethoden in Ihren Tabellen verwenden
Während die Modifizierung globaler Typen bequem erscheint, kann sie unangenehme Nebenwirkungen haben. Deshalb empfehle ich Ihnen, zuerst diese Bibliotheken und Artikel zu betrachten:
- Method Chaining Wrapper (http://lua-users.org/wiki/MethodChainingWrapper)
- Moses (https://github.com/Yonaba/Moses)
- underscore-lua (https://github.com/jtarchie/underscore-lua)
Sie könnten beispielsweise Moses' oder Underscore's _ zur Template-Tabelle oder Kontext-Tabelle hinzufügen.
Beispiel
local _ = require "moses"
local template = require "resty.template"
template._ = _
Dann können Sie _ innerhalb Ihrer Vorlagen verwenden. Ich habe einen Beispiel-Template-Helfer erstellt, der hier zu finden ist: https://github.com/bungle/lua-resty-template/blob/master/lib/resty/template/html.lua
Lua
local template = require "resty.template"
local html = require "resty.template.html"
template.render([[
<ul>
{% for _, person in ipairs(context) do %}
{*html.li(person.name)*}
{% end %}
</ul>
<table>
{% for _, person in ipairs(context) do %}
<tr data-sort="{{(person.name or ""):lower()}}">
{*html.td{ id = person.id }(person.name)*}
</tr>
{% end %}
</table>]], {
{ id = 1, name = "Emma"},
{ id = 2, name = "James" },
{ id = 3, name = "Nicholas" },
{ id = 4 }
})
Ausgabe
<ul>
<li>Emma</li>
<li>James</li>
<li>Nicholas</li>
<li />
</ul>
<table>
<tr data-sort="emma">
<td id="1">Emma</td>
</tr>
<tr data-sort="james">
<td id="2">James</td>
</tr>
<tr data-sort="nicholas">
<td id="3">Nicholas</td>
</tr>
<tr data-sort="">
<td id="4" />
</tr>
</table>
Verwendungsbeispiele
Template-Einbindung
Sie können Vorlagen innerhalb von Vorlagen mit der Syntax {(template)} und {(template, context)} einfügen. Die erste verwendet den aktuellen Kontext als Kontext für die eingeschlossene Vorlage, und die zweite ersetzt ihn durch einen neuen Kontext. Hier ist ein Beispiel für die Verwendung von Einfügungen und das Übergeben eines anderen Kontexts an die eingeschlossene Datei:
Lua
local template = require "resty.template"
template.render("include.html", { users = {
{ name = "Jane", age = 29 },
{ name = "John", age = 25 }
}})
include.html
<html>
<body>
<ul>
{% for _, user in ipairs(users) do %}
{(user.html, user)}
{% end %}
</ul>
</body>
</html>
user.html
<li>Benutzer {{name}} ist {{age}} Jahre alt</li>
Ausgabe
<html>
<body>
<ul>
<li>Benutzer Jane ist 29 Jahre alt</li>
<li>Benutzer John ist 25 Jahre alt</li>
</ul>
</body>
</html>
Views mit Layouts
Layouts (oder Master-Seiten) können verwendet werden, um eine Ansicht innerhalb einer anderen Ansicht (auch bekannt als Layout) einzuwickeln.
Lua
local template = require "resty.template"
local layout = template.new "layout.html"
layout.title = "Testing lua-resty-template"
layout.view = template.compile "view.html" { message = "Hallo, Welt!" }
layout:render()
-- Oder so
template.render("layout.html", {
title = "Testing lua-resty-template",
view = template.compile "view.html" { message = "Hallo, Welt!" }
})
-- Oder vielleicht gefällt Ihnen dieser Stil besser
-- (aber denken Sie daran, dass der Kontext.view beim Rendern von layout.html überschrieben wird)
local view = template.new("view.html", "layout.html")
view.title = "Testing lua-resty-template"
view.message = "Hallo, Welt!"
view:render()
-- Nun, vielleicht so?
local layout = template.new "layout.html"
layout.title = "Testing lua-resty-template"
local view = template.new("view.html", layout)
view.message = "Hallo, Welt!"
view:render()
view.html
<h1>{{message}}</h1>
layout.html
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
{*view*}
</body>
</html>
Alternativ können Sie das Layout auch in einer Ansicht definieren:
Lua
local view = template.new("view.html", "layout.html")
view.title = "Testing lua-resty-template"
view.message = "Hallo, Welt!"
view:render()
view.html
{% layout="section.html" %}
<h1>{{message}}</h1>
section.html
<div id="section">
{*view*}
</div>
layout.html
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
{*view*}
</body>
</html>
Ausgabe
<!DOCTYPE html>
<html>
<head>
<title>Testing lua-resty-template</title>
</head>
<body>
<div id="section">
<h1>Hallo, Welt!</h1>
</div>
</body>
</html>
Verwendung von Blöcken
Blöcke können verwendet werden, um verschiedene Teile der Ansichten an bestimmten Stellen in Layouts zu verschieben. Layouts haben Platzhalter für Blöcke.
Lua
local view = template.new("view.html", "layout.html")
view.title = "Testing lua-resty-template blocks"
view.message = "Hallo, Welt!"
view.keywords = { "test", "lua", "template", "blocks" }
view:render()
view.html
<h1>{{message}}</h1>
{-aside-}
<ul>
{% for _, keyword in ipairs(keywords) do %}
<li>{{keyword}}</li>
{% end %}
</ul>
{-aside-}
layout.html
<!DOCTYPE html>
<html>
<head>
<title>{*title*}</title>
</head>
<body>
<article>
{*view*}
</article>
{% if blocks.aside then %}
<aside>
{*blocks.aside*}
</aside>
{% end %}
</body>
</html>
Ausgabe
<!DOCTYPE html>
<html>
<head>
<title>Testing lua-resty-template blocks</title>
</head>
<body>
<article>
<h1>Hallo, Welt!</h1>
</article>
<aside>
<ul>
<li>test</li>
<li>lua</li>
<li>template</li>
<li>blocks</li>
</ul>
</aside>
</body>
</html>
Großvater-Vater-Sohn-Vererbung
Angenommen, Sie haben base.html, layout1.html, layout2.html und page.html. Sie möchten eine Vererbung wie folgt: base.html ➡ layout1.html ➡ page.html oder base.html ➡ layout2.html ➡ page.html (tatsächlich ist diese Verschachtelung nicht auf drei Ebenen beschränkt).
Lua
local res = require"resty.template".compile("page.html"){}
base.html
<html lang='zh'>
<head>
<link href="css/bootstrap.min.css" rel="stylesheet">
{* blocks.page_css *}
</head>
<body>
{* blocks.main *}
<script src="js/jquery.js"></script>
<script src="js/bootstrap.min.js"></script>
{* blocks.page_js *}
</body>
</html>
layout1.html
{% layout = "base.html" %}
{-main-}
<div class="sidebar-1">
{* blocks.sidebar *}
</div>
<div class="content-1">
{* blocks.content *}
</div>
{-main-}
layout2.html
{% layout = "base.html" %}
{-main-}
<div class="sidebar-2">
{* blocks.sidebar *}
</div>
<div class="content-2">
{* blocks.content *}
</div>
<div>Ich bin anders als layout1 </div>
{-main-}
page.html
{% layout = "layout1.html" %}
{-sidebar-}
dies ist die Seitenleiste
{-sidebar-}
{-content-}
dies ist der Inhalt
{-content-}
{-page_css-}
<link href="css/page.css" rel="stylesheet">
{-page_css-}
{-page_js-}
<script src="js/page.js"></script>
{-page_js-}
Oder:
page.html
{% layout = "layout2.html" %}
{-sidebar-}
dies ist die Seitenleiste
{-sidebar-}
{-content-}
dies ist der Inhalt
{-content-}
{-page_css-}
<link href="css/page.css" rel="stylesheet">
{-page_css-}
{-page_js-}
<script src="js/page.js"></script>
{-page_js-}
Makros
@DDarko erwähnte in einem Issue #5, dass er einen Anwendungsfall hat, in dem er Makros oder parametrisierten Ansichten benötigt. Das ist eine schöne Funktion, die Sie mit lua-resty-template verwenden können.
Um Makros zu verwenden, definieren wir zunächst etwas Lua-Code:
template.render("macro.html", {
item = "original",
items = { a = "original-a", b = "original-b" }
})
Und die macro-example.html:
{% local string_macro = [[
<div>{{item}}</div>
]] %}
{* template.compile(string_macro)(context) *}
{* template.compile(string_macro){ item = "string-macro-context" } *}
Dies wird ausgeben:
<div>original</div>
<div>string-macro-context</div>
Jetzt fügen wir ein Funktionsmakro in macro-example.html hinzu (Sie können local weglassen, wenn Sie möchten):
{% local function_macro = function(var, el)
el = el or "div"
return "<" .. el .. ">{{" .. var .. "}}</" .. el .. ">\n"
end %}
{* template.compile(function_macro("item"))(context) *}
{* template.compile(function_macro("a", "span"))(items) *}
Dies wird ausgeben:
<div>original</div>
<span>original-a</span>
Aber das ist noch flexibler, probieren wir ein weiteres Funktionsmakro:
{% local function function_macro2(var)
return template.compile("<div>{{" .. var .. "}}</div>\n")
end %}
{* function_macro2 "item" (context) *}
{* function_macro2 "b" (items) *}
Dies wird ausgeben:
<div>original</div>
<div>original-b</div>
Und hier ist noch eines:
{% function function_macro3(var, ctx)
return template.compile("<div>{{" .. var .. "}}</div>\n")(ctx or context)
end %}
{* function_macro3("item") *}
{* function_macro3("a", items) *}
{* function_macro3("b", items) *}
{* function_macro3("b", { b = "b-from-new-context" }) *}
Dies wird ausgeben:
<div>original</div>
<div>original-a</div>
<div>original-b</div>
<div>b-from-new-context</div>
Makros sind wirklich flexibel. Sie können Formular-Renderer und andere Hilfs-Makros haben, um eine wiederverwendbare und parametrische Vorlagen-Ausgabe zu haben. Eine Sache, die Sie wissen sollten, ist, dass Sie in Codeblöcken (zwischen {% und %}) kein %} haben können, aber Sie können dies mit String-Konkatenation "%" .. "}" umgehen.
Methoden in Vorlagen aufrufen
Sie können auch String-Methoden (oder andere Tabellenfunktionen) in Vorlagen aufrufen.
Lua
local template = require "resty.template"
template.render([[
<h1>{{header:upper()}}</h1>
]], { header = "hallo, welt!" })
Ausgabe
<h1>HALLO, WELT!</h1>
Einbetten von Angular oder anderen Tags / Templating innerhalb der Vorlagen
Manchmal müssen Sie andere Vorlagen (sagen wir clientseitige JavaScript-Vorlagen wie Angular) mit serverseitigen lua-resty-Vorlagen mischen und kombinieren. Angenommen, Sie haben diese Art von Angular-Vorlage:
<html ng-app>
<body ng-controller="MyController">
<input ng-model="foo" value="bar">
<button ng-click="changeFoo()">{{buttonText}}</button>
<script src="angular.js">
</body>
</html>
Jetzt sehen Sie, dass {{buttonText}} wirklich für Angular-Templating gedacht ist und nicht für lua-resty-template. Sie können dies beheben, indem Sie entweder den gesamten Code mit {-verbatim-} oder {-raw-} umschließen oder nur die Teile, die Sie möchten:
{-raw-}
<html ng-app>
<body ng-controller="MyController">
<input ng-model="foo" value="bar">
<button ng-click="changeFoo()">{{buttonText}}</button>
<script src="angular.js">
</body>
</html>
{-raw-}
oder (sehen Sie, dass die {(head.html)} von lua-resty-template verarbeitet wird):
<html ng-app>
{(head.html)}
<body ng-controller="MyController">
<input ng-model="foo" value="bar">
<button ng-click="changeFoo()">{-raw-}{{buttonText}}{-raw-}</button>
<script src="angular.js">
</body>
</html>
Sie können auch die kurze Escape-Syntax verwenden:
...
<button ng-click="changeFoo()">\{{buttonText}}</button>
...
Einbetten von Markdown innerhalb der Vorlagen
Wenn Sie Markdown (und SmartyPants) Syntax innerhalb Ihrer Vorlagen einbetten möchten, können Sie dies beispielsweise mit lua-resty-hoedown tun (es hängt von LuaJIT ab). Hier ist ein Beispiel für die Verwendung:
Lua
local template = require "resty.template"
template.markdown = require "resty.hoedown"
template.render[=[
<html>
<body>
{*markdown[[
#Hallo, Welt
Markdown testen.
]]*}
</body>
</html>
]=]
Ausgabe
<html>
<body>
<h1>Hallo, Welt</h1>
<p>Markdown testen.</p>
</body>
</html>
Sie können auch Konfigurationsparameter hinzufügen, die im Projekt lua-resty-hoedown dokumentiert sind. Angenommen, Sie möchten auch SmartyPants verwenden:
Lua
local template = require "resty.template"
template.markdown = require "resty.hoedown"
template.render[=[
<html>
<body>
{*markdown([[
#Hallo, Welt
Markdown testen mit "SmartyPants"...
]], { smartypants = true })*}
</body>
</html>
]=]
Ausgabe
<html>
<body>
<h1>Hallo, Welt</h1>
<p>Markdown testen mit “SmartyPants”…</p>
</body>
</html>
Sie möchten möglicherweise auch eine Caching-Schicht für Ihre Markdowns hinzufügen oder Hilfsfunktionen anstelle der direkten Platzierung der Hoedown-Bibliothek als Template-Helferfunktion in template.
Lua Server Pages (LSP) mit OpenResty
Lua Server Pages oder LSPs sind ähnlich wie traditionelle PHP oder Microsoft Active Server Pages (ASP), wo Sie einfach Quellcodedateien in Ihrem Dokumentenstamm (Ihres Webservers) ablegen und sie von den Compilern der jeweiligen Sprachen (PHP, VBScript, JScript usw.) verarbeiten lassen können. Sie können dies mit lua-resty-template ziemlich genau nachahmen, manchmal als Spaghetti-Stil der Entwicklung bezeichnet. Diejenigen, die ASP.NET Web Forms-Entwicklung gemacht haben, kennen das Konzept von Code Behind-Dateien. Es gibt etwas Ähnliches, aber diesmal nennen wir es Layout in Front (Sie können Lua-Module mit normalen require-Aufrufen einfügen, wenn Sie möchten, in LSPs). Um Ihnen die Konzepte zu verdeutlichen, lassen Sie uns ein kleines Beispiel haben:
nginx.conf:
http {
init_by_lua '
require "resty.core"
template = require "resty.template"
template.caching(false); -- Sie können dies in der Produktion entfernen
';
server {
location ~ \.lsp$ {
default_type text/html;
content_by_lua 'template.render(ngx.var.uri)';
}
}
}
Die obige Konfiguration erstellt eine globale template-Variable in der Lua-Umgebung (Sie möchten das möglicherweise nicht). Wir haben auch einen Standort erstellt, um alle .lsp-Dateien (oder Standorte) zu erfassen, und dann rendern wir einfach die Vorlage.
Stellen wir uns vor, die Anfrage ist für index.lsp.
index.lsp
{%
layout = "layouts/default.lsp"
local title = "Hallo, Welt!"
%}
<h1>{{title}}</h1>
Hier sehen Sie, dass diese Datei ein wenig Ansicht (<h1>{{title}}</h1>) zusätzlich zu etwas Lua-Code enthält, den wir ausführen möchten. Wenn Sie eine reine Code-Datei mit Layout in Front haben möchten, schreiben Sie einfach keinen Ansichtscode in diese Datei. Die layout-Variable ist bereits in den Ansichten definiert, wie an anderer Stelle in dieser Dokumentation dokumentiert. Lassen Sie uns nun die anderen Dateien ebenfalls ansehen.
layouts/default.lsp
<html>
{(include/header.lsp)}
<body>
{*view*}
</body>
</html>
Hier haben wir ein Layout, um index.lsp zu dekorieren, aber wir haben hier auch eine Einfügung, also schauen wir uns das an.
include/header.lsp
<head>
<title>Testing Lua Server Pages</title>
</head>
Nur statische Dinge hier.
Ausgabe
Die endgültige Ausgabe sieht wie folgt aus:
<html>
<head>
<title>Testing Lua Server Pages</title>
</head>
<body>
<h1>Hallo, Welt!</h1>
</body>
</html>
Wie Sie sehen können, kann lua-resty-template ziemlich flexibel und einfach zu starten sein. Legen Sie einfach Dateien unter Ihrem Dokumentenstamm ab und verwenden Sie den normalen Speichern-und-Aktualisieren-Stil der Entwicklung. Der Server wird die neuen Dateien automatisch erkennen und die Vorlagen (wenn das Caching deaktiviert ist) beim Speichern neu laden.
Wenn Sie Variablen an Layouts oder Einfügungen übergeben möchten, können Sie Dinge zur Kontexttabelle hinzufügen (im folgenden Beispiel sehen Sie context.title):
{%
layout = "layouts/default.lsp"
local title = "Hallo, Welt!"
context.title = 'Meine Anwendung - ' .. title
%}
<h1>{{title}}</h1>
FAQ
Wie lösche ich den Template-Cache
lua-resty-template cached automatisch (wenn Caching aktiviert ist) die resultierenden Template-Funktionen in der template.cache-Tabelle. Sie können den Cache leeren, indem Sie template.cache = {} ausführen.
Wo wird lua-resty-template verwendet
- jd.com – Jingdong Mall (Chinesisch: 京东商城; Pinyin: Jīngdōng Shāngchéng), früher 360Buy, ist ein chinesisches E-Commerce-Unternehmen
Bitte lassen Sie mich wissen, wenn es Fehler oder veraltete Informationen in dieser Liste gibt.
Alternativen
Sie können sich auch diese (als Alternativen oder um sie mit lua-resty-template zu mischen) ansehen:
- lemplate (https://github.com/openresty/lemplate)
- lua-resty-tags (https://github.com/bungle/lua-resty-tags)
- lua-resty-hoedown (https://github.com/bungle/lua-resty-hoedown)
- etlua (https://github.com/leafo/etlua)
- lua-template (https://github.com/dannote/lua-template)
- lua-resty-tmpl (https://github.com/lloydzhou/lua-resty-tmpl) (ein Fork von lua-template)
- htmlua (https://github.com/benglard/htmlua)
- cgilua (http://keplerproject.github.io/cgilua/manual.html#templates)
- orbit (http://keplerproject.github.io/orbit/pages.html)
- turbolua mustache (http://turbolua.org/doc/web.html#mustache-templating)
- pl.template (http://stevedonovan.github.io/Penlight/api/modules/pl.template.html)
- lustache (https://github.com/Olivine-Labs/lustache)
- luvstache (https://github.com/james2doyle/luvstache)
- luaghetti (https://github.com/AterCattus/luaghetti)
- lub.Template (http://doc.lubyk.org/lub.Template.html)
- lust (https://github.com/weshoke/Lust)
- templet (http://colberg.org/lua-templet/)
- luahtml (https://github.com/TheLinx/LuaHTML)
- mixlua (https://github.com/LuaDist/mixlua)
- lutem (https://github.com/daly88/lutem)
- tirtemplate (https://github.com/torhve/LuaWeb/blob/master/tirtemplate.lua)
- cosmo (http://cosmo.luaforge.net/)
- lua-codegen (http://fperrad.github.io/lua-CodeGen/)
- groucho (https://github.com/hanjos/groucho)
- einfacher Lua-Präprozessor (http://lua-users.org/wiki/SimpleLuaPreprocessor)
- etwas weniger einfacher Lua-Präprozessor (http://lua-users.org/wiki/SlightlyLessSimpleLuaPreprocessor)
- ltp (http://www.savarese.com/software/ltp/)
- slt (https://code.google.com/p/slt/)
- slt2 (https://github.com/henix/slt2)
- luasp (http://luasp.org/)
- view0 (https://bitbucket.org/jimstudt/view0)
- leslie (https://code.google.com/p/leslie/)
- fraudster (https://bitbucket.org/sphen_lee/fraudster)
- lua-haml (https://github.com/norman/lua-haml)
- lua-template (https://github.com/tgn14/Lua-template)
- hige (https://github.com/nrk/hige)
- mod_pLua (https://sourceforge.net/p/modplua/wiki/Home/)
- lapis HTML-Generierung (http://leafo.net/lapis/reference.html#html-generation)
lua-resty-template wurde ursprünglich von Tor Hveems tirtemplate.lua abgezweigt, das er aus Zed Shaws Tir-Web-Framework (http://tir.mongrel2.org/) extrahiert hatte. Vielen Dank an Tor und Zed für Ihre früheren Beiträge.
Benchmarks
Es gibt ein kleines Mikrobenchmark hier: https://github.com/bungle/lua-resty-template/blob/master/lib/resty/template/microbenchmark.lua
Es gibt auch einen Regression in LuaJIT, der die Ergebnisse beeinflusst. Wenn Sie möchten, dass Ihr LuaJIT gegen diesen gepatcht wird, müssen Sie diesen Pull-Request zusammenführen: https://github.com/LuaJIT/LuaJIT/pull/174.
Andere haben berichtet, dass in einfachen Benchmarks diese Template-Engine tatsächlich Nginx beim Bereitstellen statischer Dateien um den Faktor drei übertrifft. Ich schätze, diese Engine ist ziemlich schnell.
Lua
local benchmark = require "resty.template.microbenchmark"
benchmark.run()
-- Sie können auch die Iterationsanzahl übergeben (standardmäßig sind es 1.000)
benchmark.run(100)
Hier sind einige Ergebnisse von meinem Desktop (alter 2010 Mac Pro):
<lua|luajit|resty> -e 'require "resty.template.microbenchmark".run()'
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
1000 Iterationen in jedem Test werden ausgeführt
Parsing-Zeit: 0.010759
Kompilierungszeit: 0.054640 (Template)
Kompilierungszeit: 0.000213 (Template, zwischengespeichert)
Ausführungszeit: 0.061851 (dasselbe Template)
Ausführungszeit: 0.006722 (dasselbe Template, zwischengespeichert)
Ausführungszeit: 0.092698 (verschiedene Vorlagen)
Ausführungszeit: 0.009537 (verschiedene Vorlagen, zwischengespeichert)
Ausführungszeit: 0.092452 (verschiedene Vorlagen, verschiedener Kontext)
Ausführungszeit: 0.010106 (verschiedene Vorlagen, verschiedener Kontext, zwischengespeichert)
Gesamtzeit: 0.338978
Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio
1000 Iterationen in jedem Test werden ausgeführt
Parsing-Zeit: 0.011633
Kompilierungszeit: 0.060598 (Template)
Kompilierungszeit: 0.000243 (Template, zwischengespeichert)
Ausführungszeit: 0.068009 (dasselbe Template)
Ausführungszeit: 0.007307 (dasselbe Template, zwischengespeichert)
Ausführungszeit: 0.071339 (verschiedene Vorlagen)
Ausführungszeit: 0.007150 (verschiedene Vorlagen, zwischengespeichert)
Ausführungszeit: 0.066766 (verschiedene Vorlagen, verschiedener Kontext)
Ausführungszeit: 0.006940 (verschiedene Vorlagen, verschiedener Kontext, zwischengespeichert)
Gesamtzeit: 0.299985
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
1000 Iterationen in jedem Test werden ausgeführt
Parsing-Zeit: 0.012458
Kompilierungszeit: 0.050013 (Template)
Kompilierungszeit: 0.000249 (Template, zwischengespeichert)
Ausführungszeit: 0.057579 (dasselbe Template)
Ausführungszeit: 0.006959 (dasselbe Template, zwischengespeichert)
Ausführungszeit: 0.065352 (verschiedene Vorlagen)
Ausführungszeit: 0.007133 (verschiedene Vorlagen, zwischengespeichert)
Ausführungszeit: 0.060965 (verschiedene Vorlagen, verschiedener Kontext)
Ausführungszeit: 0.007726 (verschiedene Vorlagen, verschiedener Kontext, zwischengespeichert)
Gesamtzeit: 0.268434
Lua 5.4.0 Copyright (C) 1994-2019 Lua.org, PUC-Rio
1000 Iterationen in jedem Test werden ausgeführt
Parsing-Zeit: 0.009466
Kompilierungszeit: 0.053116 (Template)
Kompilierungszeit: 0.000209 (Template, zwischengespeichert)
Ausführungszeit: 0.059017 (dasselbe Template)
Ausführungszeit: 0.006129 (dasselbe Template, zwischengespeichert)
Ausführungszeit: 0.061882 (verschiedene Vorlagen)
Ausführungszeit: 0.006613 (verschiedene Vorlagen, zwischengespeichert)
Ausführungszeit: 0.059104 (verschiedene Vorlagen, verschiedener Kontext)
Ausführungszeit: 0.005761 (verschiedene Vorlagen, verschiedener Kontext, zwischengespeichert)
Gesamtzeit: 0.261297
LuaJIT 2.0.5 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/
1000 Iterationen in jedem Test werden ausgeführt
Parsing-Zeit: 0.005198
Kompilierungszeit: 0.029687 (Template)
Kompilierungszeit: 0.000082 (Template, zwischengespeichert)
Ausführungszeit: 0.033824 (dasselbe Template)
Ausführungszeit: 0.003130 (dasselbe Template, zwischengespeichert)
Ausführungszeit: 0.075899 (verschiedene Vorlagen)
Ausführungszeit: 0.007027 (verschiedene Vorlagen, zwischengespeichert)
Ausführungszeit: 0.070269 (verschiedene Vorlagen, verschiedener Kontext)
Ausführungszeit: 0.007456 (verschiedene Vorlagen, verschiedener Kontext, zwischengespeichert)
Gesamtzeit: 0.232572
LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/
1000 Iterationen in jedem Test werden ausgeführt
Parsing-Zeit: 0.003647
Kompilierungszeit: 0.027145 (Template)
Kompilierungszeit: 0.000083 (Template, zwischengespeichert)
Ausführungszeit: 0.034685 (dasselbe Template)
Ausführungszeit: 0.002801 (dasselbe Template, zwischengespeichert)
Ausführungszeit: 0.073466 (verschiedene Vorlagen)
Ausführungszeit: 0.010836 (verschiedene Vorlagen, zwischengespeichert)
Ausführungszeit: 0.068790 (verschiedene Vorlagen, verschiedener Kontext)
Ausführungszeit: 0.009818 (verschiedene Vorlagen, verschiedener Kontext, zwischengespeichert)
Gesamtzeit: 0.231271
resty (resty 0.23, nginx version: openresty/1.15.8.2)
``` 1000 Iterationen in jedem Test werden ausgeführt Parsing-Zeit: 0.003980 Kompilierungs