CSS/JS: Git-Revision von HEAD als GET-Parameter verwenden
authorMoritz Bunkus <m.bunkus@linet.de>
Mon, 16 Nov 2020 16:02:38 +0000 (17:02 +0100)
committerMoritz Bunkus <m.bunkus@linet.de>
Mon, 16 Nov 2020 16:18:19 +0000 (17:18 +0100)
Webbrowser cachen CSS & JS sehr aggressiv. Das ist während der
Entwicklung störend, weshalb es bereits seit langem die
Konfigurationsoption `auto_reload_resources` gibt. Ist diese an, so
wird an alle CSS- und JS-URLs ein GET-Parameter `?rand=<Zufallswert>`
angehängt wird, um das Cachen auszuhebeln.

Dieser Commit führt etwas Ähnliches ein, das für den Produktivbetrieb
ohne `auto_reload_resources` gedacht ist. Wenn kivitendo erkennt, dass
es aus git heraus läuft (also ein `.git`-Verzeichnis existiert), so
parset es die Revision von `HEAD` und nimmt das als GET-Parameter
`?rand=<Revision>`. Der Vorteil ist, dass nach Updates einer
Produktivinstallation die Webbrowser der Anwender*innen genau einmal
alle Ressourcen neu laden, weil sich ja die Git-Revisionsnummer
geändert hat. Anschließend können sie die Ressourcen aber wieder
normal cachen, bis das nächste Update kommt.

Es wird hierfür übrigens kein installiertes git-Executable benötigt;
die Infos werden zwecks Performance direkt aus den Dateien gelesen,
anstatt bei jedem Request ein Programm auszuführen.

Zukünftig könnte man ein analoges Verfahren anwenden, wenn es kein
`.git`-Verzeichnis gibt, und dann zumindest die
kivitendo-Versionsnummer verwenden.

SL/Layout/Base.pm

index df9c008..8e6acfc 100644 (file)
@@ -3,6 +3,7 @@ package SL::Layout::Base;
 use strict;
 use parent qw(Rose::Object);
 
+use File::Slurp qw(read_file);
 use List::MoreUtils qw(uniq);
 use Time::HiRes qw();
 
@@ -19,6 +20,7 @@ use Rose::Object::MakeMethods::Generic (
 
 use SL::Menu;
 use SL::Presenter;
+use SL::System::Process;
 
 my %menu_cache;
 
@@ -42,8 +44,21 @@ sub get {
 }
 
 sub init_auto_reload_resources_param {
-  return '' unless $::lx_office_conf{debug}->{auto_reload_resources};
-  return sprintf('?rand=%d-%d-%d', Time::HiRes::gettimeofday(), int(rand 1000000000000));
+  return sprintf('?rand=%d-%d-%d', Time::HiRes::gettimeofday(), int(rand 1000000000000)) if $::lx_office_conf{debug}->{auto_reload_resources};
+
+  my $git_dir = SL::System::Process::exe_dir() . '/.git';
+
+  return '' unless -d $git_dir;
+
+  my $content = eval { scalar(read_file($git_dir . '/HEAD')) };
+
+  return '' unless ($content // '') =~ m{\Aref: ([^\r\n]+)};
+
+  $content = eval { scalar(read_file($git_dir . '/' . $1)) };
+
+  return '' unless ($content // '') =~ m{\A([0-9a-fA-F]+)};
+
+  return '?rand=' . $1;
 }
 
 ##########################################