文章來(lái)源于公眾號(hào):充實(shí)的腦洞 ,作者:瘋狂的技術(shù)宅
優(yōu)化網(wǎng)站的性能需要花費(fèi)大量的時(shí)間,并且如果要根據(jù)自己的需求進(jìn)行優(yōu)化則花費(fèi)的時(shí)間可能更多。
在本文中,我將向你展示 10 個(gè)快速優(yōu)化 Web 性能的手段,能在 5 分鐘內(nèi)用于你自己的網(wǎng)站。這些捷徑對(duì)你的代碼庫(kù)或服務(wù)器配置幾乎沒(méi)有什么影響。它們簡(jiǎn)單且容易實(shí)現(xiàn),無(wú)需詳細(xì)了解它們的原理,并且能夠?qū)δ愕男阅墚a(chǎn)生重大影響。
1. 使用文本壓縮
使用文本壓縮,可以最大程度地減少通過(guò)網(wǎng)絡(luò)傳輸?shù)淖止?jié)數(shù)。有幾種壓縮算法。gzip[1] 是最受歡迎的,但Brotli[2] 是一種更新甚至更好的壓縮算法。如果要檢查服務(wù)器是否支持Brotli,則可以使用 Brotli.pro[3] 工具。
如果你的服務(wù)器不支持 Brotli ,則可以按照以下簡(jiǎn)單指南進(jìn)行安裝:
- Nginx on Linux[4]
- Apache[5]
- NodeJs - Express[6]
這是你能夠免費(fèi)得到的第一個(gè)優(yōu)化手段,大多數(shù)托管平臺(tái)或 CDN 默認(rèn)都會(huì)提供壓縮。
2. 圖像壓縮
未壓縮的圖像是潛在的巨大性能瓶頸。如果不對(duì)圖像進(jìn)行壓縮,將會(huì)消耗很大的帶寬。有幾種有用的工具可用于快速壓縮圖像,而不會(huì)損失可見(jiàn)質(zhì)量。我通常使用 Imagemin[7]。它支持多種圖像格式,你可以在命令行界面下使用[8]或使用 npm 模塊[9]。
imagemin img/* --out-dir=dist/images
你可以將 npm
模塊用到 webpack
、gulp
或 grunt
等打包程序中。
const imagemin = require('imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
(async() => {
const files = await imagemin(
['img/*.jpg'],
{
destination: 'dist/img',
plugins: [
imageminMozjpeg({quality: 60}),
]
}
);
console.log(files);
})();
一般情況下可將 4MB 大小的文件減小到 100kB??梢栽?Github中查看演示代碼[10]。
單位 | 文件大小,無(wú)壓縮 | 壓縮文件大小 | 文件大小減少百分比 |
---|---|---|---|
Bytes | 4156855 Bytes | 103273 Bytes | -97% |
MB/kB | 4MB | 103 kB | -97% |
3.圖片格式
使用現(xiàn)代圖像格式可以真正提高性能。WebP 圖像比 JPEG 和 PNG 都小,通常小 25%~35%。WebP 得到了瀏覽器的廣泛支持[11]。
我們使用 imagemin npm
包并為其添加 WebP 插件[12]。以下代碼可將圖像的 WebP 版本輸出到 dist 文件夾中。
const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');
(async() => {
const files = await imagemin(
['img/*.jpg'],
{
destination: 'dist/img',
plugins: [
imageminWebp({quality: 50})
]
}
);
console.log(files);
})();
再看一下文件大小:
單位 | 文件大小,無(wú)壓縮 | 壓縮文件大小 | 文件大小減少百分比 |
---|---|---|---|
Bytes | 4156855 Bytes | 58940 Bytes | -98% |
MB/kB | 4MB | 59 kB | -98% |
結(jié)果表明,與原始圖像相比,文件大小減少了 98%,并且與壓縮的 JPG 文件相比,WebP 更加明顯的壓縮了圖像。WebP 版本比壓縮的 JPEG 版本小 43%。
4. 圖像惰性加載
圖像惰性加載是一種在以后加載暫時(shí)不顯示在屏幕上的圖像的技術(shù)。當(dāng)解析器遇到圖像時(shí)立即加載的話會(huì)減慢初始頁(yè)面的加載速度。使用惰性加載,可以加速頁(yè)面加載過(guò)程并稍后加載圖像。使用 lazysizes[13] 可以輕松完成此操作。你可以把下面這樣的代碼:
<img src="image.jpg" alt="">
改為:
<img data-src="image.jpg" class="lazyload" alt="">
lazysizes
庫(kù)會(huì)處理其余的工作,可以使用瀏覽器進(jìn)行驗(yàn)證。打開(kāi)你的站點(diǎn)并找到圖像標(biāo)簽。如果該 class 從 lazyload
變成了 lazyloaded
,則意味著它可以正常工作。
5. 緩存你的資源:HTTP 緩存頭
緩存是一種可以快速提高網(wǎng)站速度的方法。它減少了老用戶的頁(yè)面加載時(shí)間。如果你有權(quán)限訪問(wèn)服務(wù)器緩存,則用起來(lái)非常簡(jiǎn)單。
你可以使用以下API進(jìn)行緩存:
- Cache-Control[14]
- ETag[15]
- Last-Modified[16]
6. 內(nèi)聯(lián)關(guān)鍵 CSS:推遲非關(guān)鍵 CSS
CSS 是渲染阻止的。這意味著瀏覽器必須先下載并處理所有 CSS 文件,然后才能繪制像素。通過(guò)內(nèi)聯(lián)關(guān)鍵的 CSS,可以大大加快此過(guò)程。
你可以按照以下步驟進(jìn)行操作:
識(shí)別關(guān)鍵的 CSS
如果你不知道你的關(guān)鍵 CSS 是什么,則可以通過(guò) Critcal[17]、CriticalCSS[18] 或 Penthouse[19] 來(lái)幫忙。這些庫(kù)都用來(lái)從給定視口中可見(jiàn)的 HTML 文件中提取 CSS。
下面是使用 criticalCSS
的例子。
var criticalcss = require("criticalcss");
var request = require('request');
var path = require( 'path' );
var criticalcss = require("criticalcss");
var fs = require('fs');
var tmpDir = require('os').tmpdir();
var cssUrl = 'https://web.dev/app.css';
var cssPath = path.join( tmpDir, 'app.css' );
request(cssUrl).pipe(fs.createWriteStream(cssPath)).on('close', function() {
criticalcss.getRules(cssPath, function(err, output) {
if (err) {
throw new Error(err);
} else {
criticalcss.findCritical("https://web.dev/", { rules: JSON.parse(output) }, function(err, output) {
if (err) {
throw new Error(err);
} else {
console.log(output);
// 將其保存到文件以進(jìn)行第 2 步
}
});
}
});
});
內(nèi)聯(lián)關(guān)鍵CSS
當(dāng) HTML 解析器遇到 style
標(biāo)簽時(shí)會(huì)立即處理關(guān)鍵的 CSS。
body {...}
/* ... 其余的關(guān)鍵CSS */
延遲不重要的CSS
非關(guān)鍵的 CSS 不需要立即進(jìn)行處理。瀏覽器可以在 onload 事件之后再加載它,使用戶不必等待。
7. JavaScript 異步及延遲加載
JavaScript 是 HTML 解析器阻止的。瀏覽器必須等待 JavaScript 執(zhí)行才能完成對(duì) HTML 的解析。但是你可以告訴瀏覽器等待 JavaScript 執(zhí)行。
異步加載 JavaScript
通過(guò) async
屬性,你可以告訴瀏覽器異步加載腳本。
Defer JavaScript
defer
屬性告訴瀏覽器在 HTML 解析器完成文檔解析之后再運(yùn)行腳本,但在事件發(fā)生之前,將會(huì)觸發(fā)DOMContentLoaded。
調(diào)整內(nèi)聯(lián)腳本的位置
內(nèi)聯(lián)腳本會(huì)立即執(zhí)行,瀏覽器對(duì)其進(jìn)行解析。因此,你可以將它們放在 HTML 的末尾,緊接在 body 標(biāo)記之前。
8. 使用資源提示加快交付速度。
資源提示[20]能夠訴瀏覽器以后可能加載什么頁(yè)面。該規(guī)范定義了四個(gè)原語(yǔ):
- preconnect(預(yù)連接)
- dns-prefetch(DNS預(yù)?。?/li>
- prefetch(預(yù)?。?/li>
- prerender(預(yù)渲染)
另外,關(guān)于資源提示,我們將 preload[21] 關(guān)鍵字用于 link
屬性。
preconnect
下面的代碼告訴瀏覽器你要建立與另一個(gè)域的連接。瀏覽器將為此連接做準(zhǔn)備。使用預(yù)連接鏈接標(biāo)簽可以將加載時(shí)間縮短 100–500 ms。那么什么時(shí)候應(yīng)該用它呢?直白的說(shuō):當(dāng)你知道在哪里拿東西但不知道該怎么拿。比如哈希樣式文件(styles.2f2k1kd.css
)這類的東西。
dns-prefetch
如果你想告訴瀏覽器將要建立與非關(guān)鍵域的連接,則可以用 dns-prefetch
進(jìn)行預(yù)連接。這大約能夠?yàn)槟愎?jié)省 20–120 毫秒。
prefetch
使用預(yù)取,你可以告訴瀏覽器下載鏈接標(biāo)記中所指的整個(gè)網(wǎng)站。你可以預(yù)取頁(yè)面或資源。預(yù)取在加快網(wǎng)站速度方面非常有用,但是要注意有可能降低網(wǎng)站速度的情況。
低端設(shè)備或網(wǎng)速較慢的情況下可能會(huì)遇到問(wèn)題,因?yàn)闉g覽器會(huì)一直忙于預(yù)取。你可以考慮將預(yù)取與自適應(yīng)加載結(jié)合使用,也可以將智能預(yù)取與 quicklink[22] 和 Guess.js[23] 結(jié)合使用:
prerender
使用預(yù)渲染時(shí),將會(huì)先加載內(nèi)容,然后在后臺(tái)渲染。當(dāng)用戶導(dǎo)航到預(yù)渲染的內(nèi)容時(shí),內(nèi)容會(huì)立即顯示。
preload
借助預(yù)加載功能,瀏覽器會(huì)得到引用的資源很重要的提示,應(yīng)盡快獲取?,F(xiàn)代瀏覽器很擅長(zhǎng)于對(duì)資源進(jìn)行優(yōu)先級(jí)排序,所以應(yīng)該只對(duì)關(guān)鍵資源使用預(yù)加載??煽紤]用預(yù)連接和預(yù)取代替,或者嘗試使用instant.page[24]。
9. 使用 Google Fonts
Google Fonts 很不錯(cuò)。他們提供了優(yōu)質(zhì)的服務(wù),并且應(yīng)用廣泛。如果你不想自己托管字體,那么 Google 字體是一個(gè)很不錯(cuò)的選擇。但是你應(yīng)該注意如何實(shí)現(xiàn)它們。Harry Roberts[25] 寫(xiě)了一篇非常出色的文章,內(nèi)容涉及怎樣用 Google Fonts 來(lái)為網(wǎng)站加速[26]。強(qiáng)烈建議閱讀。
如果你只想知道怎樣用,可以通過(guò)下面的代碼段進(jìn)行 Google 字體集成,但功勞歸功于 Harry。
10. 用 service worker 來(lái)緩存你的資源
service worker 是瀏覽器在后臺(tái)運(yùn)行的腳本。緩存是最常用的功能之一,也是你最應(yīng)該使用的功能。我認(rèn)為這不是選擇問(wèn)題。通過(guò) service worker 實(shí)施緩存,可以使用戶與你的站點(diǎn)之間的交互速度更快,而且即使用戶斷網(wǎng)也可以訪問(wèn)你的網(wǎng)站。
總結(jié)
在本文中,我向你介紹 10 個(gè)快速優(yōu)化 Web 性能的手段,能在 5 分鐘內(nèi)用于你自己的網(wǎng)站。你可以在GitHub 中找到相關(guān)資源[27]。
以上就是W3Cschool編程獅
關(guān)于 Web 性能優(yōu)化的10 個(gè)快速有效手段的相關(guān)介紹了,希望對(duì)大家有所幫助。
參考資料
[1]gzip: https://www.youtube.com/watch?v=whGwm0Lky2s&feature=youtu.be&t=14m11s
[2]Brotli: https://opensource.googleblog.com/2015/09/introducing-brotli-new-compression.html
[3]Brotli.pro: https://www.brotli.pro/
[4]Nginx on Linux: https://computingforgeeks.com/how-to-enable-gzip-brotli-compression-for-nginx-on-linux/
[5]Apache: https://bash-prompt.net/guides/apache-brotoli/
[6]NodeJs - Express: https://web.dev/codelab-text-compression-brotli/
[7]Imagemin: https://github.com/imagemin/imagemin
[8]在命令行界面下使用: https://github.com/imagemin/imagemin-cli
[9]npm 模塊: https://www.npmjs.com/package/imagemin
[10]Github中查看演示代碼: https://github.com/marcradziwill/web-performance-quick-wins-tutorial
[11]WebP 得到了瀏覽器的廣泛支持: https://caniuse.com/#feat=webp
[12]WebP 插件: https://www.npmjs.com/package/imagemin-webp
[13]lazysizes: https://github.com/aFarkas/lazysizes
[14]Cache-Control: https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility
[15]ETag: https://developer.mozilla.org/docs/Web/HTTP/Headers/ETag#Browser_compatibility
[16]Last-Modified: https://developer.mozilla.org/docs/Web/HTTP/Headers/Last-Modified#Browser_compatibility
[17]Critcal: https://github.com/addyosmani/critical
[18]CriticalCSS: https://github.com/filamentgroup/criticalCSS
[19]Penthouse: https://github.com/pocketjoso/penthouse
[20]資源提示: https://www.w3.org/TR/resource-hints/
[21]preload: https://www.w3.org/TR/preload/
[22]quicklink: https://github.com/GoogleChromeLabs/quicklink
[23]Guess.js: https://github.com/guess-js
[24]instant.page: https://instant.page/
[25]Harry Roberts: https://csswizardry.com/
[26]怎樣用 Google Fonts 來(lái)為網(wǎng)站加速: https://csswizardry.com/2020/05/the-fastest-google-fonts/
[27]GitHub 中找到相關(guān)資源: https://github.com/marcradziwill/web-performance-quick-wins-tutorial