又新學到了一個 JavaScript 知識點 Import Maps
關於import maps
不知道大家有沒有聽過,我之前只是知道JavaScript
增加的新特性,具體什麼作用也沒有進行學習研究過,週末學習中看到有人使用它,於是也嘗試瞭解一下~,後來發現確實還是挺好用的,所以寫一篇文章給大家分享一下。
我主要從以下幾個方面來簡單介紹一下import maps
:
import maps
是什麼
import map
直譯過來是 導入映射,它與模塊的使用有關,一般我們在項目中導入模塊,會調用require
方法,或者使用import
語句或方法,引入的模塊通常使用 npm 之類的包管理器進行管理。但是import map
提供了一種支持,讓我們可以直接在頁面上管理模塊,不需要通過打包構建。
import maps
已經成爲了一個 Web 標準,並且在 2021 年 7 月正式通過了 W3C 的標準化流程;但是由於這個特性比較新,很多瀏覽器不支持,後面我們詳細聊聊兼容情況。
接下來看一下import map
怎麼工作的...
import maps
怎麼使用
在import maps
中,可以使用一個 JavaScript
對象來定義模塊標識符與對應 URL
的映射關係,例如:
<script type="importmap">
{
"imports": {
"lodash": "https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.js",
"react": "/node_modules/react/index.js"
}
}
</script>
在上述示例中,定義了 lodash
模塊的 URL
爲 https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.js,而 react
模塊的 URL
則爲相對路徑 /node_modules/react/index.js
。
通過importmap
,可以在模塊中使用字符串形式的模塊名稱來導入其他模塊,而不必關心實際模塊資源的 URL
,例如:
<script type="module">
import _ from "lodash";
import React from "react";
</script>
這樣,JavaScript
引擎會自動根據導入映射中定義的映射關係來加載模塊資源,並將其綁定到相應的模塊變量上。
總之import maps
使用其實非常的簡單,是通過在html
文檔的script
標籤中,使用json
對象來配置所有需要再當前 html 文檔中需要引入的模板。
如果這個json
映射表內容比較多,我們還可以將它放在其他文件中,然後通過src
屬性去鏈接它,例如:
<script scr="xxx_importmaps.json"></script>
上面一起簡單的認識了import maps
相信不少人和我一樣,都在想一個問題,這種實現方式有什麼優勢呢,或者說究竟能解決哪些問題, 帶着疑問我們進入下一節
import maps
有何優勢?
換句話說,我們需要先知道import maps
可以用來做什麼?
動態加載模塊
import maps
支持動態加載模塊,可以在需要的時候才進行加載,避免了一次性加載所有模塊的開銷,提高了應用程序的性能和用戶體驗。
這裏舉例說明一下,例如在 Vue2
的項目中,文章頁面支持播放視頻,但是文章中沒有視頻時,我可以不用加載播放器, 項目中動態加載 player.min.js
:
- 首先在
index.html
文件中添加import maps
<head>
<script type="importmap">
{
"imports": {
"player": "https://example.com/path/to/player.min.js"
}
}
</script>
</head>
- 在 Vue 組件中動態加載
player.min.js
文件
可以在需要使用播放器的 Vue 組件中使用動態加載 player.min.js
文件的代碼,例如:
export default {
data() {
return {
player: null,
};
},
methods: {
loadPlayer() {
if (this.player) {
return Promise.resolve(this.player);
}
return import('player').then((Player) => {
this.player = new Player.default();
return this.player;
});
},
play() {
this.loadPlayer().then((player) => {
player.play();
});
},
},
};
減少網絡請求
使用 import maps
可以減少網絡請求的主要原因是,可以將多個模塊合併成一個請求,從而減少了網絡請求的次數,提高了頁面的加載速度。
如果一個頁面需要引入多個模塊,如果不使用import maps
,每個模塊都需要通過一個獨立的請求進行加載。而使用 import maps
,可以將多個模塊合併成一個請求,從而減少了網絡請求的次數。例如:
<script type="importmap">
{
'lodash': 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js',
'vue': 'https://cdn.jsdelivr.net/npm/vue@3.0.0/dist/vue.esm-browser.js',
'axios': 'https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js'
};
</script>
// 定義一個映射表
// 加載模塊
Promise.all([
import('lodash'),
import('vue'),
import('axios')
]).then(([ _, { createApp }, axios ]) => {
const app = createApp({ /* ... */ });
axios.get(/* ... */);
});
在上面的代碼中,在加載模塊時,我們使用了 Promise.all
方法將多個模塊的導入操作合併到一個 Promise
對象中,這樣瀏覽器就可以將多個模塊的請求合併成一個請求,從而減少了網絡請求的次數。需要注意的是,在使用 import maps
減少網絡請求時,我們需要避免將過多的模塊合併到一個請求中,否則可能會導致請求過大,影響頁面的加載速度。通常建議將多個模塊合併到一個請求中時,選擇具有相似功能或關聯度高的模塊進行合併,同時需要進行適當的測試和優化,以確保頁面的加載速度和性能。
模塊依賴關係管理
通過在import maps
中定義模塊之間的依賴關係,可以更加方便地進行依賴管理,並且可以在不同的環境中(例如開發環境和生產環境)使用不同的導入映射,從而更好地控制依賴關係。假設我們有一個頁面需要加載三個模塊:module1.js
、module2.js
和 module3.js
。其中,module2.js
和 module3.js
依賴於 module1.js
,也就是說,需要先加載 module1.js
,再加載 module2.js
和 module3.js
。在不使用 Import Maps 的情況下,我們需要手動管理這些模塊的加載順序,代碼如下:
// 加載模塊 1
const script1 = document.createElement('script');
script1.src = 'module1.js';
script1.onload = () => {
// 加載模塊 2
const script2 = document.createElement('script');
script2.src = 'module2.js';
script2.onload = () => {
// 加載模塊 3
const script3 = document.createElement('script');
script3.src = 'module3.js';
document.head.appendChild(script3);
};
document.head.appendChild(script2);
};
document.head.appendChild(script1);
上面的代碼中,我們通過創建 script
標籤來加載模塊,並使用 onload
事件來控制模塊的加載順序,保證模塊的依賴關係正確。這種方式需要手動管理模塊的加載順序,代碼比較冗長,且容易出錯。
使用 Import Maps 可以簡化這個過程,代碼如下:
<script type="importmap">
{
'module1': 'module1.js',
'module2': { deps: ['module1'], url: 'module2.js' },
'module3': { deps: ['module1'], url: 'module3.js' },
};
</script>
// 加載模塊
Promise.all([
import(moduleMap['module1'].url),
import(moduleMap['module2'].url),
import(moduleMap['module3'].url),
]).then(([module1, module2, module3]) => {
// ...
});
其中每個模塊都定義了其依賴關係和對應的 URL。然後在加載模塊時,我們只需要按照模塊依賴關係的順序,依次導入每個模塊即可,不需要手動管理模塊的加載順序。這種方式代碼比較簡潔,且可以更好地管理模塊的依賴關係。
其他用法
動態構建 import map
import maps
可以根據條件任意的動態配置,這個能力就相當於支持了動態加載模塊,可以在需要的時候才進行加載,避免一次性加載所有的模塊,提高應用程序的性能和用戶體驗。這裏舉例說明一下,例如我的文章頁面支持播放視頻,但是文章中沒有視頻,我可以不用加載播放器:
<script>
const importMap = {
imports: {
lazyload: "player.min.js",
},
};
const imp = document.createElement('script');
imp.type = 'importmap';
imp.textContent = JSON.stringify(importMap);
document.currentScript.after(im);
</script>
這種方式需要確保創建和插入 import map
腳本標籤之前進行(如上所述),因爲修改一個已經存在的import map
對象不會有任何效果。
import maps
引入同一個包的不同版本
通過import maps
引入同一個包的不同版本是一件非常簡單的事情,你只需要把不同版本的標識符在映射中寫出來就行。就像下面這樣。
<script type="importmap">
{
"imports": {
"vue@2/": "https://cdn.jsdelivr.net/npm/vue@2.0.0/dist/vue.esm-browser.js",
"vue@3/": "https://cdn.jsdelivr.net/npm/vue@3.0.0/dist/vue.esm-browser.js"
}
}
</script>
import maps
can i use
最後說一下關於import maps
的兼容性問題,首先上一張can i use
上的截圖:
目前已經得到了多個主流瀏覽器的支持,但還沒有被所有瀏覽器兼容。特別國內常用的QQ瀏覽器
、安卓手機常用的UC瀏覽器
等。
然而,對於一些舊版本的瀏覽器或者不支持導入映射的瀏覽器,可以通過使用 polyfill
或者額外的加載器庫(如 SystemJS
)來實現導入映射的功能。
總之,雖然導入映射已經得到了多個主流瀏覽器的支持,但在開發過程中需要考慮到不同瀏覽器的兼容性問題。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/yXg9Aa20MTjnFdF47QQlyA