[前端] DNS解析與優化
這篇筆記總結自網課??DNS解析和優化【渡一教育】
DNS用于將域名轉換成IP地址。
特點:
-
DNS解析過程耗費時間長;
-
DNS有本地緩存。
DNS解析完成得到IP地址,這個IP地址會存儲到本地設備,后續再讀這個域名會直接返回本地緩存的IP地址。
用戶瀏覽網頁中的DNS解析流程

- 首先用戶輸入url地址,然后需要對網站的域名進行DNS解析,這個解析過程無法優化。
- 而在站點中可能還用到了很多其它域名下的資源,在解析
html的過程也會觸發DNS解析。
例如:<img>標簽的src引用了其它域名站點的圖片,或者<script>標簽引入了外部的腳本文件,或者<link>標簽引入了其它域名站點的css文件。
當解析html的過程中遇到了站外的
script標簽且本地無緩存時,解析html的進度會暫停,直到script標簽引入并執行再繼續。
隨著網站規模越來越大,這種外部資源的引入可能越來越多。而多次的DNS解析會耗費許多時間。
優化思路:源代碼中使用的外部域名是已知的,可以把它們都提取到html的頭部,提前異步解析。
提前異步解析DNS

使用link標簽的dns-prefetch
<html>
<head>
<link rel="dns-prefetch" />
<link rel="dns-prefetch" />
<link rel="dns-prefetch" />
...
</head>
<body>
...
</body>
</html>
但是,考慮到我們平時的開發環境有以下特點:
- 使用框架開發,不同的域名分散在不同的組件;
- 多人開發,不知道其他人有沒有引入外部域名;
- 一般不會手動編輯打包后的
index.html文件。
我們需要較為自動化的腳本協助完成整個項目中的外部域名統計,并寫入到最終打包的index.html頭部。
腳本編寫
目的:讀取dist文件夾中的.css,.js文件,統計外部域名并寫入到index.html頭部。
創建腳本:項目根目錄下創建文件夾/scripts,創建文件dns-prefetch.js;
腳本內容:
const fs = require('fs');
const path = require('path');
const { parse } = require('node-html-parse');
const { glob } = require('glob');
const urlRegex = require('url-regex');
// 獲取外部鏈接的正則表達式
const urlPattern = /(https?:\/\/[^/]*)/i;
const urls = new Set();
// 遍歷dist目錄中的所有HTML, JS, CSS文件
async function searchDomain(){
const files = await glob('dist/**/*.{html,css,js}');
for(const file of files){
const source = fs.readFileSync(file, 'utf-8');
const matches = source.match(urlRegex({strict: true}));
if(matches){
matches.forEach((url)=>{
const match = url.match(urlPattern);
if(match && match[1]){
urls.add(match[1]);
}
});
}
}
}
async function insertLinks(){
const files = await glob('dist/**/*.html');
const links = [...urls]
.map((url) => `<link rel="dns-prefetch" href="${url}"/>`)
.join('\n');
for(const file of files){
const html = fs.readFileSync(file, 'utf-8');
const root = parse(html);
const head = root.querySelector('head');
head.insertAdjacentHTML('afterbegin', links);
fs.writeFileSync(file, root.toString());
}
}
async function main(){
await searchDomain();
// 在<head>標簽中添加預取鏈接
await insertLinks();
}
main();
glob用于使用正則表達式將匹配的文件都找到;fs用于讀取選中的文件;urlRegex用于分析出文件中的URL地址;node-html-parse用于在脫離瀏覽器的環境下,將讀取到的html代碼文本轉換為節點。
當腳本編寫完成之后,將其添加到打包代碼的工具流程中。
在package.json文件中:
{
"scripts": {
"build": "vite build && node ./scripts/dns-prefetch.js"
}
}

浙公網安備 33010602011771號