From 3e2cacb826dc703b789d575c378f8dccb2dc95a6 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Fri, 29 May 2020 09:51:09 +0200 Subject: JS: Split v2rw.js into plain.js and elm.js, only include JS files when necessary The trace_log showed that the vast majority of pageviews do not need any Elm modules at all, so we can save a lot by not loading them on the page. Some pages (most notably: VN pages for not-logged-in visitors) do need JS but don't load any Elm modules. I've added a 'js' flag to HTML::framework_() to indicate that and ensure that plain.js is still loaded. --- .gitignore | 9 +++++--- Makefile | 50 +++++++++++++++++++++++++++-------------- elm/ImageFlagging.js | 6 ++--- elm/UList/LabelEdit.js | 5 ++--- elm/UList/ManageLabels.js | 5 ++--- elm/UList/Opt.js | 12 +++++----- elm/UList/VoteEdit.js | 5 ++--- elm/elm-init.js | 2 +- elm/lib.js | 15 +++++++++++++ elm/pagevars.js | 5 ----- lib/VNDB/Util/LayoutHTML.pm | 1 - lib/VNWeb/HTML.pm | 17 ++++++-------- lib/VNWeb/User/Lists.pm | 2 +- lib/VNWeb/User/Notifications.pm | 2 +- lib/VNWeb/VN/Page.pm | 2 +- 15 files changed, 78 insertions(+), 60 deletions(-) create mode 100644 elm/lib.js delete mode 100644 elm/pagevars.js diff --git a/.gitignore b/.gitignore index eda3cee9..584a6483 100644 --- a/.gitignore +++ b/.gitignore @@ -12,9 +12,12 @@ /static/f/vndb.js /static/f/vndb.min.js /static/f/vndb.min.js.gz -/static/f/v2rw.js -/static/f/v2rw.min.js -/static/f/v2rw.min.js.gz +/static/f/elm.js +/static/f/elm.min.js +/static/f/elm.min.js.gz +/static/f/plain.js +/static/f/plain.min.js +/static/f/plain.min.js.gz /static/feeds/ /static/s/*/style.css /static/s/*/style.min.css diff --git a/Makefile b/Makefile index 953cd1c2..35151029 100644 --- a/Makefile +++ b/Makefile @@ -30,14 +30,16 @@ ALL_KEEP=\ ALL_CLEAN=\ static/f/vndb.js \ - static/f/v2rw.js \ + static/f/plain.js \ + static/f/elm.js \ data/icons/icons.css \ sql/editfunc.sql \ $(shell ls static/s | sed -e 's/\(.\+\)/static\/s\/\1\/style.css/g') PROD=\ static/f/vndb.min.js static/f/vndb.min.js.gz \ - static/f/v2rw.min.js static/f/v2rw.min.js.gz \ + static/f/plain.min.js static/f/plain.min.js.gz \ + static/f/elm.min.js static/f/elm.min.js.gz \ static/f/icons.opt.png \ $(shell ls static/s | sed -e 's/\(.\+\)/static\/s\/\1\/style.min.css/g') \ $(shell ls static/s | sed -e 's/\(.\+\)/static\/s\/\1\/style.min.css.gz/g') @@ -115,43 +117,57 @@ static/f/vndb.min.js: static/f/vndb.js # Files without that comment are assumed to have '//order:4'. # (This trick will not work if we ever add JS files generated by this Makefile) JS_FILES=$(shell find elm \! -path 'elm/elm-stuff/*' -name '*.js' -exec sh -c "echo \`grep -Eo '^// *order: *[0-9]+' \"{}\" || echo 4\` \"{}\"" \; | sed -E 's/\/\/ *order: *//' | sort | sed 's/..//') + +static/f/plain.js: ${JS_FILES} | static/f + echo '// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0-only' > $@~ + echo '// @source: https://code.blicky.net/yorhel/vndb/src/branch/master/elm' >>$@~ + echo '// SPDX-License-Identifier: AGPL-3.0-only' >>$@~ + for fn in ${JS_FILES}; do \ + echo; \ + echo "(function(){'use strict'; /* $$fn */"; \ + cat $$fn; \ + echo "})();"; \ + done >>$@~ + echo '// @license-end' >>$@~ + mv $@~ $@ + +static/f/plain.min.js: static/f/plain.js + uglifyjs $< --comments '/(@license|@source|SPDX-)/' --compress \ + 'pure_getters,keep_fargs=false,unsafe_comps,unsafe'\ + | uglifyjs --mangle --comments all -o $@ + + ELM_FILES=elm/*.elm elm/*/*.elm ELM_MODULES=$(shell grep -l '^main =' ${ELM_FILES} | sed 's/^elm\///') -# Patch the Javascript generated by Elm and append the $JS_FILES to it. -# Patches include: +# Patch the Javascript generated by Elm: # - Add @license and @source comments # - Redirect calls from Lib.Ffi.* to window.elmFfi_* # - Patch the virtualdom diffing algorithm to always apply the 'selected' attribute -define fix-js +define fix-elm ( echo '// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0-only'; \ echo '// @license magnet:?xt=urn:btih:c80d50af7d3db9be66a4d0a86db0286e4fd33292&dn=bsd-3-clause.txt BSD-3-Clause'; \ echo '// @source: https://code.blicky.net/yorhel/vndb/src/branch/master/elm'; \ echo '// SPDX-License-Identifier: AGPL-3.0-only and BSD-3-Clause'; \ - cat $@ \ + cat $@; \ + echo; \ + echo '// @license-end' \ ) | sed 's/var \$$author\$$project\$$Lib\$$Ffi\$$/var __unused__/g' \ | sed -E 's/\$$author\$$project\$$Lib\$$Ffi\$$([a-zA-Z0-9_]+)/window.elmFfi_\1(_Json_wrap,_Browser_call)/g' \ | sed -E "s/([^ ]+) !== 'checked'/\\1 !== 'checked' \&\& \\1 !== 'selected'/g" >$@~ - for fn in ${JS_FILES}; do \ - echo; \ - echo "(function(){'use strict'; /* $$fn */"; \ - cat $$fn; \ - echo "})();"; \ - done >>$@~ - echo '// @license-end' >>$@~ mv $@~ $@ endef elm/Gen/.generated: lib/VNWeb/*.pm lib/VNWeb/*/*.pm lib/VNDB/Types.pm lib/VNDB/ExtLinks.pm lib/VNDB/Config.pm data/conf.pl util/vndb.pl elmgen -static/f/v2rw.js: ${ELM_FILES} ${JS_FILES} elm/Gen/.generated | static/f +static/f/elm.js: ${ELM_FILES} elm/Gen/.generated | static/f cd elm && ELM_HOME=elm-stuff elm make ${ELM_MODULES} --output ../$@ - ${fix-js} + ${fix-elm} -static/f/v2rw.min.js: ${ELM_FILES} ${JS_FILES} elm/Gen/.generated | static/f +static/f/elm.min.js: ${ELM_FILES} elm/Gen/.generated | static/f cd elm && ELM_HOME=elm-stuff elm make --optimize ${ELM_MODULES} --output ../$@ - ${fix-js} + ${fix-elm} uglifyjs $@ --comments '/(@license|@source|SPDX-)/' --compress \ 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe'\ | uglifyjs --mangle --comments all -o $@~ diff --git a/elm/ImageFlagging.js b/elm/ImageFlagging.js index 87ced23a..d460bd10 100644 --- a/elm/ImageFlagging.js +++ b/elm/ImageFlagging.js @@ -1,6 +1,4 @@ -var init = Elm.ImageFlagging.init; - -Elm.ImageFlagging.init = function(opt) { +wrap_elm_init('ImageFlagging', function(init, opt) { opt.flags.pWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; opt.flags.pHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; var app = init(opt); @@ -15,4 +13,4 @@ Elm.ImageFlagging.init = function(opt) { preload[url].src = url; } }); -}; +}); diff --git a/elm/UList/LabelEdit.js b/elm/UList/LabelEdit.js index 6617bf11..156ae08f 100644 --- a/elm/UList/LabelEdit.js +++ b/elm/UList/LabelEdit.js @@ -1,5 +1,4 @@ -var init = Elm.UList.LabelEdit.init; -Elm.UList.LabelEdit.init = function(opt) { +wrap_elm_init('UList.LabelEdit', function(init, opt) { opt.flags.uid = pageVars.uid; opt.flags.labels = pageVars.labels; var app = init(opt); @@ -8,4 +7,4 @@ Elm.UList.LabelEdit.init = function(opt) { l.setAttribute('data-publabel', pub?1:''); l.classList.toggle('invisible', !((l.getAttribute('data-voted') && !pageVars.voteprivate) || l.getAttribute('data-publabel'))) }); -}; +}); diff --git a/elm/UList/ManageLabels.js b/elm/UList/ManageLabels.js index 6f762bd8..f9f8c68b 100644 --- a/elm/UList/ManageLabels.js +++ b/elm/UList/ManageLabels.js @@ -6,8 +6,7 @@ document.querySelectorAll('#managelabels').forEach(function(b) { return false; }); -var init = Elm.UList.ManageLabels.init; -Elm.UList.ManageLabels.init = function(opt) { +wrap_elm_init('UList.ManageLabels', function(init, opt) { opt.flags = { uid: pageVars.uid, labels: pageVars.labels }; init(opt); -}; +}); diff --git a/elm/UList/Opt.js b/elm/UList/Opt.js index 75a302b9..7a80884a 100644 --- a/elm/UList/Opt.js +++ b/elm/UList/Opt.js @@ -1,6 +1,4 @@ -var init = Elm.UList.Opt.init; - -var actualInit = function(opt) { +var actualInit = function(init, opt) { var app = init(opt); app.ports.ulistVNDeleted.subscribe(function(b) { @@ -27,10 +25,10 @@ var actualInit = function(opt) { }; // This module is typically hidden, lazily load it only when the module is visible to speed up page load time. -Elm.UList.Opt.init = function(opt) { +wrap_elm_init('UList.Opt', function(init, opt) { var e = document.getElementById('collapse_vid'+opt.flags.vid); if(e.checked) - actualInit(opt); + actualInit(init, opt); else - e.addEventListener('click', function() { actualInit(opt) }, { once: true }); -}; + e.addEventListener('click', function() { actualInit(init, opt) }, { once: true }); +}); diff --git a/elm/UList/VoteEdit.js b/elm/UList/VoteEdit.js index 99d5b31b..a7ebfb74 100644 --- a/elm/UList/VoteEdit.js +++ b/elm/UList/VoteEdit.js @@ -1,9 +1,8 @@ -var init = Elm.UList.VoteEdit.init; -Elm.UList.VoteEdit.init = function(opt) { +wrap_elm_init('UList.VoteEdit', function(init, opt) { var app = init(opt); app.ports.ulistVoteChanged.subscribe(function(voted) { var l = document.getElementById('ulist_public_'+opt.flags.vid); l.setAttribute('data-voted', voted?1:''); l.classList.toggle('invisible', !((l.getAttribute('data-voted') && !pageVars.voteprivate) || l.getAttribute('data-publabel'))) }); -}; +}); diff --git a/elm/elm-init.js b/elm/elm-init.js index e48a94f3..d9978111 100644 --- a/elm/elm-init.js +++ b/elm/elm-init.js @@ -23,7 +23,7 @@ if(pageVars.elm) { for(var i=0; i 1) mod.init({ node: node, flags: e[1] }); diff --git a/elm/lib.js b/elm/lib.js new file mode 100644 index 00000000..859cfc22 --- /dev/null +++ b/elm/lib.js @@ -0,0 +1,15 @@ +//order:0 - Before anything else that may use these functions. + +/* Load global page-wide variables from and store them into window.pageVars */ +var e = document.getElementById('pagevars'); +window.pageVars = e ? JSON.parse(e.innerHTML) : {}; + + +// Utlity function to wrap the init() function of an Elm module. +window.wrap_elm_init = function(mod, newinit) { + mod = mod.split('.').reduce(function(p, c) { return p ? p[c] : null }, window.Elm); + if(mod) { + var oldinit = mod.init; + mod.init = function(opt) { newinit(oldinit, opt) }; + } +}; diff --git a/elm/pagevars.js b/elm/pagevars.js deleted file mode 100644 index e36ed7da..00000000 --- a/elm/pagevars.js +++ /dev/null @@ -1,5 +0,0 @@ -//order:0 - Before anything else that may use window.pageVars - -/* Load global page-wide variables from and store them into window.pageVars */ -var e = document.getElementById('pagevars'); -window.pageVars = e ? JSON.parse(e.innerHTML) : {}; diff --git a/lib/VNDB/Util/LayoutHTML.pm b/lib/VNDB/Util/LayoutHTML.pm index 6bafbeda..a18542f8 100644 --- a/lib/VNDB/Util/LayoutHTML.pm +++ b/lib/VNDB/Util/LayoutHTML.pm @@ -35,7 +35,6 @@ sub htmlFooter { # %options => { pref_code => 1 } noscript id => 'pref_code', title => $self->authGetCode('/xml/prefs.xml'), '' if $o{pref_code} && $self->authInfo->{id}; script type => 'text/javascript', src => $self->{url_static}.'/f/vndb.js?'.$self->{version}, ''; - VNWeb::HTML::v2rwjs_() if $o{v2rwjs}; end 'body'; end 'html'; } diff --git a/lib/VNWeb/HTML.pm b/lib/VNWeb/HTML.pm index 4231b3c1..25df6152 100644 --- a/lib/VNWeb/HTML.pm +++ b/lib/VNWeb/HTML.pm @@ -403,19 +403,11 @@ sub _hidden_msg_ { } -sub v2rwjs_ { # Also used by VNDB::Util::LayoutHTML. - script_ type => 'application/json', id => 'pagevars', sub { - # Escaping rules for a JSON