瀏覽器中的 ESM

大家好,我是若川。最近組織了源碼共讀活動,感興趣的可以加我微信?ruochuan12

早期的web應用非常簡單,可以直接加載js的形式去實現。隨著需求的越來越多,應用越做越大,需要模塊化去管理項目中的js、css、圖片等資源。這里有很多大家熟悉的模塊化標準, CJS、AMD、CMD、UMD 等等。模塊化提供了我們更好的方式來組織和維護函數以及變量。而在 npm 生態開發的背景下,CJS 模塊是開發過程中接觸最多也是無法避免的。但由于瀏覽器并不能直接執行基于 CJS 打包的模塊,因此類似 webpack 等打包工具便應運而生。隨著webpack 大有一統構建工具的趨勢下,JavaScript 官方的標準化模塊系統ESM完成了。本文主要介紹下模塊化標準間差異、基本加載原理。

模塊化發展

1、為何要模塊化

仔細想想,用 JavaScript 編碼就是管理變量。這一切都是關于為變量賦值,或為變量添加數字,或將兩個變量組合在一起并將它們放入另一個變量中。

18b0dce1b5643310eeab66323cfdfaba.png

如果代碼中僅有少量的變量,那么組織起來其實是很簡單的。一旦有很多的變量,我們會通過函數作用域去組織變量。因為函數作用域的緣故,一個函數無法訪問另一個函數中定義的變量。

如果只維護少量變量非常簡單。但是如果有很多的變量,我們就需要用一種方法來幫助做到這一點,叫做作用域。由于作用域在 JavaScript 中的工作方式,函數不能訪問在其他函數中定義的變量。

fcd2de9bb092853f6da23f47e3765af0.png

這種方式是很有效的。在寫一個函數的時候,只需要考慮當前函數,而不必擔心其它函數可能會改變當前函數的變量。如果想要函數之間共享變量要怎么辦呢?一種通用的做法是全局作用域。

在 jQuery 時代這種提升做法相當普遍。在我們加載任何 jQuery 插件之前,我們必須確保 jQuery 已經存在于全局作用域。

98485ede48230781e3b88e5b1e457ac5.png

所有的 <script> 必須以正確的順序排列,必須保證被依賴的變量先加載。如果排列錯了,那么在運行過程中,應用將會拋出錯誤,并且停止繼續運行。

代碼之間的依賴是不透明的。這使得代碼維護變得困難。代碼變得充滿不確定性。任何函數都可能依賴全局作用域中的任何變量。

其次,由于變量存在于全局作用域,所以任何代碼都可以改變它。

2、模塊化的作用

模塊化為你提供了一種更好的方式來組織變量和函數。可以把相關的變量和函數放在一起組成一個模塊。這種實現形式可以把函數和變量放在模塊作用域中。模塊作用域還提供一種暴露變量給其他模塊使用的方式。模塊可以明確地指定哪些變量、類或函數對外暴露。

對外暴露的過程稱為導出。一旦導出,其他模塊就可以明確地聲稱它們依賴這些導出的變量、類或者函數。

95a7ee95e3d9085d220da3f52fb318f9.png

因為這是一種明確的關系,所以你可以很簡單地辨別哪些代碼能移除,哪些不能移除。

擁有了在模塊之間導出和導入變量的能力之后,你就可以把代碼分割成更小的、可以獨立運行地代碼塊了。基于這些代碼塊,你就可以像搭樂高積木一樣,創建所有不同類型的應用。比較流程的規范有CommonJS,AMD,CMD,ES,UMD等

3、現有模塊標準

CJS?是?CommonJS?的縮寫。只適用于node端:

const _ = require('lodash'); module.exports = function doSomething(n) {}

AMD?代表異步模塊定義。在瀏覽器端有效:

define(['dep1', 'dep2'], function (dep1, dep2) {return function () {};
});

UMD?代表通用模塊定義(Universal Module Definition):

(function (root, factory) {if (typeof define === 'function' && define.amd) {// AMD. Register as an anonymous module.define([], factory);} else if (typeof module === 'object' && module.exports) {// Node. Does not work with strict CommonJS, but// only CommonJS-like environments that support module.exports,// like Node.module.exports = factory();} else {// Browser globals (root is window)root.returnExports = factory();}
}(typeof self !== 'undefined' ? self : this, function () {// Just return a value to define the module export.// This example returns an object, but the module// can return a function as the exported value.return {};
}));

什么是 ESM

簡介

ESM是ES6提出的標準模塊系統,ECMAScript modules。JS自己的模塊體系

<script type="module">import { html, Component, render } from 'https://unpkg.com/htm/preact/standalone.module.js';class App extends Component {state = {count: 0}add = () => {this.setState({ count: this.state.count + 1 });}render() {return html`<div class="app"><div>count: ${this.state.count}</div><button onClick=${this.add}>Add Todo</button></div>`;}}render(html`<${App} page="All" />`, document.body);
</script>

思考:上述代碼和在webpack中開發有啥區別?

2、瀏覽器端技術實現

回顧下Webpack執行流程

  1. 本地模塊化解析(通過webpack或者babel,將import解析成cjs)

  2. 將各個庫打包成一個js boundle

  1. 開啟服務,托管資源

  2. 瀏覽器獲取資源

  1. 執行代碼

瀏覽器端ESM執行流程

  1. 開啟服務,托管資源(ES源碼)

  2. 加載入口文件,瀏覽器模塊化解析

    47cf87ba58bdeb0f56e1a696a97cb838.png

  3. 構建

    1. 遍歷依賴樹,先解析文件,然后找出依賴,最后又定位并加載這些依賴,如此往復。(下載所有的js)

      99e825b667bb8143496cb0c585a13c70.png

    2. 模塊映射

      當加載器要從一個 URL 加載文件時,它會把 URL 記錄到模塊映射中,并把它標記為正在下載的文件。然后它會發出這個文件請求并繼續開始獲取下一個文件。

      480dffbfc210687aa585d23831ca212b.png

    3. 解析模塊
      所有的模塊都按照嚴格模式來解析的。不同文件類型按照不同的解析方式稱。在瀏覽器中,通過 type="module" 屬性告訴瀏覽器這個文件需要被解析為一個模塊。不過在 Node 中,我們并不使用 HTML 標簽,所以也沒辦法通過 type 屬性來辨別。社區提出一種解決辦法是使用 .mjs 拓展名。

  1. 運行
    采用深度優先的后序遍歷方式,順著關系圖到達最底端沒有任何依賴的模塊,然后設置它們的導出。模塊映射會以 URL 為索引來緩存模塊,以確保每個模塊只有一個模塊記錄。這保證了每個模塊只會運行一次。

3、為什么火起來

  • ES語法基本確定

  • http2普及

  • 新瀏覽器普及

  • 開發與發布代碼一致

  • 啟動快

  • 全新加載模式

目前瀏覽器支持:

86356fa04ef755e150d5a3ee6aadb9f0.png

a237c2f4774df7880994fe35b90272e0.png

5e24b6a8e4e61b45d6c24f005cd37d30.png

e92234d971bda3cdcdbb103be80a7be5.png

6374a0f2228808a415cc77d6576484d5.png

目前只有5%的瀏覽器不兼容es相關規范。

4、為什么還沒火起來

  • 部分瀏覽器的兼容性

  • 歷史包袱悠久

  • 生態不完善

實戰

當我們在項目中使用需要考慮以下幾個問題點

1. 代碼開發需要基于es開發

let a = 1;
new Promise()
() => {}
...

2. 依賴庫加載

  • node_modules代碼服務化

  • 兼容cjs

    1. 加載包內部es目錄

    2. cjstoesm

c30923406ac07add1128d1db22347c18.png

  • CDN(network for npm)

    1. https://unpkg.com/

    2. https://www.skypack.dev/

3. 兼容不支持的瀏覽器

  • type="module"實現

    • 如果瀏覽器不支持,他只識別type="text/javascript"不識別 type="module" ,故不下載js;如果支持,則會下載js

    • 如果瀏覽器不支持,則會忽略nomodule,下載js;如果支持,則不會下載js

<script type="module" src="app.js"></script>
<script nomodule src="app-bundle.js"></script>
  • systemjs實現https://github.com/systemjs/systemjs

<script src="system.js"></script>
<script type="systemjs-importmap">
{"imports": {"lodash": "https://unpkg.com/lodash@4.17.10/lodash.js"}
}
</script>
<script type="systemjs-module" src="/js/main.js"></script>

4. jsx支持

  • 通過其他開源庫

<script type="module">import { html, Component, render } from 'https://unpkg.com/htm/preact/standalone.module.js';class App extends Component {render() {return html`<div class="app"></div>`;}}render(html`<${App} page="All" />`, document.body);
</script>
  • 本地語法糖解析

<APP {...Props}/>
=>
React.createElement(App, {...props})

現有腳手架

1. snowpack

4bb0dccb70e4f5d4d8f0ee80d4369923.png

  • 托管node_modules

  • 支持圖片、css等資源

  • JSX 和 Typescript 編譯

  • HMR

  • ...

2. vite

https://cn.vitejs.dev/guide/

目前snowpack的作者后續可能不再維護了,所以推薦大家使用vite

ESM 未來

2018 年 5 月 Firefox 60 發布后,所有的主流瀏覽器就都默認支持 ESM 了。Node 也正在添加 ESM 支持,為此還成立了工作小組來專門研究 CJS 和 ESM 之間的兼容性問題。所以,在未來你可以直接在 <script> 標簽中使用 type="module",并且在代碼中使用 importexport 。同時,更多的模塊功能也正在研究中。比如動態導入提案已經處于 Stage 3 狀態;import.meta也被提出以便 Node.js 對 ESM 的支持;模塊定位提案 也致力于解決瀏覽器和 Node.js 之間的差異。

相信在不久的未來,跟模塊一起玩耍將會變成一件更加愉快的事!

node v10以上版本全部支持ESM https://kentcdodds.com/blog/super-simple-start-to-es-modules-in-node-js

相關參考

ECMAScript modules in browsers https://jakearchibald.com/2017/es-modules-in-browsers/

JavaScript 模塊現狀 https://zhuanlan.zhihu.com/p/26567790

基于esm、html、unpkg的前端開發模式:https://github.com/developit/htm

How I Build JavaScript Apps In 2021:https://timdaub.github.io/2021/01/16/web-principles/

Find out how much turning on modern JS could save. https://estimator.dev/

什么是amd、commonjs、umd、esm? https://zhuanlan.zhihu.com/p/96718777

ES modules: A cartoon deep-dive:https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/

import.map:https://github.com/WICG/import-maps

面對 ESM 的開發模式,webpack 還有還手之力嗎? https://topic.atatech.org/articles/202736


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275287.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275287.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275287.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

理解面向連接和無連接協議之間的區別

理解面向連接和無連接協議之間的區別 網絡編程中最基本的概念就是面向連接&#xff08;connection-oriented&#xff09;和無連接&#xff08;connectionless&#xff09;協議。 面向連接和無連接指的都是協議。也就是說&#xff0c;這些術語指的并不是無理介質本身&#xff0c…

標記圖標_標記您的圖標

標記圖標Not labeling your icons is the same as assuming that we are all fluent in ancient hieroglyphics. Are you? Can you just walk up to Cleopatras needle and read it like you could read a childrens book? Even emojis, our modern hieroglyphics dont mean …

找出無序數組中最小的k個數(top k問題)

2019獨角獸企業重金招聘Python工程師標準>>> 給定一個無序的整型數組arr&#xff0c;找到其中最小的k個數 該題是互聯網面試中十分高頻的一道題&#xff0c;如果用普通的排序算法&#xff0c;排序之后自然可以得到最小的k個數&#xff0c;但時間復雜度高達O(NlogN)&…

你應該知道的 Node 基礎知識

大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12 參與&#xff0c;已進行兩個多月&#xff0c;大家一起交流學習&#xff0c;共同進步。源碼共讀學的多數是 Node.js &#xff0c;今天分享一篇 Node.js 基礎知識的文章。一. N…

C# 中數據緩存總結

在C#嘗試了5種方法進行數據緩存&#xff0c;具體如下&#xff1a;(如有遺漏&#xff0c;錯誤歡迎大家指正&#xff0c;歡迎提建議。)1&#xff1a;Session方法&#xff1a;此方法是針對于每個用戶來的&#xff0c;如果用戶量比較大&#xff0c;那么建議不要采用此方法&#xff…

react 引入 mobx @babel/core: 7.2.2

為什么80%的碼農都做不了架構師&#xff1f;>>> yarn add babel/plugin-proposal-class-propertiesyarn add babel/plugin-proposal-decorators"babel": {"plugins": [["babel/plugin-proposal-decorators", {"legacy": …

面試官問:怎么自動檢測你使用的組件庫有更新

大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12本文來自V同學投稿的源碼共讀第六期筆記&#xff0c;寫得很有趣。現在已經進行到第十期了。你或許經常看見 npm 更新的提示。npm 更新提示面試官可能也會問你&#xff0c;組件庫…

設計模式完整備忘錄

小言&#xff1a;這不是設計模式講解型博文&#xff0c;以下將設計模式的概述、類圖&#xff0c;代碼示例&#xff0c;總結分每篇博文單獨展示&#xff0c;現將其歸類&#xff0c;便于以后翻閱&#xff0c;設計模式也不是一兩個月學完了就能完全領悟&#xff0c;它只告訴我們幾…

使用Microsoft Web Application Stress Tool對web進行壓力測試

你的Web服務器和應用到底能夠支持多少并發用戶訪問&#xff1f;在出現大量并發請求的情況下&#xff0c;軟件會出現問題嗎&#xff1f;這些問題靠通常的測試手段是無法解答的。本文介紹 了Microsoft為這個目的而提供的免費工具WAS及其用法。另外&#xff0c;本文介紹了一種Web應…

2021前端高頻面試題整理,附答案

大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12若川視野原意是若川的前端視野。但太長了就留下了四個字&#xff0c;不知道的以為關注的不是技術公眾號。今天分享一篇慕課網精英講師河畔一角的好文章~廢話不多說&#xff0c;…

OO第二單元作業小結

總結性博客作業 第一次作業 (1)從多線程的協同和同步控制方面&#xff0c;分析和總結自己三次作業的設計策略。 第一次作業為單電梯傻瓜調度&#xff0c;可以采用生產者——消費者模型&#xff0c;是一個有一個生產者&#xff08;標準輸入電梯請求&#xff09;&#xff0c;一個…

dribbble加速vpn_關于Dribbble設計的幾點思考

dribbble加速vpn重點 (Top highlight)I’d like to start with the following quote from Paul Adam’s “The Dribbbilisation of Design,” a powerful read that examines the superficiality of modern product design portfolios, often containing Dribbble posts that l…

JS Compress and Decompress

<html><head><title>JavaScript字符串之壓縮與還原</title><meta http-equiv"Content-Type"content"text/html; charsetutf-8"/><script type"text/javascript"><!--/** * 壓縮 */functionCompress(strN…

尤雨溪推薦神器 ni ,能替代 npm/yarn/pnpm ?簡單好用!源碼揭秘!

1. 前言大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12想學源碼&#xff0c;極力推薦之前我寫的《學習源碼整體架構系列》jQuery、underscore、lodash、vuex、sentry、axios、redux、koa、vue-devtools、vuex4、koa-compose、…

如何了解自己的認知偏差_了解吸引力偏差

如何了解自己的認知偏差Let me introduce you the attractiveness bias theory known as cognitive bias.讓我向您介紹稱為認知偏差的吸引力偏差理論。 Think about a person with outstanding fashion. It will draw our attention, and maybe encourage us to interact with…

隱馬爾可夫模型(HMM)及Viterbi算法

HMM簡介 對于算法愛好者來說&#xff0c;隱馬爾可夫模型的大名那是如雷貫耳。那么&#xff0c;這個模型到底長什么樣&#xff1f;具體的原理又是什么呢&#xff1f;有什么具體的應用場景呢&#xff1f;本文將會解答這些疑惑。  本文將通過具體形象的例子來引入該模型&#xf…

尤大直播分享:vue3生態進展和展望

大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12前言10月23日&#xff0c;參加了前端早早聊組織的【vue生態專場】&#xff0c;準備寫一波分享方便大家學習。早上有4個話題&#xff1a;volar開發&#xff0c;搭建平臺組件開發…

利用Python查看微信共同好友

思路 首先通過itchat這個微信個人號接口掃碼登錄個人微信網頁版&#xff0c;獲取可以識別好友身份的數據。這里是需要分別登錄兩人微信的&#xff0c;拿到兩人各自的好友信息存到列表中。 這樣一來&#xff0c;查共同好友就轉化成了查兩個列表中相同元素的問題。獲取到共同好友…

女生適合學ux嗎_UX設計色彩心理學,理論與可訪問性

女生適合學ux嗎Colour is an interesting topic, which I feel is often overlooked and sometimes under-appreciated. One of the first things I was taught was the power of colour, how it can have an impact on human emotion, and that there should be purpose behin…

初學者也能看懂的 Vue2 源碼中那些實用的基礎工具函數

1. 前言大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12想學源碼&#xff0c;極力推薦之前我寫的《學習源碼整體架構系列》jQuery、underscore、lodash、vuex、sentry、axios、redux、koa、vue-devtools、vuex4、koa-compose、…