前面關于雙代號網絡所有概念和參數的算法都已經學完了,今天來認識一下另外一種網絡圖-雙代號時標網絡圖,雙代號網絡計劃一共分兩類一類是雙代號標時網絡圖,簡稱雙代號網絡圖就是前幾天我們學習的網絡圖,平時說的雙代號網絡就是說的雙代號標時網絡圖,還有一類就是雙代號時標網絡圖,主要區別就在名字上一個是標時一個是時標,這里的時標的意思是指持續時間是用時標來表示的。下面來認識一下。
定義:以水平時間坐標為尺度表示工作時間編制的雙代號網絡計劃。
雙代號時標網絡圖
和雙代號網絡圖不同有上下多出時標刻度,有的工作上還有波浪線,工作下方沒有持續時間。下面我們就認識一下個部位分別表示什么。
實箭線:實際發生的工作表示實工作;
虛箭線:工作間邏輯關系表示虛工作;
這兩中箭線表示的意思和雙代號網絡表示意思相同,下面就是不同之處。
波形線表示本項工作的自由時差;是不是感覺跟雙代號網絡圖簡單算法算時間參數的第一步差不多,其實就是相互轉化的關系。
持續時間:就用時間刻度來表示。箭線的長度和持續時間成比例。
這么一看是不是感覺雙代號時標網絡算時間參數簡單了,確實簡單很多直接就可以看出來,不用一個一個算了。但是雙代號時標網絡繪圖比較麻煩,出現問題需要修改時更麻煩,所以平時用的比較少一些。
還有一個平時比較容易忽視也比較容易犯錯的一個知識點,就是時間刻度表示方法。上面的網絡圖第五周末在哪里,第六周初又在哪里,其實他倆位置是一個點,都在第五段和第六段中間那個刻度上,在每段上表示時間刻度比較容易確定位置也不容易犯錯,但是下面這種表示方就比較容易犯錯:
上圖的時間刻度的數字是直接標注到在各個點上,還是上面問題第五周末、第六周初在哪,首先要看刻度的起點是0,那么第一個格就是第一周標注1的位置就是第一周末,同理其他的都是。那么第五周末、第六周就是標注5的位置。如果第一個數字是1就是另外一種結果。
雙代號時標網絡圖表示持續時間是用刻度表示的一定要注意第幾周末、第幾周初不要搞錯,要是在這上犯錯后面計算所有的數都是錯的,題目也會做錯。還有一個就是查持續時間時一定要查準。
雖然雙代號時標網絡圖看著比較簡單,但是易錯點很多,網絡圖的特點是環扣一環的,前面一個錯了后面相應的都會算錯,遇到易錯點一定要注意。
如果你要是沒有學習的資料也可以關注我,我微頭條最少每天都會發一下好的資料給大家,方便大家學習,您要是遇到學習上的問題也可以找我哦?。?!希望大家多多關注砼砼造價
聊一聊如何搭建高性能網站
在快節奏的時代中,慢是個不容忍受的事情。
一、 為什么會‘慢’呢?
慢的情況是多種多樣的,比如:
我們只能要求自己,所以用戶手機網速慢是不存在的~。
二、 排查手段
我們直接進入則會難過 i 天
我們將從幾個方面著手講一下排查問題的手段。
2.1 技術上的選擇
在前端日常開發中,技術上的選擇是非常重要的。為什么要講這個呢?因為現象頻發。
前端工程化嚴重的當下,輕量化的框架慢慢被遺忘掉了。并不是所有的業務場景都適合使用工程化框架,react/vue 并不輕量。
復雜的框架是為了解決復雜的業務
如果研發 h5 宣發、PC 展示等場景簡單的業務時候, 原生 配合一些輕量化插件更適合。
多頁面應用也并不都是缺點。根據業務不同而選擇不一樣的技術是非常重要的,是每個前端都應該反思的事情。
這方面是導致卡頓的關鍵問題。
2.2 NetWrok
我們的老朋友 NetWrok 想必前端同學都很熟悉。我們先來看一下 network 面板
從面板上我們可以看出一些信息:
瀑布圖是什么呢?
瀑布圖就是上方圖片后面的 縱列
瀑布圖是一個級聯圖, 展示了瀏覽器如何加載資源并渲染成網頁. 圖中的每一行都是一次單獨的瀏覽器請求. 這個圖越長, 說明加載網頁過程中所發的請求越多. 每一行的寬度, 代表瀏覽器發出請求并下載該資源的過程中所耗費的時間。它的側重點在于分析網路鏈路
瀑布圖顏色說明:
那么除了瀑布圖的長度外,我們如何才能判斷一個瀑布圖的狀態是健康的呢?
這樣,我們就可以從 network 的角度去排查 “慢” 的問題。
2.3 webpack-bundle-
項目構建后生成的 bundle 包是壓縮后的。webpack-bundle- 是一款包分析工具。
我們先來看一下它能帶來的效果。如下圖:
從上圖來看,我們的 bundle 包被解析的一覽無余。其中模塊面積占的越大說明在 bundle 包中 size 越大。就值得注意了,重點優化一下。
它能夠排查出來的信息有
排查包中的模塊情形是非常有必要的,通過 webpack-bundle- 來排查出一些無用的模塊,過大的模塊。然后進行優化。以減少我們的 bundle 包 size,減少加載時長。
安裝
\#?NPM?
npm?install?--save-dev?webpack-bundle-analyzer
#?Yarn?
yarn?add?-D?webpack-bundle-analyzer
復制代碼
使用 (as a Webpack-Plugin)
const?BundleAnalyzerPlugin?=?require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
?
module.exports?=?{
??plugins:?\[
????new?BundleAnalyzerPlugin()
??\]
}
復制代碼
然后構建包完畢后會自動彈出一個窗口展示上圖信息。
2.4
chrome 自帶的 模塊。先附上一個官網文檔傳送門:
可以檢測很多方面的數據,多數情況的性能排查上用的比較多。如果想要深入了解的同學建議去看一下官方文檔。
接下來我們來說一下在 面板中如何排差 “慢” 的問題,它給我們提供了哪些信息呢。先附上一張 的面板圖片。
從上圖中可以分析出一些指標
這些指標就是我們需要重點關注的,當然 的功能并不止于此。
先記住如何獲取到這些指標,后面來一一進行解析優化。
2.5 抓包
有一些業務狀況是沒有上述的一些調試工具該怎么辦呢?我們可以利用抓包工具進行對頁面信息對抓取,上述我們通過 chrome 工具排查出來的指標,也可以通過抓包工具進行抓取。
這里我推薦一款抓包工具 charles。使用教程網上很多,自行搜索即可
三、優化指標
這里我們來講一下如何優化上述指標和一些導致慢的情況
3.1 tree shaking
中文(搖樹),webpack 構建優化中重要一環。搖樹用于清除我們項目中的一些無用代碼,它依賴于 ES 中的模塊語法。
比如日常使用 lodash 的時候
import?\_?from?'lodash'
復制代碼
如果如上引用 lodash 庫,在構建包的時候是會把整個 lodash 包打入到我們的 bundle 包中的。
import?\_isEmpty?from?'lodash/isEmpty';
復制代碼
如果如上引用 lodash 庫,在構建包的時候只會把 isEmpty 這個方法抽離出來再打入到我們的 bundle 包中。
這樣的化就會大大減少我們包的 size。所以在日常引用第三方庫的時候,需要注意導入的方式。
如何開啟搖樹
在 .x 中默認對 tree-shaking 進行了支持。在 .x 中使用 tree-shaking:傳送門
3.2 split chunks
中文(分包)
在沒配置任何東西的情況下,webpack 4 就智能的幫你做了代碼分包。入口文件依賴的文件都被打包進了 main.js,那些大于 30kb 的第三方包,如:echarts、xlsx、 等都被單獨打包成了一個個獨立 bundle。
其它被我們設置了異步加載的頁面或者組件變成了一個個 chunk,也就是被打包成獨立的 bundle。
它內置的代碼分割策略是這樣的:
大家可以根據自己的項目環境來更改配置。配置代碼如下:
splitChunks({
??cacheGroups:?{
????vendors:?{
??????name:?\`chunk-vendors\`,
??????test:?/\[\\\\/\]node\_modules\[\\\\/\]/,
??????priority:?-10,
??????chunks:?'initial',
????},
????dll:?{
??????name:?\`chunk-dll\`,
??????test:?/\[\\\\/\]bizcharts|\[\\\\/\]\\@antv\[\\\\/\]data-set/,
??????priority:?15,
??????chunks:?'all',
??????reuseExistingChunk:?true
????},
????common:?{
??????name:?\`chunk-common\`,
??????minChunks:?2,
??????priority:?-20,
??????chunks:?'all',
??????reuseExistingChunk:?true
????},
??}
})
復制代碼
沒有使用 .x 版本的項目,依然可以通過按需加載的形式進行分包,使得我們的包分散開,提升加載性能。
按需加載也是以前分包的重要手段之一
這里推薦一篇非常好的文章:webpack 如何使用按需加載
3.3 拆包
與 3.2 的分包不同。大家可能沒發現,上面 2.3 的 bundle 包解析中有個有趣的現象,上面項目的技術棧是 react,但是 bundle 包中并沒有 react、react-dom、react-router 等。
因為把這些插件 “拆” 開了。并沒有一起打在 bundle 中。而是放在了 CDN 上。下面我舉一個例子來解釋一下。
假設:原本 bundle 包為 2M,一次請求拉取。拆分為 bundle(1M) + react 桶(CDN)(1M) 兩次請求并發拉取。
從這個角度來看,1+1 的模式拉取資源更快。
換一個角度來說,全量部署項目的情況,每次部署 bundle 包都將重新拉取。比較浪費資源。react 桶的方式可以命中強緩存,這樣的化,就算全量部署也只需要重新拉取左側 1M 的 bundle 包即可,節省了服務器資源。優化了加載速度。
注意:在本地開發過程中,react 等資源建議不要引入 CDN,開發過程中刷新頻繁,會增加 CDN 服務其壓力,走本地就好。
gzip
服務端配置 gzip 壓縮后可大大縮減資源大小。
Nginx 配置方式
http?{
??gzip?on;
??gzip\_buffers?32?4K;
??gzip\_comp\_level?6;
??gzip\_min\_length?100;
??gzip\_types?application/javascript?text/css?text/xml;
??gzip\_disable?"MSIE?\[1-6\]\\.";
??gzip\_vary?on;
}
復制代碼
配置完成后在 header 中可以查看。
3.5 圖片壓縮
開發中比較重要的一個環節,我司自己的圖床工具是自帶壓縮功能的,壓縮后直接上傳到 CDN 上。
如果公司沒有圖床工具,我們該如何壓縮圖片呢?我推薦幾種我常用的方式
圖片壓縮是常用的手法,因為設備像素點的關系,UI 給予的圖片一般都是 x2,x4 的,所以壓縮就非常有必要。
3.6 圖片分割
如果頁面中有一張效果圖,比如真機渲染圖,UI 手拿著刀不讓你壓縮。這時候不妨考慮一下分割圖片。
建議單張土圖片的大小不要超過 100k,我們在分割完圖片后,通過布局再拼接在一起??梢詧D片加載效率。
這里注意一點,分割后的每張圖片一定要給 height,否則網速慢的情況下樣式會塌陷。
3.7 sprite
南方叫精靈圖,北方叫雪碧圖。這個現象就很有趣。
在網站中有很多小圖片的時候,一定要把這些小圖片合并為一張大的圖片,然后通過 分割到需要展示的圖片。
這樣的好處是什么呢?先來普及一個規則
瀏覽器請求資源的時候,同源域名請求資源的時候有最大并發限制,chrome 為 6 個,就比如你的頁面上有 10 個相同 CDN 域名小圖片,那么需要發起 10 次請求去拉取,分兩次并發。第一次并發請求回來后,發起第二次并發。
如果你把 10 個小圖片合并為一張大圖片的畫,那么只用一次請求即可拉取下來 10 個小圖片的資源。減少服務器壓力,減少并發,減少請求次數。
附上一個 sprite 的例子。
3.8 CDN
中文(內容分發網絡),服務器是中心化的,CDN 是 “去中心化的”。
在項目中有很多東西都是放在 CDN 上的,比如:靜態文件,音頻,視頻,js 資源,圖片。那么為什么用 CDN 會讓資源加載變快呢?
舉個簡單的例子:
以前買火車票大家都只能去火車站買,后來我們買火車票就可以在樓下的火車票代售點買了。
你細品。
所以靜態資源度建議放在 CDN 上,可以加快資源加載的速度。
3.9 懶加載。
懶加載也叫延遲加載,指的是在長網頁中延遲加載圖像,是一種非常好的優化網頁性能的方式。
當可視區域沒有滾到資源需要加載的地方時候,可視區域外的資源就不會加載。
可以減少服務器負載,常適用于圖片很多,頁面較長的業務場景中。
如何使用懶加載呢?
3.10
中文(字體圖表),現在比較流行的一種用法。使用字體圖表有幾種好處
就像上面說的雪碧圖,如果都用字體圖標來替換的畫,一次請求都免了,可以直接打到 bundle 包中。
使用前提是 UI 給點力,設計趨向于字體圖標,提前給好資源,建立好字體圖標庫。
3.11 邏輯后移
邏輯后移是一種比較常見的優化手段。用一個打開文章網站的操作來舉個例子。
沒有邏輯后移處理的請求順序是這個樣子的
頁面的展示主體是文章展示,如果文章展示的請求靠后了,那么渲染文章出來的時間必然靠后,因為有可能因為請求阻塞等情況,影響請求響應情況,如果超過一次并發的情況的話,會更加的慢。如圖的這種情況也是在我們項目中發生過的。
很明顯我們應該把主體 “請求文章” 接口前移,把一些非主體的請求邏輯后移。這樣的話可以盡快的把主體渲染出來,就會快很多。
優化后的順序是這個樣子的。
在平常的開發中建議時常注意邏輯后移的情況,突出主體邏輯。可以極大的提升用戶體驗。
3.12 算法復雜度
在數據量大的應用場景中,需要著重注意算法復雜度問題。
在這個方面可以參考 算法之復雜度分析這篇文章。
如上面 解析出的 執行指標上,可以推測出來你的 code 執行效率如何,如果執行時間過長就要考慮一下是否要優化一下復雜度了。
在時間換空間,空間換時間的選擇上,要根據業務場景來進行取舍。
3.13 組件渲染
拿 react 舉例,組件分割方面不要太深。需要控制組件的渲染,尤其是深層組件的 render。
老生常談的話題,我們可以一些方式來優化組件渲染
沒有必要的渲染是對性能的極大浪費。
3.14 node
中文(node 中間件)
中間件主要是指封裝所有 Http 請求細節處理的方法。一次 Http 請求通常包含很多工作,如記錄日志、ip 過濾、查詢字符串、請求體解析、Cookie 處理、權限驗證、參數驗證、異常處理等,但對于 Web 應用而言,并不希望接觸到這么多細節性的處理,因此引入中間件來簡化和隔離這些基礎設施與業務邏輯之間的細節,讓我們能夠關注在業務的開發上,以達到提升開發效率的目的。
使用 node 合并請求。減少請求次數。這種方式也是非常實用的。
3.15 web worker
Web Worker 的作用,就是為 創造多線程環境,允許主線程創建 Worker 線程,將一些任務分配給后者運行。在主線程運行的同時,Worker 線程在后臺運行,兩者互不干擾。等到 Worker 線程完成計算任務,再把結果返回給主線程。這樣的好處是,一些計算密集型或高延遲的任務,被 Worker 線程負擔了,主線程(通常負責 UI 交互)就會很流暢,不會被阻塞或拖慢。
合理實用 web worker 可以優化復雜計算任務。這里直接拋阮一峰的入門文章:傳送門
3.16 緩存
緩存方面可以講非常多的內容,我會單獨開一篇緩存全攻略文章來詳細講述。
合理的利用強緩存、緩存協商、動態緩存等等機制,可以極大提升用戶體驗及頁面打開速度。在開發過程中,緩存也成為了不可或缺的一部分。
四、END
上面整理了一些在實際業務開發中遇到的關于頁面加載慢的排查和解決的方法。后面還會越來月豐富起來,如果你的項目有可能遇到打開慢的情況,不妨點贊收藏一下~
*請認真填寫需求信息,我們會在24小時內與您取得聯系。