最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Reduce the impact of third-party code (zendesk) - Stack Overflow

programmeradmin2浏览0评论

<script
  id="ze-snippet"
  src=".js?key=some_zendesk_key"
/>

I'm trying to optimize my web site performance. I've faced a big impact of third-party code to my performance, I think all my bundle has a lower size than zendesk code. How can I load it without impacting on the main thread? Should I use the async or defer tags? Or which approach is better for this case?

<script
  id="ze-snippet"
  src="https://static.zdassets./ekr/snippet.js?key=some_zendesk_key"
/>

I'm trying to optimize my web site performance. I've faced a big impact of third-party code to my performance, I think all my bundle has a lower size than zendesk code. How can I load it without impacting on the main thread? Should I use the async or defer tags? Or which approach is better for this case?

Share Improve this question edited Oct 8, 2020 at 15:21 Giorgio Tempesta 2,0591 gold badge26 silver badges38 bronze badges asked Oct 20, 2019 at 8:23 Andrii RadkevychAndrii Radkevych 3,4527 gold badges35 silver badges65 bronze badges 2
  • IIRC, I have tried using async tags in my development with the Zendesk Chat, and it just causes so many problems. I've basically e to the conclusion that there is no way for this script not to impact your performance because it simply loads so many other scripts. – Bergis Commented Oct 29, 2019 at 16:28
  • Same here. I am loading this script in a react gatsby application. Funny thing is that if you run audits to zendesk., the size is 354 KB and blocking time 638 ms. I get the feeling that audits are too sensitive though, as the real feel of the loading time is actually good. – itdoesntwork Commented May 11, 2020 at 12:38
Add a ment  | 

3 Answers 3

Reset to default 1

This seems to be an issue that tortures so many people without a clear solution.

What I managed to do it to reduce the block time by adding this configuration.

window.zESettings = {
    webWidget: {
      chat: {
        connectOnPageLoad: false
      }
    }
  };

ref https://developer.zendesk./embeddables/docs/widget/settings#connectonpageload

ps I did a performance test to my zendesk helpdesk "domain.zendesk." and the results there were even worse

I came across this issue recently and made this hack using a function for loading the zendesk script only when you reached certain point of the doc. I know is kind of dirty but it works:

<script defer type="text/javascript">
    (function($, win) {
        $.fn.inViewport = function(cb) {
            return this.each(function(i,el){
                function visPx(){
                    var H = $(this).height(),
                    r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
                    return cb.call(el, Math.max(0, t>0? H-t : (b<H?b:H)));  
                }  visPx();
                $(win).on("resize scroll", visPx);
            });
        };
    }(jQuery, window));


$('#trigger_div').inViewport(function(px){
    if(px) {

    //zopim code

    }
});

Starting from this article https://www.newmediacampaigns./blog/maintaining-great-site-performanc-using-zendesk-web-widget I have implemented a solution that significantly reduces the load time by at least 3 seconds (in Google Lighthouse).

I have created a fake button in the HTML that will load the Zendesk script and open the widget when clicked. It will also load a localStorage item that will prevent this from happening on subsequent page loads.

⚠️ Warning:

The code relies heavily on how the widget is currently implemented (for example it expects a #launcher and a #webWidget element to appear on the page), so it can break as soon as the original code changes, but at least we will have an improvement in the loading times until they fix it.

Here is the most important part of the code:

HTML Button

<button class="zendesk-button">
  <span class="left-icon">
    <!-- here you insert the icon -->
  </span>
  <span class="text">Chat</span>
</button>

JavaScript code

// 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./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 = (parison, callback, timerStep = 250, maxTime = 5000) => {
  // why setTimeout instead of setInterval
  // https://stackoverflow./questions/8682622/using-setinterval-to-do-simplistic-continuous-polling
  let currTime = 0;
  const checkCondition = () => {
    // `parison` is a function so the condition is always up-to-date
    if (parison() === 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);
});

Regarding styles, I have pretty much copied the style in the original widget, converting ems to pixels, but one part I'd like to highlight is the focus style, because in my opinion it helps telling the user that something is happening.

.zendesk-button:focus {
  outline: none;
  box-shadow: inset 0 0 0 0.21429rem rgb(255 255 255 / 40%) !important;
}
发布评论

评论列表(0)

  1. 暂无评论