新聞中心
當(dāng)ES模塊第一次在ECMAScript 2015中被引入,作為在JavaScript中標(biāo)準(zhǔn)化模塊系統(tǒng)的一種方式時,它是通過在import語句中指定相對或絕對路徑來實現(xiàn)的。

import dayjs from "https://cdn.skypack.dev/dayjs@1.10.7"; // ES modules
console.log(dayjs("2019-01-25").format("YYYY-MM-DDTHH:mm:ssZ[Z]"));
這與模塊在其他通用模塊系統(tǒng)中的工作方式略有不同,例如CommonJS,以及在使用webpack這樣的模塊捆綁器時,使用的是更簡單的語法。
const dayjs = require('dayjs') // CommonJS
import dayjs from 'dayjs'; // webpack在這些系統(tǒng)中,通過Node.js運(yùn)行時或相關(guān)的構(gòu)建工具,導(dǎo)入指定器被映射到一個特定(和版本)的文件。用戶只需要在導(dǎo)入語句中應(yīng)用裸露的模塊指定符(通常是包名),圍繞模塊解析的問題就會被自動解決。
由于開發(fā)者已經(jīng)熟悉了這種從npm導(dǎo)入包的方式,所以需要一個構(gòu)建步驟來確保以這種方式編寫的代碼能夠在瀏覽器中運(yùn)行。這個問題由import maps解決了。從本質(zhì)上講,它允許將導(dǎo)入指定器映射到相對或絕對的URL上,這有助于控制模塊的解析,而不需要應(yīng)用構(gòu)建步驟。
import maps 是怎么工作的
import map 是通過HTML document中的
在上面的 imports 對象中,每個屬性都對應(yīng)著一個映射。映射的左邊是 import 指定器的名稱,而右邊是指定器應(yīng)該映射到的相對或絕對URL。
當(dāng)在映射中指定相對URL時,確保它們總是以/、./或./開頭。請注意,在 import map 中出現(xiàn)包并不意味著它一定會被瀏覽器加載。任何沒有被頁面上的 script 使用的模塊都不會被瀏覽器加載,即使它存在于import map中。
你也可以在一個外部文件中指定你的映射,然后使用src屬性鏈接到該文件(如上所示)。如果決定使用這種方法,請確保在發(fā)送文件時將其Content-Type標(biāo)頭設(shè)置為application/importmap+json。
注意,出于性能方面的考慮,推薦使用內(nèi)聯(lián)方式,本文的其余部分的事例,也會使用內(nèi)聯(lián)方式。
一旦指定了映射,就可以在import語句中使用import說明符,如下所示:
需要注意的是,導(dǎo)入映射中的映射不會影響諸如
這種方法允許我們導(dǎo)入指定路徑中的任何模塊,而不是整個主模塊,這會導(dǎo)致所有組件模塊由瀏覽器下載。
動態(tài)地構(gòu)建 import map
映射也可以基于任意條件在 script 中動態(tài)構(gòu)造,這種能力可以用來根據(jù)特征檢測有條件地導(dǎo)入模塊。下面的例子根據(jù)IntersectionObserver API是否被支持,在lazyload指定器下選擇正確的文件進(jìn)行導(dǎo)入。
如果你想使用這種方法,請確保在創(chuàng)建和插入 import map 腳本標(biāo)簽之前進(jìn)行(如上所述),因為修改一個已經(jīng)存在的導(dǎo)入地圖對象不會有任何效果。
通過對哈希值的映射來提高腳本的可緩存性
實現(xiàn)靜態(tài)文件長期緩存的常見技術(shù)是在文件名中使用文件內(nèi)容的哈希值,這樣文件就會一直在瀏覽器的緩存中,直到文件內(nèi)容發(fā)生變化。當(dāng)這種情況發(fā)生時,文件將得到一個新的名字,以便最新的更新立即反映在應(yīng)用程序中。
在傳統(tǒng)的 bundling scripts,的方式下,如果一個被多個模塊依賴的依賴關(guān)系被更新,這種技術(shù)就會出現(xiàn)問題。這將導(dǎo)致所有依賴該依賴的文件被更新,迫使瀏覽器重新下載它們,即使只有一個字符的代碼被改變。
import map 為這個問題提供了一個解決方案,它允許通過重映射技術(shù)單獨(dú)更新每個依賴關(guān)系。假設(shè)你需要從一個名為post.bundle.8cb615d12a121f6693aa.js的文件中導(dǎo)入一個方法:
而不是這樣寫:
import { something } from './static/dist/post.bundle.8cb615d12a121f6693aa.js'可以這么寫:
import { something } from 'post.js'當(dāng)更新文件的時候,只有 import map 需要更新。由于對其導(dǎo)出的引用沒有更改,它們將保持在瀏覽器中的緩存,同時由于更新的哈希值,更新的腳本將再次被下載。
使用同一模塊的多個版本
在 import map 中很容易實現(xiàn)一個包對應(yīng)多個版本,所需要做的就是在映射中使用不同的導(dǎo)入指定符,如下圖所示:
通過使用作用域,也可以用同一個導(dǎo)入指定符來指代同一個包的不同版本。這允許我們在一個給定的作用域內(nèi)改變導(dǎo)入指定符的含義。
有了這種映射,在/static/js路徑下的任何模塊,在導(dǎo)入語句中引用lodash/指定器時,將使用https://unpkg.com/lodash-es@3.10.1/,而其他模塊將使用https://unpkg.com/lodash-es@4.17.21/。
使用帶有 import map 的 NPM 包
正如在本文中所展示的,任何使用ES Modules的NPM包的生產(chǎn)版本都可以通過ESM、Unpkg和Skypack等CDN在 import map中使用。
即使NPM上的包不是為ES模塊系統(tǒng)和本地瀏覽器導(dǎo)入行為設(shè)計的,像Skypack和ESM這樣的服務(wù)也可以將它們轉(zhuǎn)化為可在導(dǎo)入地圖中使用的包??梢允褂肧kypack主頁上的搜索欄來尋找瀏覽器優(yōu)化的NPM包,這些包可以立即使用,而無需擺弄構(gòu)建步驟。
檢測 import map支持
只要支持HTMLScriptElement.supports()方法,就可以在瀏覽器中檢測 import map的支持:?
if (HTMLScriptElement.supports && HTMLScriptElement.supports('importmap')) {
// import maps is supported
}
支持舊的瀏覽器
Import map 使得在瀏覽器中使用裸模塊指定器成為可能,而無需依賴目前在JavaScript生態(tài)系統(tǒng)中普遍存在的復(fù)雜的構(gòu)建系統(tǒng),但目前網(wǎng)絡(luò)瀏覽器中并不廣泛支持它。
在整理本文時,Chrome和Edge瀏覽器的89版及以后的版本提供了全面支持,但Firefox、Safari和一些移動瀏覽器不支持這項技術(shù)。為了在這些瀏覽器中保留對 import map的使用,必須采用一個合適的 polyfill 。
一個可以使用的polyfill的例子是ES Module Shims polyfill,它為任何支持ES模塊基線的瀏覽器(約94%的瀏覽器)添加了 import map 和其他新模塊特性的支持。我們所需要做的就是在 import map 腳本之前在HTML文件中包含es-module-shim腳本。
在包括polyfill之后,可能會在你的控制臺中得到一個JavaScript TypeError。這個錯誤可以被安全地忽略,因為它不會產(chǎn)生任何面向用戶的后果。
總結(jié)
import map提供了一種更理智的方式來在瀏覽器中使用ES模塊,而不局限于從相對或絕對的URL中導(dǎo)入。這使得我們可以很容易地移動代碼,而不需要調(diào)整 import語句,并使個別模塊的更新更加無縫,而不影響依賴這些模塊的腳本的緩存能力??偟膩碚f,import map為ES模塊在服務(wù)器和瀏覽器中的使用方式帶來了平等性。
網(wǎng)頁標(biāo)題:Type="Module"你了解,但Type="Importmap"你知道嗎?
鏈接地址:http://www.dlmjj.cn/article/djdojce.html


咨詢
建站咨詢
