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.
This commit is contained in:
Joffrey JAFFEUX 2021-08-04 08:27:22 +02:00 committed by GitHub
parent 1da0aa838f
commit d23c0c06c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 18 deletions

View File

@ -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);
});
};

View File

@ -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),