整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          十天搭建前端監(jiān)控系統(tǒng)(四) Js監(jiān)控img、css、js文件加載失敗

          控系統(tǒng)首頁

          靜態(tài)資源加載失敗導致的問題

          靜態(tài)資源加載失敗的時候,會有哪些問題會出現呢。資源加載失敗會直接造成白屏頁面渲染不全、頁面卡死、樣式錯亂、圖片無法顯示等等。而且這些都是很難復現的錯誤,那么這時候就會有小伙伴得意地說 “你不能復現,我就無法解決啊”,留下測試的小伙伴在那里一臉懵逼。嗯,真是甩的一口好鍋,當然,這也不一定就是你的鍋。

          資源加載失敗的問題解決難度大

          靜態(tài)資源加載錯誤,對有些前端小伙伴來說可能還是有些陌生的。因為這個問題大部分出現在線上環(huán)境,本地環(huán)境也會出現,只不過你的網絡一般比較好,沒事再來個強制刷新,基本上就解決了。所以你可能不會注意到這個問題。它不易發(fā)生,也不易發(fā)現,一旦發(fā)生,頁面應該就直接歇菜了。由于這種問題經常發(fā)生在生產環(huán)境,很難被大家注意到,被發(fā)現了之后也不容易復現,所以無形中就增加了它的解決難度

          資源加載失敗的情況有哪些

          舉一個比較常見的例子:大家應該都用過Jquery.js(下面簡稱Jq),他們的官網上也提供了一個CDN的地址,專門供用戶使用的。可是用過的小伙伴應該都知道,加了他們的CDN以后,整個項目都不好了,慢,但是慢得很特別,也就是特別的慢 。為啥啊?因為你既然是基于Jq,那你就得等人家加載完啊,要是你的網絡再差點,就有可能出現靜態(tài)資源加載失敗的情況,那么你的頁面基本上就很難呈現給用戶了,我相信用過的小伙伴都會有過這種感覺。

          還有一些比較常見的問題:比如阿里云的CDN、微信的SDK、等等一些依賴第三方js的情況下都會出現。什么?你沒遇到過?你沒監(jiān)控過,又怎么會遇到呢。

          本文由 www.webfunny.cn 前端監(jiān)控提供;只需要簡單幾步就可以搭建一套屬于自己的前端監(jiān)控系統(tǒng),快來試試吧(記得收藏哦)。

          哈哈,扯了這么多,進入正題吧,先看看我們監(jiān)控的效果。

          靜態(tài)資源監(jiān)控總覽

          雖然靜態(tài)資源加載失敗的時候會造成如此嚴重的問題,但是我們卻沒有一個特別好用的API來幫我們捕獲這種錯誤,手動表示一下無奈。 ╮(╯▽╰)╭

          方法一:Object.onerror定義指定對象資源加載錯誤時的回調函數,說實話,不好用,因為太麻煩了。

          方法二:利用 performance.getEntries()方法,獲取到所有加載成功的資源列表,在onload事件中遍歷出所有頁面資源集合,利用排除法,到所有集合中過濾掉成功的資源列表,即為加載失敗的資源。 此方法看似合理,也確實能夠排查出加載失敗的靜態(tài)資源,但是檢查的時機很難掌握,另外,如果遇到異步加載的javascript(下面簡稱js)文件也就歇菜了,不好用。

          方法三:通過window.addEventListener來實現,這個方法會監(jiān)控到很多的error, 所以我們要從中篩選出靜態(tài)資源加載報錯的error, 代碼如下:

          window.addEventListener('error',function(e){  
            // 你的邏輯代碼 
          }, true);

          了解線上項目的報錯趨勢

          實時報錯趨勢和評分

          首先,我們需要有個報錯趨勢總覽的功能,報錯趨勢圖中添加了對7天前,同一時間段的數據做了對比,可以作為參考。另外,我們還需要一個警報系統(tǒng),這樣,我們就能夠實時掌握線上項目的健康狀況了。最后,我加了評分功能,輔助我們對項目健康狀況的判斷。

          靜態(tài)資源加載失敗的分類聚合

          分類聚合的結果

          其實靜態(tài)資源析到這里,基本上也就完結了。因為靜態(tài)資源加載不出來一般都是第三方,運營商和網絡的問題,這些都是非我們力所能及的因素,失敗就是失敗,沒必要分析個所以然出來了。

          解決方案

          如果是第三方服務商(比如CDN),那你需要想個辦法在兩個CDN之間做靈活切換,或者加上你們自己的服務器做三方切換,提高容錯率。

          如果是網絡問題,就只能提示用戶去網絡好點的地方了,既然能監(jiān)控,那提示的時機也就容易掌握了。

          如果是運營商的問題,(⊙o⊙)…,啊... 嗯...

          lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

          <html xmlns="http://www.w3.org/1999/xhtml">

          <head>

          <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

          <title>網站頁面</title>

          <style type="text/css">

          * {

          margin: 0px;

          padding: 0px;

          border-top-width: 0px;

          border-right-width: 0px;

          border-bottom-width: 0px;

          border-left-width: 0px;

          }

          body {

          background-color: #FFFFFF;

          text-align: center;

          font-family: "宋體";

          font-size: 12px;

          color: #575757;

          }

          #banner {

          height: 210px;

          width: 982px;

          margin: 0 auto;

          }

          #menu {

          height: 87px;

          width: 982px;

          margin: 0 auto;

          }

          </style>

          </head>

          <body>

          <div id="box">

          <div id="banner"><img src="images/203.jpg" width="982" height="210" alt="banner" /></div>

          <div id="menu"><img src="images/204.jpg" width="223" height="80" alt="gamestart" />

          <img src="images/205.jpg" width="106" height="80" alt="menu1" />

          <img src="images/206.jpg" width="102" height="80" alt="menu2" />

          <img src="images/207.jpg" width="105" height="80" alt="menu3" />

          <img src="images/208.jpg" width="100" height="80" alt="menu4" />

          <img src="images/209.jpg" width="77" height="80" alt="menu5" />

          <img src="images/210.jpg" width="86" height="80" alt="menu6" />

          <img src="images/211.jpg" width="77" height="80" alt="menu7" />

          <img src="images/212.jpg" width="106" height="80" alt="menu8" /></div>

          </div>

          </body>

          </html>

          根據我們的案例,邊框、邊界、邊距都設置成0了,圖片與圖片之間還是有空隙,這是為什么呢?

          記得之前解決的方法是,img標簽符之間不要有空格或者回車。

          就是寫成這樣的

          還有些其他的方法,可以讓其在水平方向上不留下空隙,也就是左右的空隙,比如

          #menu { font-size:0;} //意思是父級元素的字體大小為0,img默認是根據父元素的baseline進行對齊的,把父元素的字體大小設置為0,就沒有空隙了,作為子元素的img對齊相應的也就沒有空隙了

          #menu {letter-spacing:-600px}

          OM to Image

          dom-to-image是一個js庫,可以將任意dom節(jié)點轉換為矢量(SVG)或光柵(PNG或JPEG)圖像。

          安裝

          npm install dom-to-image -S

          加載

          /* in ES 6 */
          import domtoimage from 'dom-to-image';
          /* in ES 5 */
          var domtoimage = require('dom-to-image');

          用法

          所有高階函數都接受DOM節(jié)點和渲染選項options ,并返回promises。

          1. 獲取PNG圖像base64編碼的data URL:
          <div id="my-node"></div>
          var node = document.getElementById('my-node');
          // options 可不傳
          var options = {}  
          domtoimage.toPng(node, options)
              .then(function (dataUrl) {
                  var img = new Image();
                  img.src = dataUrl;
                  document.body.appendChild(img);
              })
              .catch(function (error) {
                  console.error('oops, something went wrong!', error);
              });
          1. 獲取圖像blob:
          domtoimage.toBlob(document.getElementById('my-node'))
              .then(function (blob) { 
                  console.log('blob', blob)
              });
          1. 獲取JPEG圖像base64編碼的data URL并下載:
          domtoimage.toJpeg(document.getElementById('my-node'), { quality: 0.95 })
              .then(function (dataUrl) {
                  var link = document.createElement('a');
                  link.download = 'my-image-name.jpeg';
                  link.href = dataUrl;
                  link.click();
          });
          1. 獲取SVGdata URL,但篩選出所有元素:
          function filter (node) {
              return (node.tagName !== 'i');
          }
           
          domtoimage.toSvg(document.getElementById('my-node'), {filter: filter})
              .then(function (dataUrl) {
                  /* do something */
          });
          1. 以uint8數組的形式獲取原始像素數據,每4個數組元素表示一個像素的RGBA數據:
          var node = document.getElementById('my-node');
           
          domtoimage.toPixelData(node)
              .then(function (pixels) {
                  for (var y = 0; y < node.scrollHeight; ++y) {
                    for (var x = 0; x < node.scrollWidth; ++x) {
                      pixelAtXYOffset = (4 * y * node.scrollHeight) + (4 * x);
                      /* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */
                      pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
                    }
                  }
              });

          options參數

          Name

          類型

          Default

          Description

          filter

          Function

          ——

          以DOM節(jié)點為參數的函數。如果傳遞的節(jié)點應包含在輸出中,則應返回true(排除節(jié)點意味著也排除其子節(jié)點)

          bgcolor

          String

          ——

          背景色的字符串值,任何有效的CSS顏色值。

          height

          Number

          ——

          渲染前應用于節(jié)點的高度(以像素為單位)。

          width

          Number

          ——

          渲染前應用于節(jié)點的寬度(以像素為單位)。

          style

          Object

          ——

          object對象,其屬性在渲染之前要復制到節(jié)點的樣式中。

          quality

          Number

          1.0

          介于0和1之間的數字,表示JPEG圖像的圖像質量(例如0.92=>92%)。默認值為1.0(100%)

          cacheBust

          Boolean

          false

          設置為true可將當前時間作為查詢字符串附加到URL請求以啟用清除緩存。

          imagePlaceholder

          Boolean

          undefined

          獲取圖片失敗時使用圖片的數據URL作為占位符。默認為未定義,并將在失敗的圖像上引發(fā)錯誤。

          原理

          dom-to-image使用SVG的一個特性,它允許在標記中包含任意HTML內容。

          • 遞歸地克隆原始DOM節(jié)點
          • 計算節(jié)點和每個子節(jié)點的樣式,并將其復制到相應的克隆 創(chuàng)建偽元素,因為它們不是以任何方式克隆的
          • 嵌入web字體 查找所有@font face聲明的web字體 解析文件URL,下載相應文件 base64編碼的內聯(lián)作為data:URLs 將所有已處理的CSS放入中,然后將其附加到克隆
          • 嵌入圖片 在嵌入圖片URL 使用backgroundCSS屬性的圖片,方法類似于字體
          • 將克隆的節(jié)點序列化為XML
          • 將XML包裝到標記中,然后包裝到SVG中,然后使其成為data URL
          • 或者,要以Uint8Array的形式獲取PNG內容或原始像素數據,可以創(chuàng)建一個以SVG為源的圖像元素,并將其呈現在已經創(chuàng)建的canvas上,從canvas讀取內容

          部分源碼分析

          dom-to-image.js

          // Default impl options
          var defaultOptions = {
              // Default is to fail on error, no placeholder
              imagePlaceholder: undefined,
              // Default cache bust is false, it will use the cache
              cacheBust: false
          };
          
          var domtoimage = {
              toSvg: toSvg,
              toPng: toPng,
              toJpeg: toJpeg,
              toBlob: toBlob,
              toPixelData: toPixelData,
              impl: {
                  fontFaces: fontFaces,
                  images: images,
                  util: util,
                  inliner: inliner,
                  options: {}
              }
          };
          
          if (typeof module !== 'undefined')
              module.exports = domtoimage;
          else
              global.domtoimage = domtoimage;
          • defaultOptions設置默認options選項
          • domtoimage的核心api:
            • toSvg
            • toPng
            • toJpeg
            • toBlob
            • toPixelData
          • 例:toJpeg:將draw函數返回的canvas實例,使用canvas的toDataURL方法生成jpeg圖片。toSvg函數將遞歸地克隆原始DOM節(jié)點, 將克隆的節(jié)點序列化為XML,將XML包裝到標記中,然后包裝到SVG中,然后使其轉成dataURL。
          function toJpeg(node, options) {
             options = options || {};
             return draw(node, options)
                 .then(function (canvas) {
                     return canvas.toDataURL('image/jpeg', options.quality || 1.0);
                 });
          }
          復制代碼
          function draw(domNode, options) {
              return toSvg(domNode, options)
                  .then(util.makeImage)
                  .then(util.delay(100))
                  .then(function (image) {
                      var canvas = newCanvas(domNode);
                      canvas.getContext('2d').drawImage(image, 0, 0);
                      return canvas;
                  });
          
              function newCanvas(domNode) {
                  var canvas = document.createElement('canvas');
                  canvas.width = options.width || util.width(domNode);
                  canvas.height = options.height || util.height(domNode);
          
                  if (options.bgcolor) {
                      var ctx = canvas.getContext('2d');
                      ctx.fillStyle = options.bgcolor;
                      ctx.fillRect(0, 0, canvas.width, canvas.height);
                  }
          
                  return canvas;
              }
          }
          function toSvg(node, options) {
              options = options || {};
              copyOptions(options);
              return Promise.resolve(node)
                  .then(function (node) {
                      return cloneNode(node, options.filter, true);
                  })
                  .then(embedFonts)
                  .then(inlineImages)
                  .then(applyOptions)
                  .then(function (clone) {
                      return makeSvgDataUri(clone,
                          options.width || util.width(node),
                          options.height || util.height(node)
                      );
                  });
          
              function applyOptions(clone) {
                  if (options.bgcolor) clone.style.backgroundColor = options.bgcolor;
          
                  if (options.width) clone.style.width = options.width + 'px';
                  if (options.height) clone.style.height = options.height + 'px';
          
                  if (options.style)
                      Object.keys(options.style).forEach(function (property) {
                          clone.style[property] = options.style[property];
                      });
          
                  return clone;
              }
          }


          作者:知其
          https://juejin.cn/post/6988045156473634852


          主站蜘蛛池模板: 日韩精品乱码AV一区二区| 红桃AV一区二区三区在线无码AV| 亚洲一区二区三区国产精品| 亚洲视频一区在线| 久久久人妻精品无码一区| 色狠狠AV一区二区三区| 中文字幕一区二区三区四区| 国产精品亚洲一区二区三区在线观看| 精品一区二区三区在线成人| 成人免费av一区二区三区| 日本一区二区在线不卡| 夜精品a一区二区三区| 国产91精品一区二区麻豆网站| 国产精品无圣光一区二区 | 久久婷婷色一区二区三区| 夜夜爽一区二区三区精品| 视频一区视频二区在线观看| 日韩福利视频一区| 天天视频一区二区三区| 国产高清一区二区三区视频| 天堂va视频一区二区| 国产一区二区三区电影| 日本精品视频一区二区三区| 日韩一区二区三区电影在线观看 | 精品无码成人片一区二区98| 中文字幕人妻丝袜乱一区三区| 夜夜爽一区二区三区精品| 亚洲第一区在线观看| 精品福利一区3d动漫| 精品乱码一区二区三区在线 | 3d动漫精品成人一区二区三| 国产精品丝袜一区二区三区 | 精品欧美一区二区在线观看| 日韩少妇无码一区二区三区| 四虎永久在线精品免费一区二区 | 无码一区二区三区亚洲人妻 | 无码人妻精品一区二区三区久久久| 人妻少妇精品视频一区二区三区 | 在线视频亚洲一区| 国产一区二区三区在线观看免费| 一区二区三区四区在线视频|