重新認(rèn)識(shí) script 標(biāo)簽:不只是寫(xiě) JavaScript 那么簡(jiǎn)單

很多人以為 script 標(biāo)簽只是用來(lái)寫(xiě) JavaScript 代碼的地方。這種理解沒(méi)錯(cuò),但并不完整。實(shí)際上,這個(gè)看似簡(jiǎn)單的標(biāo)簽背后隱藏著許多值得探索的細(xì)節(jié)。
腳本加載的兩種方式:async 與 defer
瀏覽器解析 html 文檔時(shí),是從上到下一邊解析一邊渲染的。當(dāng)遇到普通的 script 標(biāo)簽時(shí),它會(huì)暫停解析,直到腳本下載并執(zhí)行完成后才會(huì)繼續(xù)。這就是為什么我們通常把腳本放在 body 底部的原因。
不過(guò),async 和 defer 屬性提供了更好的解決方案。
使用 defer 屬性的腳本會(huì)異步下載,但會(huì)等到整個(gè)頁(yè)面解析完成后,按照它們?cè)谖臋n中出現(xiàn)的順序執(zhí)行。這意味著它不會(huì)阻塞頁(yè)面解析,又能保證執(zhí)行順序。
<scriptdefersrc="js/script1.js"></script>
<scriptdefersrc="js/script2.js"></script>async 屬性的腳本也是異步下載,但它會(huì)在下載完成后立即執(zhí)行,不保證執(zhí)行順序。這意味著如果多個(gè)腳本有依賴(lài)關(guān)系,使用 async 可能會(huì)導(dǎo)致錯(cuò)誤。
<scriptasyncsrc="js/script1.js"></script>
<scriptasyncsrc="js/script2.js"></script>簡(jiǎn)單來(lái)說(shuō),defer 適合需要按順序執(zhí)行且不急于執(zhí)行的腳本,而 async 適合獨(dú)立且需要盡快執(zhí)行的腳本,比如網(wǎng)站統(tǒng)計(jì)分析代碼。
跨域腳本處理:crossorigin 屬性
script 標(biāo)簽可以加載跨域資源,JSONP 技術(shù)就是利用了這個(gè)特性。但隨著網(wǎng)絡(luò)安全要求的提高,crossorigin 屬性變得越來(lái)越重要。
設(shè)置 crossorigin 屬性后,瀏覽器會(huì)啟用 CORS(跨域資源共享)檢查。如果服務(wù)器沒(méi)有正確配置 CORS 響應(yīng)頭,瀏覽器會(huì)拒絕執(zhí)行腳本。
<scriptsrc="https://fly63.com/script.js"crossorigin="anonymous"></script>crossorigin 有兩個(gè)可選值:
- anonymous:?jiǎn)⒂?CORS 但不發(fā)送憑據(jù)
 - use-credentials:?jiǎn)⒂?CORS 并發(fā)送憑據(jù)(如 cookies)
 
使用 crossorigin 的主要好處是:
- 配合 integrity 屬性可以驗(yàn)證資源完整性,防止腳本被篡改
 - 能夠獲取更詳細(xì)的腳本錯(cuò)誤信息
 - 符合內(nèi)容安全策略(CSP)的要求
 
模塊化腳本:type="module"
現(xiàn)代瀏覽器已經(jīng)支持 ES 模塊,只需設(shè)置 type="module" 即可使用 import 和 export 語(yǔ)法。
<scripttype="module">
import { utils } from'./utils.js';
// 使用導(dǎo)入的模塊
</script>使用模塊化腳本有幾個(gè)特點(diǎn):
- 自動(dòng)啟用嚴(yán)格模式
 - 支持頂級(jí) await
 - 默認(rèn)具有 defer 的行為(異步加載不阻塞頁(yè)面)
 - 支持按需導(dǎo)入
 
對(duì)于需要導(dǎo)入映射的情況,可以使用 importmap:
<scripttype="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
  }
}
</script>這樣在代碼中就可以直接使用 import Vue from 'vue',而不需要寫(xiě)完整的 URL。
安全增強(qiáng):nonce 屬性
除了上述屬性,nonce 也是一個(gè)重要的安全特性。它通常與內(nèi)容安全策略(CSP)一起使用,防止跨站腳本攻擊(XSS)。
nonce 是一個(gè)隨機(jī)生成的字符串,只有匹配 CSP 頭中指定的 nonce 值的腳本才會(huì)被執(zhí)行。
服務(wù)器端設(shè)置 CSP 頭:
Content-Security-Policy: script-src 'nonce-abc123'HTML 中使用:
<scriptnonce="abc123">
// 只有 nonce 值匹配的腳本才會(huì)執(zhí)行
</script>這種方式可以有效防止惡意腳本注入,提高網(wǎng)站安全性。
實(shí)際應(yīng)用建議
- 對(duì)于主要功能腳本,優(yōu)先使用 defer 而不是將腳本放在 body 底部
 - 加載第三方資源時(shí),總是使用 crossorigin 屬性
 - 在現(xiàn)代項(xiàng)目中,可以考慮使用 type="module" 利用瀏覽器原生模塊支持
 - 對(duì)于重要網(wǎng)站,實(shí)施 CSP 策略并使用 nonce 增強(qiáng)安全性
 
理解這些屬性和它們的用途,不僅能優(yōu)化頁(yè)面加載性能,還能提高網(wǎng)站的安全性。雖然有些細(xì)節(jié)看起來(lái)復(fù)雜,但掌握它們對(duì)于前端開(kāi)發(fā)者來(lái)說(shuō)是非常有價(jià)值的。















 
 
 






 
 
 
 