Начиная с этой статьи https://www.newmediacampaigns.com/blog/maintaining-great-site-performanc-using-zendesk-web-widget Я реализовал решение, которое значительно сокращает время загрузки как минимум на 3 секунды (в Google Lighthouse).
Я создал фальшивую кнопку в HTML, которая будет загружать скрипт Zendesk и открывать виджет при нажатии. Он также загрузит элемент localStorage, который предотвратит это при последующих загрузках страницы.
⚠️ Внимание:
Код в значительной степени зависит от того, как в настоящее время реализован виджет (например, он ожидает, что на странице появятся элементы #launcher
и #webWidget
), поэтому он может сломаться, как только исходный код изменится, но, по крайней мере, мы получим улучшение в время загрузки, пока они не исправят это.
Вот самая важная часть кода:
HTML-кнопка
<button class="zendesk-button">
<span class="left-icon">
<!-- here you insert the icon -->
</span>
<span class="text">Chat</span>
</button>
JavaScript-код
// select the button
const zendeskButton = document.querySelector('.zendesk-button');
// add the script to the page
const loadZendeskScript = () => {
const zenDeskScript = document.createElement("script");
zenDeskScript.id = "ze-snippet";
zenDeskScript.src = "https://static.zdassets.com/ekr/snippet.js?key=HERE_YOU_INSERT_YOUR_KEY";
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] || document.getElementsByTagName('script')[0].parentNode).insertBefore(zenDeskScript, null);
};
// a poller that waits for a condition and executes a callback
const poller = (comparison, callback, timerStep = 250, maxTime = 5000) => {
// why setTimeout instead of setInterval
// https://stackoverflow.com/questions/8682622/using-setinterval-to-do-simplistic-continuous-polling
let currTime = 0;
const checkCondition = () => {
// `comparison` is a function so the condition is always up-to-date
if (comparison() === true) {
callback();
} else if (currTime <= maxTime) {
currTime += timerStep;
setTimeout(checkCondition, timerStep);
}
};
checkCondition(); // calling the function
};
// load the script and execute a callback if provided
const loadZendeskChat = callback => {
loadZendeskScript();
if (callback) {
callback();
}
};
// this function opens the chat
const openZendeskChat = () => {
poller(
() => {
// check that zendesk-related functions are available
return typeof zE !== 'undefined';
},
() => {
// open the widget
zE('webWidget', 'open');
poller(
() => {
// check that the elements exist and that the opacity is already set to "1"
const launcher = document.querySelector('#launcher');
const webWidget = document.querySelector('#webWidget');
return launcher !== null && webWidget !== null && webWidget.style.opacity === '1';
},
() => {
// hide the fake button
zendeskButton.style.opacity = '0';
// save in localStorage
localStorage.setItem('zd_hasOpened', 'true');
}
);
}
);
};
// zendesk management
if (localStorage.getItem('zd_hasOpened')) {
// load the zendesk widget if we find that it was opened
loadZendeskChat();
} else {
// show the fake button if it's the first time it shows
zendeskButton.style.opacity = '1';
}
// This will run when the .zendesk-button element is clicked
zendeskButton.addEventListener('click', () => {
// add a 'Loading' text to the button, as the widget will take some time to load (between 1 and 2 seconds on my laptop)
zendeskButton.querySelector('.text').innerHTML = 'Loading';
// load the zendesk widget
// open the widget and hide the fake button
loadZendeskChat(openZendeskChat);
});
Что касается стилей, я в значительной степени скопировал стиль исходного виджета, преобразовав ems в пиксели, но одну часть, которую я хотел бы выделить, — это стиль фокуса, потому что, по моему мнению, он помогает сообщить пользователю, что что-то происходит.
.zendesk-button:focus {
outline: none;
box-shadow: inset 0 0 0 0.21429rem rgb(255 255 255 / 40%) !important;
}
person
Giorgio Tempesta
schedule
19.04.2021