PERF: reduces rendering time of local-dates (#13931)

PERF: reduces rendering time of local-dates (#13931)

  • prefers insertAdjacentHTML over innerHTML as it’s much faster in this case (about 5x)
  • memoizes tz.guess()
  • memoizes list of timezones
  • inlines template
  • applies main element class in one pass

All in all for a very edge case of about 80 dates it should be faster of about 15/20ms.

diff --git a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6 b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6
index c4633d1..53d8d04 100644
--- a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6
+++ b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js.es6
@@ -2,15 +2,6 @@ import LocalDateBuilder from "../lib/local-date-builder";
 import showModal from "discourse/lib/show-modal";
 import { withPluginApi } from "discourse/lib/plugin-api";
 
-const DATE_TEMPLATE = `
-  <span>
-    <svg class="fa d-icon d-icon-globe-americas svg-icon" xmlns="http://www.w3.org/2000/svg">
-      <use xlink:href="#globe-americas"></use>
-    </svg>
-    <span class="relative-time"></span>
-  </span>
-`;
-
 function initializeDiscourseLocalDates(api) {
   api.decorateCooked(
     ($elem) => $(".discourse-local-date", $elem).applyLocalDates(),
@@ -45,6 +36,8 @@ export default {
   initialize(container) {
     const siteSettings = container.lookup("site-settings:main");
     if (siteSettings.discourse_local_dates_enabled) {
+      const currentUserTZ = moment.tz.guess();
+
       $.fn.applyLocalDates = function () {
         return this.each(function () {
           const opts = {};
@@ -67,7 +60,7 @@ export default {
 
           const localDateBuilder = new LocalDateBuilder(
             opts,
-            moment.tz.guess()
+            currentUserTZ
           ).build();
 
           const htmlPreviews = localDateBuilder.previews.map((preview) => {
@@ -96,15 +89,24 @@ export default {
             previewsNode.appendChild(htmlPreview)
           );
 
-          this.innerHTML = DATE_TEMPLATE;
+          this.innerText = "";
+          this.insertAdjacentHTML(
+            "beforeend",
+            `
+              <svg class="fa d-icon d-icon-globe-americas svg-icon" xmlns="http://www.w3.org/2000/svg">
+                <use xlink:href="#globe-americas"></use>
+              </svg>
+              <span class="relative-time">${localDateBuilder.formated}</span>
+            `
+          );
           this.setAttribute("aria-label", localDateBuilder.textPreview);
           this.dataset.htmlTooltip = previewsNode.outerHTML;
-          this.classList.add("cooked-date");
+
+          const classes = ["cooked-date"];
           if (localDateBuilder.pastEvent) {
-            this.classList.add("past");
+            classes.push("past");
           }
-          const relativeTime = this.querySelector(".relative-time");
-          relativeTime.innerText = localDateBuilder.formated;
+          this.classList.add(...classes);
         });
       };
 
diff --git a/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6 b/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6
index 09eba6c..69ecd7f 100644
--- a/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6
+++ b/plugins/discourse-local-dates/assets/javascripts/lib/discourse-markdown/discourse-local-dates.js.es6
@@ -1,5 +1,7 @@
 import { parseBBCodeTag } from "pretty-text/engines/discourse-markdown/bbcode-block";
 
+const timezoneNames = moment.tz.names();
+
 function addLocalDate(buffer, matches, state) {
   let token;
 
@@ -77,7 +79,7 @@ function addLocalDate(buffer, matches, state) {
 
   if (
     config.displayedTimezone &&
-    moment.tz.names().includes(config.displayedTimezone)
+    timezoneNames.includes(config.displayedTimezone)
   ) {
     token.attrs.push([
       "data-displayed-timezone",
@@ -87,7 +89,7 @@ function addLocalDate(buffer, matches, state) {
 
   if (config.timezones) {
     const timezones = config.timezones.split("|").filter((timezone) => {
-      return moment.tz.names().includes(timezone);
+      return timezoneNames.includes(timezone);
     });
 
     token.attrs.push([
@@ -96,7 +98,7 @@ function addLocalDate(buffer, matches, state) {
     ]);
   }
 
-  if (config.timezone && moment.tz.names().includes(config.timezone)) {
+  if (config.timezone && timezoneNames.includes(config.timezone)) {
     token.attrs.push([
       "data-timezone",
       state.md.utils.escapeHtml(config.timezone),

GitHub sha: d23c0c06c380045370c2f117fd27424a459956ba

This commit appears in #13931 which was approved by davidtaylorhq. It was merged by jjaffeux.