在瀏覽器中使用ES6的模塊功能 import 及 export

感謝英文原做者 Jake Archibald 的技術分享javascript

各個瀏覽器對於ES6模塊 import 、 export的支持狀況java

  • Safari 10.1.
  • Chrome 61.
  • Firefox 54 – behind the dom.moduleScripts.enabled setting in about:config.
  • Edge 16.

clipboard.png

ES6 import 和 export 在瀏覽器當中的使用

1.顯示聲明type="module"

script 裏面要加 type="module", 這樣瀏覽器纔會把相關的代碼看成ES6的module 來對待
<script type="module"> 
    import {addTextToBody} from './utils.js'; 
    addTextToBody('Modules are pretty cool.'); 
</script>

2.不能寫「裸」路徑如:

<script type="module"> 
    import {addTextToBody} from 'utils.js';  // error
    addTextToBody('Modules are pretty cool.'); 
</script>

直接寫 'utils.js' 會報錯
你能夠寫絕對路徑和相對路徑, 可是不能直接寫文件名,即便是同一層級下面的文件。也要加上 './name.js'
文件名後綴 .js 必需要有,否則瀏覽器沒法識別路徑。跨域

3.如何向下兼容

使用 "nomodule" 關鍵字來實現瀏覽器的向下兼容
<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>

我是這樣理解的,老的瀏覽器自己不會識別type="module" js,也就不會去有執行有type="module" 的js代碼(可是仍是會下載的哈)。
也不識別 nomodule 關鍵字,因此它會忽略nomodule,即正常執行這個有nomodule標識的js。
而支持type=「module」的瀏覽器,它會自動不去執行有nomodule關鍵字的js。甚至連下都不去下載。
因此向下兼容的功能就走通了(這個你們用不一樣的瀏覽器試試,馬上能夠明白)瀏覽器

惟一的問題,還有一類瀏覽器,它支持 type="module" 的 ES6特性,可是它不支持nomodule關鍵字。也就是說,即便有nomodule標識,它仍是會去下載而且執行這個js。即便它已經執行了 type=「module」的 js。
這些瀏覽器有服務器

  • Firefox doesn't support nomodule (issue). Fixed in Firefox nightly!
  • Edge doesn't support nomodule (issue). Fixed in Edge 16!
  • Safari 10.1 doesn't support nomodule. Fixed in Safari 11!

4.默認加載方式

type=「module」的加載方式默認使用 defer的加載方式。

關於defer 和 async :defer和async 都是異步加載代碼。可是defer要等到整個頁面在內存中正常渲染結束(DOM 結構徹底生成,以及其餘腳本執行完成),纔會執行。 async一旦下載完,渲染引擎就會中斷渲染,執行這個腳本之後,再繼續渲染。 一句話,defer是「渲染完再執行」,async是「下載完就執行」。另外,若是有多個defer腳本,會按照它們在頁面出現的順序加載,而多個async腳本是不能保證加載順序的。dom

<!-- This script will execute after… -->
<script type="module" src="1.js"></script>

<!-- …this script… -->
<script src="2.js"></script>

<!-- …but before this script. -->
<script defer src="3.js"></script>
內聯的 <script> 也是採用的 defer加載模式
<!-- This script will execute after… -->
<script type="module">
  addTextToBody("Inline module executed");
</script>

<!-- …this script… -->
<script src="1.js"></script>

<!-- …and this script… -->
<script>     //這裏默認採用defer,避免歧義,建議手動加上
  addTextToBody("Inline script executed");
</script>

<!-- …but before this script. -->
<script defer src="2.js"></script>

而若是是傳統的script 內聯js,調用的那個js文件在後面的話,會報錯。異步

<!-- This script will throw error… -->
<script defer>     //這裏就算採用defer也會報錯
  addTextToBody("Inline module executed");
</script>

<script>     
  addTextToBody("Inline script executed");
</script>

5.支持async的加載方式

type="module" 也可使用 async 的方式進行加載(包括其內聯的 import),等同普通 js 採用 async 進行加載的方式
<script type="module" async></script>

Browser issues
Firefox doesn't support async on inline module scripts (issue)async

6.只執行一次

<script type="module"> 只執行一次同ES6的加載機制,屢次import 只會被當成一次import處理
<!-- 1.js 只會被加載執行一次-->
<script type="module" src="1.js"></script>
<script type="module" src="1.js"></script>
<script type="module">
  import "./1.js";
</script>

<!--  普通JS 也只會被加載一次,可是會被執行屢次-->
<script src="2.js"></script>
<script src="2.js"></script>

Browser issues
Edge executes modules multiple times (issue). Fixed, but not yet shipped (expect Edge 17 to ship with the fix).this

7.關於CORS

type="module" 默認不支持跨域,這一點兒與傳統js或圖片徹底不同。傳統js或圖片默認就是支持跨域的。若是你想 type="module" 支持跨域。須要在從服務器返回的header上顯示的給予有效的 CORS聲明

Access-Control-Allow-Origin: * spa

Browser issues
Firefox fails to load the demo page (issue).
Edge loads module scripts without CORS headers (issue). Fixed in Edge 16!

9.Mime-types

不一樣於傳統的 <scripts>, <script type="module"> 必須向瀏覽器提供有效的 javascript MIME types。
否則請求到的模塊javascript不會執行
clipboard.png

Browser issues
Edge executes scripts with invalid MIME types (issue).

最後還想說

沒想到任何一個小功能,仔細去研究都有這麼多的知識點。碼文不易,各位給個贊可好。
轉載請註明出處
相關文章
相關標籤/搜索