整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          Android WebView 致安卓應(yīng)用閃退,看看

          Android WebView 致安卓應(yīng)用閃退,看看如何規(guī)避

          據(jù)外媒 9to5 Google 報道,3 月 23 日幾個小時內(nèi),大量安卓用戶遇到一些安卓應(yīng)用連續(xù)閃退的情況,有人發(fā)現(xiàn)卸載安卓系統(tǒng) WebView 就可以停止閃退。目前,谷歌已經(jīng)發(fā)布了應(yīng)用崩潰問題的永久修復(fù),涉及更新 Android System WebView 和 Chrome 瀏覽器 89.0.4389.105 版本升級。

          實際上,Android 碎片化問題自其誕生之初業(yè)已存在,而且目前看上去并沒有好的解決方案。不同系統(tǒng)、不同廠商中的瀏覽器內(nèi)核同樣存在差異,導(dǎo)致層出不窮的兼容性問題令眾多安卓開發(fā)同學(xué)頭疼不已。

          為了徹底解決并且掌控這些問題,mPaaS 集成獨立的 UC 瀏覽器內(nèi)核,由此針對 WebView 所產(chǎn)生的閃退、卡頓等問題可以被有效收斂,統(tǒng)一管控。同時,根據(jù)眾多業(yè)務(wù)的應(yīng)用和測試,使用 UC 瀏覽器內(nèi)核,瀏覽器相關(guān)的閃退和 ANR(Application Not Respond) 有明顯的下降。

          除此之外,圍繞 WebView 所產(chǎn)生的任何安全問題,mPaaS 可以在第一時間修復(fù)并發(fā)布[1],遠(yuǎn)比廠商升級更有效率。

          除 UC WebView 內(nèi)核之外,mPaaS 同時繼承了支付寶深度應(yīng)用的容器及離線包[2]技術(shù)。

          常規(guī)情況下,在 App 中啟動一個線上頁面,通常會有一個白屏階段,這是瀏覽器需要從服務(wù)器下載 HTML 資源。由于手機網(wǎng)絡(luò)限制,資源加載時間不可控,通常會花費 300ms 以上的實踐,用戶在這個時間段就會看到頁面白屏。

          為了優(yōu)化用戶體驗,減少白屏?xí)r間,支付寶在容器內(nèi)引用了離線包技術(shù)。離線包可以簡單理解為一個 zip 壓縮包,其中包含前端頁面所需的 HTML、CSS、JS、圖片等資源,內(nèi)置到客戶端后,容器打開離線包頁面時會直接從離線包中獲取資源。這個過程僅需毫秒,消除了頁面啟動白屏的問題。

          目前,mPaaS 容器方案支持 HTML5 及小程序。借助離線包能力輕松實現(xiàn)渲染、邏輯、配置等靜態(tài)資源的預(yù)置,擺脫網(wǎng)絡(luò)環(huán)境對頁面加載的影響,提升用戶體驗。

          同時,借助 mPaaS 動態(tài)發(fā)布服務(wù),針對新的產(chǎn)品/業(yè)務(wù)需求,能夠?qū)崿F(xiàn)快速開發(fā),并通過 mPaaS 控制臺即可完成發(fā)布;而終端用戶客戶端中集成的容器 SDK 將自動拉取最新的離線包。這種發(fā)布、更新的過程無需通過應(yīng)用商店審核,最大化提升業(yè)務(wù)迭代效率。


          參考文檔

          [1]mPaaS 動態(tài)發(fā)布產(chǎn)品文檔:https://help.aliyun.com/document_detail/49580.html

          [2]mPaaS H5 容器及離線包產(chǎn)品文檔:https://help.aliyun.com/document_detail/59192.html


          -

          午接手一臺海信TLM26V68液晶電視,上電試機故障白屏!鎖定故障范圍主板及邏輯板!

          大致與用戶說好維修費用等等,動手拆機,上電測試電壓!上屏電壓正常主板上屏驅(qū)動信號電壓正常 排除主板 故障鎖定在邏輯板

          此機邏輯板與屏是一體的,拆卸的注意,直奔DC-DC轉(zhuǎn)換電路(AAT1168B)首先檢查芯片供電是5V正常,在測周邊電壓,首先測后面提升二極管電

          壓,才4V左右電壓明顯不對,該電壓正常為12V,故障的問題應(yīng)該就在這里!斷開提升二極管,測試二極管無漏電與開路,后面也并無短路,漏電!判斷芯片內(nèi)部故障!一次性成功焊接,美中不足的是沒有貼上保護(hù)層,周邊膠殼都給吹翻了

          上電試機故障排除!

          原文:http://www.jdwx.info/thread-633163-1-1.html

          作者:11323211111

          家電維修論壇是專業(yè)的家電維修技術(shù)交流社區(qū),學(xué)習(xí)電子電路基礎(chǔ)知識,分享家電維修技術(shù)資料,交流家電維修技巧經(jīng)驗,獲取更多精彩內(nèi)容請關(guān)注家電維修論壇微信公眾號。

          微信公眾號:jdwxinfo

          升首屏的加載速度,是前端性能優(yōu)化中最重要的環(huán)節(jié),這里筆者梳理出一些 常規(guī)且有效 的首屏優(yōu)化建議

          目標(biāo): 通過對比優(yōu)化前后的性能變化,來驗證方案的有效性,了解并掌握其原理

          1、路由懶加載

          SPA 項目,一個路由對應(yīng)一個頁面,如果不做處理,項目打包后,會把所有頁面打包成一個文件,當(dāng)用戶打開首頁時,會一次性加載所有的資源,造成首頁加載很慢,降低用戶體驗

          列一個實際項目的打包詳情:

          • app.js 初始體積: 1175 KB
          • app.css 初始體積: 274 KB

          將路由全部改成懶加載

          // 通過webpackChunkName設(shè)置分割后代碼塊的名字
          const Home=()=> import(/* webpackChunkName: "home" */ "@/views/home/index.vue");
          const MetricGroup=()=> import(/* webpackChunkName: "metricGroup" */ "@/views/metricGroup/index.vue");
          …………
          const routes=[
              {
                 path: "/",
                 name: "home",
                 component: Home
              },
              {
                 path: "/metricGroup",
                 name: "metricGroup",
                 component: MetricGroup
              },
              …………
           ]
          復(fù)制代碼

          重新打包后,首頁資源拆分為 app.js 和 home.js,以及對應(yīng)的 css 文件

          • app.js:244 KB、 home.js: 35KB
          • app.css:67 KB、home.css: 15KB

          通過路由懶加載,該項目的首頁資源壓縮約 52%

          路由懶加載的原理

          懶加載前提的實現(xiàn):ES6的動態(tài)地加載模塊——import()

          調(diào)用 import() 之處,被作為分離的模塊起點,意思是,被請求的模塊和它引用的所有子模塊,會分離到一個單獨的 chunk 中
          ——摘自《webpack——模塊方法》的import()小節(jié)

          要實現(xiàn)懶加載,就得先將進(jìn)行懶加載的子模塊分離出來,打包成一個單獨的文件

          webpackChunkName 作用是 webpack 在打包的時候,對異步引入的庫代碼(lodash)進(jìn)行代碼分割時,設(shè)置代碼塊的名字。webpack 會將任何一個異步模塊與相同的塊名稱組合到相同的異步塊中

          2、組件懶加載

          除了路由的懶加載外,組件的懶加載在很多場景下也有重要的作用

          舉個:

          home 頁面 和 about 頁面,都引入了 dialogInfo 彈框組件,該彈框不是一進(jìn)入頁面就加載,而是需要用戶手動觸發(fā)后才展示出來

          home 頁面示例:

          <template>
            <div class="homeView">
              <p>home 頁面</p>
              <el-button @click="dialogVisible=!dialogVisible">打開彈框</el-button>
              <dialogInfo v-if="dialogVisible" />
            </div>
          </template>
          <script>
          import dialogInfo from '@/components/dialogInfo';
          export default {
            name: 'homeView',
            components: {
              dialogInfo
            }
          }
          </script>
          復(fù)制代碼

          項目打包后,發(fā)現(xiàn) home.js 和 about.js 均包括了該彈框組件的代碼(在 dist 文件中搜索dialogInfo彈框組件)

          當(dāng)用戶打開 home 頁時,會一次性加載該頁面所有的資源,我們期望的是用戶觸發(fā)按鈕后,再加載該彈框組件的資源

          這種場景下,就很適合用懶加載的方式引入

          彈框組件懶加載:

          <script>
          const dialogInfo=()=> import(/* webpackChunkName: "dialogInfo" */ '@/components/dialogInfo');
          export default {
            name: 'homeView',
            components: {
              dialogInfo
            }
          }
          </script>
          復(fù)制代碼

          重新打包后,home.js 和 about.js 中沒有了彈框組件的代碼,該組件被獨立打包成 dialogInfo.js,當(dāng)用戶點擊按鈕時,才會去加載 dialogInfo.js 和 dialogInfo.css

          最終,使用組件路由懶后,該項目的首頁資源進(jìn)一步減少約 11%

          組件懶加載的使用場景

          有時資源拆分的過細(xì)也不好,可能會造成瀏覽器 http 請求的增多

          總結(jié)出三種適合組件懶加載的場景:

          1)該頁面的 JS 文件體積大,導(dǎo)致頁面打開慢,可以通過組件懶加載進(jìn)行資源拆分,利用瀏覽器并行下載資源,提升下載速度(比如首頁)

          2)該組件不是一進(jìn)入頁面就展示,需要一定條件下才觸發(fā)(比如彈框組件)

          3)該組件復(fù)用性高,很多頁面都有引入,利用組件懶加載抽離出該組件,一方面可以很好利用緩存,同時也可以減少頁面的 JS 文件大?。ū热绫砀窠M件、圖形組件等)

          3、合理使用 Tree shaking

          Tree shaking 的作用:消除無用的 JS 代碼,減少代碼體積

          舉個:

          // util.js
          export function targetType(target) {
            return Object.prototype.toString.call(target).slice(8, -1).toLowerCase();
          }
          export function deepClone(target) {
            return JSON.parse(JSON.stringify(target));
          }
          復(fù)制代碼

          項目中只使用了 targetType 方法,但未使用 deepClone 方法,項目打包后,deepClone 方法不會被打包到項目里

          tree-shaking 原理:

          依賴于ES6的模塊特性,ES6模塊依賴關(guān)系是確定的,和運行時的狀態(tài)無關(guān),可以進(jìn)行可靠的靜態(tài)分析,這就是 tree-shaking 的基礎(chǔ)

          靜態(tài)分析就是不需要執(zhí)行代碼,就可以從字面量上對代碼進(jìn)行分析。ES6之前的模塊化,比如 CommonJS 是動態(tài)加載,只有執(zhí)行后才知道引用的什么模塊,就不能通過靜態(tài)分析去做優(yōu)化,正是基于這個基礎(chǔ)上,才使得 tree-shaking 成為可能

          Tree shaking 并不是萬能的

          并不是說所有無用的代碼都可以被消除,還是上面的代碼,換個寫法 tree-shaking 就失效了

          // util.js
          export default {
            targetType(target) {
              return Object.prototype.toString.call(target).slice(8, -1).toLowerCase();
            },
            deepClone(target) {
              return JSON.parse(JSON.stringify(target));
            }
          };
          
          // 引入并使用
          import util from '../util';
          util.targetType(null)
          復(fù)制代碼

          同樣的,項目中只使用了 targetType 方法,未使用 deepClone 方法,項目打包后,deepClone 方法還是被打包到項目里

          在 dist 文件中搜索 deepClone 方法:

          究其原因,export default 導(dǎo)出的是一個對象,無法通過靜態(tài)分析判斷出一個對象的哪些變量未被使用,所以 tree-shaking 只對使用 export 導(dǎo)出的變量生效

          這也是函數(shù)式編程越來越火的原因,因為可以很好利用 tree-shaking 精簡項目的體積,也是 vue3 全面擁抱了函數(shù)式編程的原因之一

          4、骨架屏優(yōu)化白屏?xí)r長

          使用骨架屏,可以縮短白屏?xí)r間,提升用戶體驗。國內(nèi)大多數(shù)的主流網(wǎng)站都使用了骨架屏,特別是手機端的項目

          SPA 單頁應(yīng)用,無論 vue 還是 react,最初的 html 都是空白的,需要通過加載 JS 將內(nèi)容掛載到根節(jié)點上,這套機制的副作用:會造成長時間的白屏

          常見的骨架屏插件就是基于這種原理,在項目打包時將骨架屏的內(nèi)容直接放到 html 文件的根節(jié)點中

          使用骨架屏插件,打包后的 html 文件(根節(jié)點內(nèi)部為骨架屏):

          同一項目,對比使用骨架屏前后的 FP 白屏?xí)r間:

          • 無骨架屏:白屏?xí)r間 1063ms
          • 有骨架屏:白屏?xí)r間 144ms

          骨架屏確實是優(yōu)化白屏的不二選擇,白屏?xí)r間縮短了 86%

          骨架屏插件

          這里以 vue-skeleton-webpack-plugin 插件為例,該插件的亮點是可以給不同的頁面設(shè)置不同的骨架屏,這點確實很酷

          1)安裝

          npm i vue-skeleton-webpack-plugin 
          復(fù)制代碼

          2)vue.config.js 配置

          // 骨架屏
          const SkeletonWebpackPlugin=require("vue-skeleton-webpack-plugin");
          module.exports={
             configureWebpack: {
                plugins: [
                 new SkeletonWebpackPlugin({
                  // 實例化插件對象
                  webpackConfig: {
                    entry: {
                      app: path.join(__dirname, './src/skeleton.js') // 引入骨架屏入口文件
                    }
                  },
                  minimize: true, // SPA 下是否需要壓縮注入 HTML 的 JS 代碼
                  quiet: true, // 在服務(wù)端渲染時是否需要輸出信息到控制臺
                  router: {
                    mode: 'hash', // 路由模式
                    routes: [
                      // 不同頁面可以配置不同骨架屏
                      // 對應(yīng)路徑所需要的骨架屏組件id,id的定義在入口文件內(nèi)
                      { path: /^\/home(?:\/)?/i, skeletonId: 'homeSkeleton' },
                      { path: /^\/detail(?:\/)?/i, skeletonId: 'detailSkeleton' }
                    ]
                  }
                })        
                ]
             }
          }
          復(fù)制代碼

          3)新建 skeleton.js 入口文件

          // skeleton.js
          import Vue from "vue";
          // 引入對應(yīng)的骨架屏頁面
          import homeSkeleton from "./views/homeSkeleton";
          import detailSkeleton from "./views/detailSkeleton";
          
          export default new Vue({
              components: {
                  homeSkeleton,
                  detailSkeleton,
              },
              template: `
              <div>
                <homeSkeleton id="homeSkeleton" style="display:none;" />
                <detailSkeleton id="detailSkeleton" style="display:none;" />
              </div>
            `,
          });
          復(fù)制代碼

          5、長列表虛擬滾動

          首頁中不乏有需要渲染長列表的場景,當(dāng)渲染條數(shù)過多時,所需要的渲染時間會很長,滾動時還會造成頁面卡頓,整體體驗非常不好

          虛擬滾動——指的是只渲染可視區(qū)域的列表項,非可見區(qū)域的不渲染,在滾動時動態(tài)更新可視區(qū)域,該方案在優(yōu)化大量數(shù)據(jù)渲染時效果是很明顯的

          虛擬滾動圖例:

          虛擬滾動基本原理:

          計算出 totalHeight 列表總高度,并在觸發(fā)時滾動事件時根據(jù) scrollTop 值不斷更新 startIndex 以及 endIndex ,以此從列表數(shù)據(jù) listData 中截取對應(yīng)元素

          虛擬滾動性能對比:

          • 在不使用虛擬滾動的情況下,渲染10萬個文本節(jié)點:
          • 使用虛擬滾動的情況后:

          使用虛擬滾動使性能提升了 78%

          虛擬滾動插件

          虛擬滾動的插件有很多,比如 vue-virtual-scroller、vue-virtual-scroll-list、react-tiny-virtual-list、react-virtualized 等

          這里簡單介紹 vue-virtual-scroller 的使用

          // 安裝插件
          npm install vue-virtual-scroller
          
          // main.js
          import VueVirtualScroller from 'vue-virtual-scroller'
          import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
          
          Vue.use(VueVirtualScroller)
          
          // 使用
          <template> 
            <RecycleScroller 
              class="scroller" 
              :items="list" 
              :item-size="32" 
              key-field="id" 
              v-slot="{ item }"> 
                <div class="user"> {{ item.name }} </div>
            </RecycleScroller> 
          </template>
          復(fù)制代碼

          該插件主要有 RecycleScroller.vue、DynamicScroller.vue 這兩個組件,其中 RecycleScroller 需要 item 的高度為靜態(tài)的,也就是列表每個 item 的高度都是一致的,而 DynamicScroller 可以兼容 item 的高度為動態(tài)的情況

          6、Web Worker 優(yōu)化長任務(wù)

          由于瀏覽器 GUI 渲染線程與 JS 引擎線程是互斥的關(guān)系,當(dāng)頁面中有很多長任務(wù)時,會造成頁面 UI 阻塞,出現(xiàn)界面卡頓、掉幀等情況

          查看頁面的長任務(wù):

          打開控制臺,選擇 Performance 工具,點擊 Start 按鈕,展開 Main 選項,會發(fā)現(xiàn)有很多紅色的三角,這些就屬于長任務(wù)(長任務(wù):執(zhí)行時間超過50ms的任務(wù))

          測試實驗:

          如果直接把下面這段代碼直接丟到主線程中,計算過程中頁面一直處于卡死狀態(tài),無法操作

          let sum=0;
          for (let i=0; i < 200000; i++) {
              for (let i=0; i < 10000; i++) {
                sum +=Math.random()
              }
            }
          復(fù)制代碼

          使用 Web Worker 執(zhí)行上述代碼時,計算過程中頁面正??刹僮鳌o卡頓

          // worker.js
          onmessage=function (e) {
            // onmessage獲取傳入的初始值
            let sum=e.data;
            for (let i=0; i < 200000; i++) {
              for (let i=0; i < 10000; i++) {
                sum +=Math.random()
              }
            }
            // 將計算的結(jié)果傳遞出去
            postMessage(sum);
          }
          復(fù)制代碼

          Web Worker 具體的使用與案例,詳情見 一文徹底了解Web Worker,十萬、百萬條數(shù)據(jù)都是弟弟

          Web Worker 的通信時長

          并不是執(zhí)行時間超過 50ms 的任務(wù),就可以使用 Web Worker,還要先考慮通信時長的問題

          假如一個運算執(zhí)行時長為 100ms,但是通信時長為 300ms, 用了 Web Worker可能會更慢

          比如新建一個 web worker, 瀏覽器會加載對應(yīng)的 worker.js 資源,下圖中的 Time 是這個資源的通信時長(也叫加載時長)

          當(dāng)任務(wù)的運算時長 - 通信時長 > 50ms,推薦使用Web Worker

          7、requestAnimationFrame 制作動畫

          requestAnimationFrame 是瀏覽器專門為動畫提供的 API,它的刷新頻率與顯示器的頻率保持一致,使用該 api 可以解決用 setTimeout/setInterval 制作動畫卡頓的情況

          下面的案例演示了兩者制作進(jìn)度條的對比(運行按鈕可點擊)

          可以看到使用定時器制作的動畫,卡頓還是比較明顯的

          setTimeout/setInterval、requestAnimationFrame 三者的區(qū)別:

          1)引擎層面

          setTimeout/setInterval 屬于 JS引擎,requestAnimationFrame 屬于 GUI引擎

          JS引擎與GUI引擎是互斥的,也就是說 GUI 引擎在渲染時會阻塞 JS 引擎的計算

          2)時間是否準(zhǔn)確

          requestAnimationFrame 刷新頻率是固定且準(zhǔn)確的,但 setTimeout/setInterval 是宏任務(wù),根據(jù)事件輪詢機制,其他任務(wù)會阻塞或延遲js任務(wù)的執(zhí)行,會出現(xiàn)定時器不準(zhǔn)的情況

          3)性能層面

          當(dāng)頁面被隱藏或最小化時,setTimeout/setInterval 定時器仍會在后臺執(zhí)行動畫任務(wù),而使用 requestAnimationFrame 當(dāng)頁面處于未激活的狀態(tài)下,屏幕刷新任務(wù)會被系統(tǒng)暫停

          8、JS 的6種加載方式

          1)正常模式

          <script src="index.js"></script>
          復(fù)制代碼

          這種情況下 JS 會阻塞 dom 渲染,瀏覽器必須等待 index.js 加載和執(zhí)行完成后才能去做其它事情

          2)async 模式

          <script async src="index.js"></script>
          復(fù)制代碼

          async 模式下,它的加載是異步的,JS 不會阻塞 DOM 的渲染,async 加載是無順序的,當(dāng)它加載結(jié)束,JS 會立即執(zhí)行

          使用場景:若該 JS 資源與 DOM 元素沒有依賴關(guān)系,也不會產(chǎn)生其他資源所需要的數(shù)據(jù)時,可以使用async 模式,比如埋點統(tǒng)計

          3)defer 模式

          <script defer src="index.js"></script>
          復(fù)制代碼

          defer 模式下,JS 的加載也是異步的,defer 資源會在 DOMContentLoaded 執(zhí)行之前,并且 defer 是有順序的加載

          如果有多個設(shè)置了 defer 的 script 標(biāo)簽存在,則會按照引入的前后順序執(zhí)行,即便是后面的 script 資源先返回

          所以 defer 可以用來控制 JS 文件的執(zhí)行順序,比如 element-ui.js 和 vue.js,因為 element-ui.js 依賴于 vue,所以必須先引入 vue.js,再引入 element-ui.js

          <script defer src="vue.js"></script>
          <script defer src="element-ui.js"></script>
          復(fù)制代碼

          defer 使用場景:一般情況下都可以使用 defer,特別是需要控制資源加載順序時

          4)module 模式

          <script type="module">import { a } from './a.js'</script>
          復(fù)制代碼

          在主流的現(xiàn)代瀏覽器中,script 標(biāo)簽的屬性可以加上 type="module",瀏覽器會對其內(nèi)部的 import 引用發(fā)起 HTTP 請求,獲取模塊內(nèi)容。這時 script 的行為會像是 defer 一樣,在后臺下載,并且等待 DOM 解析

          Vite 就是利用瀏覽器支持原生的 es module 模塊,開發(fā)時跳過打包的過程,提升編譯效率

          5) preload

          <link rel="preload" as="script" href="index.js">
          復(fù)制代碼

          link 標(biāo)簽的 preload 屬性:用于提前加載一些需要的依賴,這些資源會優(yōu)先加載(如下圖紅框)

          vue2 項目打包生成的 index.html 文件,會自動給首頁所需要的資源,全部添加 preload,實現(xiàn)關(guān)鍵資源的提前加載

          preload 特點:

          1)preload 加載的資源是在瀏覽器渲染機制之前進(jìn)行處理的,并且不會阻塞 onload 事件;

          2)preload 加載的 JS 腳本其加載和執(zhí)行的過程是分離的,即 preload 會預(yù)加載相應(yīng)的腳本代碼,待到需要時自行調(diào)用;

          6)prefetch

          <link rel="prefetch" as="script" href="index.js">
          復(fù)制代碼

          prefetch 是利用瀏覽器的空閑時間,加載頁面將來可能用到的資源的一種機制;通常可以用于加載其他頁面(非首頁)所需要的資源,以便加快后續(xù)頁面的打開速度

          prefetch 特點:

          1)pretch 加載的資源可以獲取非當(dāng)前頁面所需要的資源,并且將其放入緩存至少5分鐘(無論資源是否可以緩存)

          2)當(dāng)頁面跳轉(zhuǎn)時,未完成的 prefetch 請求不會被中斷

          加載方式總結(jié)

          async、defer 是 script 標(biāo)簽的專屬屬性,對于網(wǎng)頁中的其他資源,可以通過 link 的 preload、prefetch 屬性來預(yù)加載

          如今現(xiàn)代框架已經(jīng)將 preload、prefetch 添加到打包流程中了,通過靈活的配置,去使用這些預(yù)加載功能,同時我們也可以審時度勢地向 script 標(biāo)簽添加 async、defer 屬性去處理資源,這樣可以顯著提升性能

          9、圖片的優(yōu)化

          平常大部分性能優(yōu)化工作都集中在 JS 方面,但圖片也是頁面上非常重要的部分

          特別是對于移動端來說,完全沒有必要去加載原圖,浪費帶寬。如何去壓縮圖片,讓圖片更快的展示出來,有很多優(yōu)化工作可以做

          淘寶首頁的圖片資源都很?。?/p>

          圖片的動態(tài)裁剪

          很多云服務(wù),比如阿里云或七牛云,都提供了圖片的動態(tài)裁剪功能,效果很棒,確實是錢沒有白花

          只需在圖片的url地址上動態(tài)添加參數(shù),就可以得到你所需要的尺寸大小,比如:http://7xkv1q.com1.z0.glb.clouddn.com/grape.jpg?imageView2/1/w/200/h/200

          圖片瘦身前后對比:

          • 原圖:1.8M
          • 裁剪后:12.8KB

          經(jīng)過動態(tài)裁剪后的圖片,加載速度會有非常明顯的提升

          圖片的懶加載

          對于一些圖片量比較大的首頁,用戶打開頁面后,只需要呈現(xiàn)出在屏幕可視區(qū)域內(nèi)的圖片,當(dāng)用戶滑動頁面時,再去加載出現(xiàn)在屏幕內(nèi)的圖片,以優(yōu)化圖片的加載效果

          圖片懶加載實現(xiàn)原理:

          由于瀏覽器會自動對頁面中的 img 標(biāo)簽的 src 屬性發(fā)送請求并下載圖片,可以通過 html5 自定義屬性 data-xxx 先暫存 src 的值,然后在圖片出現(xiàn)在屏幕可視區(qū)域的時候,再將 data-xxx 的值重新賦值到 img 的 src 屬性即可

          <img src="" alt="" data-src="./images/1.jpg">
          <img src="" alt="" data-src="./images/2.jpg">
          復(fù)制代碼

          這里以 vue-lazyload 插件為例

          // 安裝 
          npm install vue-lazyload 
              
          // main.js 注冊
          import VueLazyload from 'vue-lazyload'
          Vue.use(VueLazyload)
          // 配置項
          Vue.use(VueLazyload, {
            preLoad: 1.3,
            error: 'dist/error.png', // 圖片加載失敗時的占位圖
            loading: 'dist/loading.gif', // 圖片加載中時的占位圖
            attempt: 1
          })
          
          // 通過 v-lazy 指令使用
          <ul>  
              <li v-for="img in list">
                  <img v-lazy="img.src" :key="img.src" >
              </li>
          </ul>
          復(fù)制代碼

          使用字體圖標(biāo)

          字體圖標(biāo)是頁面使用小圖標(biāo)的不二選擇,最常用的就是 iconfont

          字體圖標(biāo)的優(yōu)點:

          1)輕量級:一個圖標(biāo)字體要比一系列的圖像要小。一旦字體加載了,圖標(biāo)就會馬上渲染出來,減少了 http 請求

          2)靈活性:可以隨意的改變顏色、產(chǎn)生陰影、透明效果、旋轉(zhuǎn)等

          3)兼容性:幾乎支持所有的瀏覽器,請放心使用

          圖片轉(zhuǎn) base64 格式

          將小圖片轉(zhuǎn)換為 base64 編碼字符串,并寫入 HTML 或者 CSS 中,減少 http 請求

          轉(zhuǎn) base64 格式的優(yōu)缺點:

          1)它處理的往往是非常小的圖片,因為 Base64 編碼后,圖片大小會膨脹為原文件的 4/3,如果對大圖也使用 Base64 編碼,后者的體積會明顯增加,即便減少了 http 請求,也無法彌補這龐大的體積帶來的性能開銷,得不償失

          2)在傳輸非常小的圖片的時候,Base64 帶來的文件體積膨脹、以及瀏覽器解析 Base64 的時間開銷,與它節(jié)省掉的 http 請求開銷相比,可以忽略不計,這時候才能真正體現(xiàn)出它在性能方面的優(yōu)勢

          項目可以使用 url-loader 將圖片轉(zhuǎn) base64:

          // 安裝
          npm install url-loader --save-dev
              
          // 配置
          module.exports={
            module: {
              rules: [{
                  test: /.(png|jpg|gif)$/i,
                  use: [{
                      loader: 'url-loader',
                      options: {
                        // 小于 10kb 的圖片轉(zhuǎn)化為 base64
                        limit: 1024 * 10
                      }
                  }]
               }]
            }
          };
          復(fù)制代碼

          關(guān)于前端性能優(yōu)化的知識點

          “春江水暖鴨先知,產(chǎn)品好壞客戶知”,作為前端開發(fā),我們更注重客戶體驗,產(chǎn)品的好壞決定著客戶的體驗,那么一款產(chǎn)品的好壞有很多因素,其中性能是決定因素,那么怎么優(yōu)化才能讓產(chǎn)品的性能達(dá)到優(yōu)良,讓客戶體驗良好,今天我就帶大家去了解學(xué)習(xí)前端性能優(yōu)化。

          優(yōu)化的目的

          優(yōu)化的目的在于讓頁面加載的更快,對用戶操作響應(yīng)更及時,為用戶帶來更好的用戶體驗,對于開發(fā)者來說優(yōu)化能夠減少頁面請求數(shù),能夠節(jié)省資源。

          前端優(yōu)化的方法有很多種,可以將其分為兩大類,第一類是頁面級別的優(yōu)化如http請求數(shù),內(nèi)聯(lián)腳本的位置優(yōu)化等,第二類為代碼級別的優(yōu)化,例Javascript中的DOM 操作優(yōu)化、CSS選擇符優(yōu)化、圖片優(yōu)化以及 HTML結(jié)構(gòu)優(yōu)化等等。

          優(yōu)化哪些?

          那么我們需要優(yōu)化哪些點呢?

          1. 加載資源優(yōu)化
          2. 渲染優(yōu)化
          3. 瀏覽器緩存策略
          4. 圖片優(yōu)化
          5. 節(jié)流與防抖

          加載資源優(yōu)化

          說起加載,當(dāng)我們輸入URL時,我們要知道這中間發(fā)生了什么?

          • 首先做 DNS 查詢,如果這一步做了智能 DNS 解析的話,會提供訪問速度最快的 IP 地址回來
          • 接下來是 TCP 握手,應(yīng)用層會下發(fā)數(shù)據(jù)給傳輸層,這里 TCP 協(xié)議會指明兩端的端口號,然后下發(fā)給網(wǎng)絡(luò)層。網(wǎng)絡(luò)層中的 IP 協(xié)議會確定 IP 地址,并且指示了數(shù)據(jù)傳輸中如何跳轉(zhuǎn)路由器。然后包會再被封裝到數(shù)據(jù)鏈路層的數(shù)據(jù)幀結(jié)構(gòu)中,最后就是物理層面的傳輸了
          • TCP 握手結(jié)束后會進(jìn)行 TLS 握手,然后就開始正式的傳輸數(shù)據(jù)
          • 數(shù)據(jù)在進(jìn)入服務(wù)端之前,可能還會先經(jīng)過負(fù)責(zé)負(fù)載均衡的服務(wù)器,它的作用就是將請求合理的分發(fā)到多臺服務(wù)器上,這時假設(shè)服務(wù)端會響應(yīng)一個 HTML 文件
          • 首先瀏覽器會判斷狀態(tài)碼是什么,如果是 200 那就繼續(xù)解析,如果 400 或 500 的話就會報錯,如果 300 的話會進(jìn)行重定向,這里會有個重定向計數(shù)器,避免過多次的重定向,超過次數(shù)也會報錯
          • 瀏覽器開始解析文件,如果是 gzip 格式的話會先解壓一下,然后通過文件的編碼格式知道該如何去解碼文件
          • 文件解碼成功后會正式開始渲染流程,先會根據(jù) HTML 構(gòu)建 DOM 樹,有 CSS 的話會去構(gòu)建 CSSOM 樹。如果遇到 script 標(biāo)簽的話,會判斷是否存在 async 或者 defer ,前者會并行進(jìn)行下載并執(zhí)行 JS,后者會先下載文件,然后等待 HTML 解析完成后順序執(zhí)行,如果以上都沒有,就會阻塞住渲染流程直到 JS 執(zhí)行完畢。遇到文件下載的會去下載文件,這里如果使用 HTTP 2.0 協(xié)議的話會極大的提高多圖的下載效率。
          • 初始的 HTML 被完全加載和解析后會觸發(fā) DOMContentLoaded 事件
          • CSSOM 樹和 DOM 樹構(gòu)建完成后會開始生成 Render 樹,這一步就是確定頁面元素的布局、樣式等等諸多方面的東西
          • 在生成 Render 樹的過程中,瀏覽器就開始調(diào)用 GPU 繪制,合成圖層,將內(nèi)容顯示在屏幕上了

          我們從輸入 URL 到顯示頁面這個過程中,涉及到網(wǎng)絡(luò)層面的,有三個主要過程:

          • DNS 解析
          • TCP 連接
          • HTTP 請求/響應(yīng)

          這里我們就不用去管DNS解析和TCP鏈接了,畢竟不是我們的事,也干不來,但是HTTP請求和響應(yīng)是我們優(yōu)化的重點。

          HTTP優(yōu)化可分為兩個方面:

          • 盡量減少請求次數(shù)
          • 盡量減少單次請求所花費的時間

          減少請求數(shù):

          • 合理的設(shè)置http緩存,恰當(dāng)?shù)木彺嬖O(shè)置可以大大減少http請求。要盡可能地讓資源能夠在緩存中待得更久。
          • 從設(shè)計實現(xiàn)層面簡化頁面,保持頁面簡潔、減少資源的使用時是最直接的。
          • 資源合并與壓縮,盡可能的將外部的腳本、樣式進(jìn)行合并,多個合為一個。
          • CSS Sprites,通過合并 CSS圖片,這是減少請求數(shù)的一個好辦法

          內(nèi)聯(lián)腳本的位置:

          瀏覽器是并發(fā)請求的,很多時候我們會加入很多的外鏈腳本,而外鏈腳本在加載時卻常常阻塞其他資源,例如在腳本加載完成之前,它后面的圖片、樣式以及其他腳本都處于阻塞狀態(tài),直到腳本加載完成后才會開始加載。如果將腳本放在比較靠前的位置,則會影響整個頁面的加載速度從而影響用戶體驗。所以說盡可能的將腳本往后挪,減少對并發(fā)下載的影響。

          渲染優(yōu)化

          客戶端的渲染

          前端去取后端的數(shù)據(jù)生成DOM樹,加載過來后,自己在瀏覽器由上而下跑執(zhí)行JS,隨后就會生成相應(yīng)的DOM。

          優(yōu)點:

          1. 客戶端的渲染使得前后端分離,開發(fā)效率高
          2. 用戶體驗更好,我們將網(wǎng)站做成SPA(單頁面應(yīng)用)或者部分內(nèi)容做成SPA,當(dāng)用戶點擊時,不會形成頻繁的跳轉(zhuǎn)

          缺點:

          1. 前端響應(yīng)速度慢,特別是首屏,這樣用戶是受不了的
          2. 不利于SEO優(yōu)化,因為爬蟲不認(rèn)識SPA,所以它只是記錄了一個頁面

          服務(wù)端的渲染

          DOM樹在服務(wù)端生成,然后返回給前端,頁面上展現(xiàn)的內(nèi)容,我們在HTML源文件也能找到。

          優(yōu)點:

          1. 服務(wù)端渲染盡量不占用前端的資源,前端這塊耗時少,速度快
          2. 利于SEO優(yōu)化,因為在后端有完整的html頁面,所以爬蟲更容易爬取信息

          缺點:

          1. 不利于前后端分離,開發(fā)的效率降低了
          2. 對html的解析,對前端來說加快了速度,但是加大了服務(wù)器的壓力

          類似企業(yè)級網(wǎng)站,主要功能是頁面展示,它沒有復(fù)雜的交互,并且需要良好的SEO,那我們應(yīng)該使用服務(wù)端渲染。

          現(xiàn)在很多網(wǎng)站使用服務(wù)端渲染和客戶端渲染結(jié)合的方式:首屏使用服務(wù)端渲染,其他頁面使用客戶端渲染。這樣可以保證首屏的加載速度,也完成了前后端分離。

          區(qū)分:源碼里如果能找到前端頁面中的內(nèi)容文字,那就是在服務(wù)端構(gòu)建的DOM,就是服務(wù)端渲染,反之是客戶端渲染。

          瀏覽器渲染

          瀏覽器渲染機制一般分為:

          • 分析HTML并構(gòu)建DOM樹
          • 分析CSS構(gòu)建CSSOM樹
          • 將DOM和CSSOM合并成一個渲染樹
          • 根據(jù)渲染樹布局,計算每個節(jié)點的位置
          • 調(diào)用GPU繪制,合成圖層,顯示頁面

          在渲染DOM的時候,瀏覽器所做的事情:

          • 獲取DOM后分割為多個圖層
          • 對每個圖層的節(jié)點計算樣式結(jié)果(recalculate style -- 樣式重計算)
          • 為每個節(jié)點生成圖形和位置(layout -- 回流和重布局)
          • 將每個節(jié)點繪制填充到圖層位圖中(paint setup 和 paint -- 重繪)
          • 圖層作為紋理上傳至GPU
          • 復(fù)合多個圖層到頁面上生成最終屏幕圖像(composite layers -- 圖層重組)

          新建獨立圖層會減少重回回流帶來的影響,但是在圖層重組的時候會消耗大量的性能,所以要權(quán)衡利弊,有所選擇。

          渲染流程的CSS優(yōu)化

          CSS的渲染是從右到左進(jìn)行匹配的,我們應(yīng)該注意:

          • 避免大量使用通配符,可選擇需要用到的元素
          • 關(guān)注可以通過繼承實現(xiàn)的屬性,避免重復(fù)匹配,重復(fù)定義
          • 少用標(biāo)簽選擇器,例如.header ul li a
          • id和class選擇器不應(yīng)該被多余的選擇器拖后腿,例如.header#title
          • 減少嵌套,后代選擇器的開銷最高,不要一大串,要將選擇器的深度降到最低,盡可能使用類來關(guān)聯(lián)每一個標(biāo)簽元素。

          CSS阻塞

          我們將css放在head標(biāo)簽里和盡快啟用CDN實現(xiàn)靜態(tài)資源加載速度的優(yōu)化,因為只要CSSOM不OK,那么渲染就不會完成。

          JS阻塞

          JS引擎是獨立于渲染引擎存在的,就是說插在頁面那,就在那執(zhí)行,瀏覽器遇到script標(biāo)簽時,它就會停止交于JS引擎渲染,等它渲染完,瀏覽器又交于渲染引擎繼續(xù)CSSOM和DOM的構(gòu)建。

          DOM渲染優(yōu)化

          也就是說重繪回流問題

          • 回流:前面我們通過構(gòu)造渲染樹,我們將可見DOM節(jié)點以及它對應(yīng)的樣式結(jié)合起來,可是我們還需要計算它們在設(shè)備視口(viewport)內(nèi)的確切位置和大小,這個計算的階段就是回流。
          • 重繪:最終,我們通過構(gòu)造渲染樹和回流階段,我們知道了哪些節(jié)點是可見的,以及可見節(jié)點的樣式和具體的幾何信息(位置、大小),那么我們就可以將渲染樹的每個節(jié)點都轉(zhuǎn)換為屏幕上的實際像素,這個階段就叫做重繪節(jié)點。

          當(dāng)頁面布局和幾何信息發(fā)生變化的時候,就需要回流。比如以下情況:

          • 添加或刪除可見的DOM元素
          • 元素的位置發(fā)生變化
          • 元素的尺寸發(fā)生變化(包括外邊距、內(nèi)邊框、邊框大小、高度和寬度等)
          • 內(nèi)容發(fā)生變化,比如文本變化或圖片被另一個不同尺寸的圖片所替代。
          • 頁面一開始渲染的時候(這肯定避免不了)
          • 瀏覽器的窗口尺寸變化(因為回流是根據(jù)視口的大小來計算元素的位置和大小的)

          注意:回流一定會觸發(fā)重繪,而重繪不一定會回流,回流比重繪做的事情要多,帶來的開銷也大,在開發(fā)中,要從代碼層面出發(fā),盡可能把回流和重繪的次數(shù)最小化。

          如何最小化重繪和重排

          • 用 translate 替代 top
          • 用 opacity 替代 visibility
          • 不要一條一條的修改 DOM 的樣式,預(yù)先定義好 class,然后修改 DOM 的 className
          • 把 DOM 離線后修改,比如:先把 DOM 給 display: none(有一次 reflow),然后修改100次,然后再顯示出來
          • 不要把 DOM 節(jié)點的屬性值放在一個循環(huán)里當(dāng)成循環(huán)里的變量
          • 不要使用 table 布局,可能很小的一個改動就會造成整個 table 的重新布局
          • 動畫實現(xiàn)的速度的選擇
          • 對于動畫新建圖層
          • 啟用 GPU 硬件加速

          優(yōu)化總結(jié)

          本文主要介紹的是 代碼層面 的性能優(yōu)化,經(jīng)過上面的一系列優(yōu)化,首頁打開速度有了明顯的提升,雖然都是一些常規(guī)方案,但其中可以深挖的知識點并不少


          主站蜘蛛池模板: 久久精品一区二区| 日韩一区二区三区电影在线观看 | 无码人妻一区二区三区一| 在线观看国产一区二三区| 成人免费一区二区无码视频| 杨幂AV污网站在线一区二区| 亚洲综合无码AV一区二区| 亚洲日韩国产一区二区三区| 国产一区二区三区在线2021 | 日本成人一区二区| 日韩精品一区二区三区在线观看l 日韩精品一区二区三区毛片 | 中文字幕一区二区免费| 蜜桃臀无码内射一区二区三区| 国产乱码精品一区二区三| 精品国产日韩亚洲一区91| 国产乱码一区二区三区四| 国产av熟女一区二区三区| 国产一区二区三区高清在线观看| 精品欧美一区二区在线观看 | 久99精品视频在线观看婷亚洲片国产一区一级在线 | 四虎精品亚洲一区二区三区| 日韩免费一区二区三区在线| 亚洲一区二区三区在线| 日本高清不卡一区| 精品无码一区二区三区爱欲| 中文无码AV一区二区三区| 精品不卡一区中文字幕| 国产精品无码一区二区三区在| 好吊妞视频一区二区| 成人精品一区二区三区校园激情| 亚洲AV无码一区二区三区在线 | 天堂资源中文最新版在线一区 | 精品无码一区在线观看| 色窝窝无码一区二区三区| 亚洲欧洲专线一区| 一区二区三区无码高清| 久久亚洲日韩精品一区二区三区 | 一区二区三区四区精品视频| 亚洲AV无码一区二区三区久久精品| 亚洲av无码一区二区三区天堂| 无码精品人妻一区二区三区人妻斩|