Zum Inhalt

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

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 die template-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 (,) in file.html verwenden, verwenden Sie in diesem Fall {["file,with,comma"]} stattdessen)
  • {[expression]}, schließt die expression-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 einer blocks-Tabelle mit einem Schlüssel block gespeichert ist (in diesem Fall), siehe Verwendung von Blöcken. Verwenden Sie keine vordefinierten Blocknamen verbatim und raw.
  • {-verbatim-}...{-verbatim-} und {-raw-}...{-raw-} sind vordefinierte Blöcke, deren Inhalt nicht von lua-resty-template verarbeitet 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 &amp;
  • < wird zu &lt;
  • > wird zu &gt;
  • " wird zu &quot;
  • ' wird zu &#39;
  • / wird zu &#47;

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.___}} verwenden
  • context, hält den aktuellen Kontext, wenn gesetzt, müssen Sie {{context.context}} verwenden
  • echo, hält die Echo-Helferfunktion, wenn gesetzt, müssen Sie {{context.echo}} verwenden
  • include, hält die Include-Helferfunktion, wenn gesetzt, müssen Sie {{context.include}} verwenden
  • layout, hält das Layout, mit dem die Ansicht dekoriert wird, wenn gesetzt, müssen Sie {{context.layout}} verwenden
  • blocks, 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- und table-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 zur context-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:

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 &ldquo;SmartyPants&rdquo;&hellip;</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:

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()'

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
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
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
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
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
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