diff options
author | Yorhel <git@yorhel.nl> | 2019-11-03 14:12:35 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2019-11-10 12:44:55 +0100 |
commit | cc4607635279792b59953bba2e3cb4a3928e76df (patch) | |
tree | 227627601aa35df51e2ca10ff0006495bb933e9e /lib/VNWeb | |
parent | 6ae025a405ea6e40c37a183ba7f3a98c4d9e39cb (diff) |
Reorganize JS and Elm instantiation + more efficient ulist loading
The order in which .js files are concatenated is (and always has been)
important, so rather than relying on name order I've changed that to an
explicit $JS_FILES list in the Makefile. Less convenient, but at least
we have more freedom regarding .js file naming and organization now.
Rather than encoding the Elm flags as JSON in 'data-' attributes, I've
added a system for global page variables (pagevars) where the Elm flags
are now stored separately from their HTML tags. This has the advantage
of more efficient encoding (no more "s), faster parsing (just a
single JSON.parse()), and easier/more efficient modification of the Elm
arguments from JS. The pagevars provide a unified way of passing other
variables to JS as well, which I've used to deduplicate the list of
labels on the new ulist page. That shaves off a good 40 KiB on the page
size for a typical listing.
Whether all of this actually improves the page loading time, I don't
really know. Most of the slowness in Firefox seems to come from simply
instantiating many <input time="date"> objects.
Diffstat (limited to 'lib/VNWeb')
-rw-r--r-- | lib/VNWeb/HTML.pm | 17 | ||||
-rw-r--r-- | lib/VNWeb/User/Lists.pm | 11 |
2 files changed, 19 insertions, 9 deletions
diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm index 23432627..30813aac 100644 --- a/lib/VNWeb/HTML.pm +++ b/lib/VNWeb/HTML.pm @@ -33,6 +33,9 @@ our @EXPORT = qw/ /; +# Encoded as JSON and appended to the end of the page, to be read by pagevars.js. +my %pagevars; + # Ugly hack to move rendering down below the float object. sub clearfloat_ { div_ class => 'clearfloat', '' } @@ -93,10 +96,9 @@ sub user_displayname { # Instantiate an Elm module sub elm_ { my($mod, $schema, $data, $placeholder) = @_; - div_ 'data-elm-module' => $mod, - $data ? ( - 'data-elm-flags' => JSON::XS->new->allow_nonref->encode($schema ? $schema->analyze->coerce_for_json($data, unknown => 'remove') : $data) - ) : (), $placeholder//''; + $pagevars{elm} ||= []; + push $pagevars{elm}->@*, [ $mod, $data ? ($schema ? $schema->analyze->coerce_for_json($data, unknown => 'remove') : $data) : () ]; + div_ id => "elm$#{$pagevars{elm}}", $placeholder//''; } @@ -282,6 +284,8 @@ sub _footer_ { my $modules = uri_escape join "\n", sort keys %INC; a_ href => 'data:text/plain,'.$modules, 'Modules'; + lit_ ' | '; + debug_ \%pagevars; } } @@ -394,6 +398,7 @@ sub _hidden_msg_ { sub framework_ { my $cont = pop; my %o = @_; + %pagevars = $o{pagevars} ? $o{pagevars}->%* : (); html_ lang => 'en', sub { head_ sub { _head_ \%o }; @@ -406,6 +411,10 @@ sub framework_ { $cont->() unless $o{hiddenmsg} && _hidden_msg_ \%o; div_ id => 'footer', \&_footer_; }; + script_ type => 'application/json', id => 'pagevars', sub { + # Escaping rules for a JSON <script> context are kinda weird, but more efficient than regular xml_escape(). + lit_(JSON::XS->new->canonical->encode(\%pagevars) =~ s{</}{<\\/}rg =~ s/<!--/<\\u0021--/rg); + } if keys %pagevars; script_ type => 'application/javascript', src => config->{url_static}.'/f/v2rw.js?'.config->{version}, ''; } } diff --git a/lib/VNWeb/User/Lists.pm b/lib/VNWeb/User/Lists.pm index 7d599536..2558963b 100644 --- a/lib/VNWeb/User/Lists.pm +++ b/lib/VNWeb/User/Lists.pm @@ -125,10 +125,7 @@ sub vn_ { my @l = grep $l{$_->{id}} && $_->{id} != 7, @$labels; my $txt = @l ? join ', ', map $_->{label}, @l : '-'; if($own) { - # XXX: Copying the entire $labels list for each entry is rather inefficient, would be nice if we could store that globally. - my @labels = grep $_->{id} != 7, @$labels; - elm_ 'ULists.LabelEdit' => $VNLABELS_OUT, - { uid => $uid, vid => $v->{id}, labels => \@labels, selected => [ grep $_ != 7, $v->{labels}->@* ] }, $txt; + elm_ 'ULists.LabelEdit' => $VNLABELS_OUT, { vid => $v->{id}, selected => [ grep $_ != 7, $v->{labels}->@* ] }, $txt; } else { txt_ $txt; } @@ -240,12 +237,16 @@ TUWF::get qr{/$RE{uid}/ulist}, sub { my $title = $own ? 'My list' : user_displayname($u)."'s list"; framework_ title => $title, type => 'u', dbobj => $u, tab => 'list', + $own ? ( pagevars => { + uid => $u->{id}*1, + labels => $LABELS->analyze->{keys}{labels}->coerce_for_json($labels), + } ) : (), sub { my $opt; div_ class => 'mainbox', sub { h1_ $title; $opt = filters_ $own, $labels; - elm_ 'ULists.ManageLabels', $LABELS, { uid => $u->{id}, labels => $labels } if $own; + elm_ 'ULists.ManageLabels' if $own; }; listing_ $u->{id}, $own, $opt, $labels; }; |