减少第三方代码的影响(zendesk)

时间:2019-10-20 08:23:16

标签: javascript zendesk lighthouse

enter image description here

Project project = await Task.FromResult(db.Projects
    .Include(p => p.ProjectOwner)
    .Include(p => p.ChildProjects)
        .ThenInclude(o => o.ProjectOwner)
    .AsEnumerable().Where(p => p.Id == id)
    .ToList().FirstOrDefault());

我尝试优化网站性能。我面临着三十个部分的代码对我的性能的巨大影响,我认为我所有的捆绑包的大小都比zendesk代码小。如何在不影响主线程的情况下加载它?我应该使用 <script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=some_zendesk_key" /> 标签中的async吗?或者哪种方法更适合这种情况?

3 个答案:

答案 0 :(得分:1)

我最近遇到了这个问题,并使用仅在到达文档的特定点时才加载zendesk脚本的功能来进行此破解。我知道有点脏,但是可以用:

<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

    }
});

答案 1 :(得分:0)

这似乎是一个困扰着许多人而没有明确解决方案的问题。

我设法通过添加此配置来减少阻止时间。

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

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

ps 我对zendesk服务台“ domain.zendesk.com”进行了性能测试,结果甚至更糟

enter image description here

答案 2 :(得分:0)

从这篇文章开始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);
});

关于样式,我几乎复制了原始小部件中的样式,将 em 转换为像素,但我想强调的部分是焦点样式,因为在我看来它有助于告诉用户正在发生某些事情.

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