日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

浏览器中的 ESM

發布時間:2023/12/9 HTML 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浏览器中的 ESM 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

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

模塊化發展

1、為何要模塊化

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

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

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

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

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

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

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

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

2、模塊化的作用

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

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

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

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

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

  • 將各個庫打包成一個js boundle

  • 開啟服務,托管資源

  • 瀏覽器獲取資源

  • 執行代碼

  • 瀏覽器端ESM執行流程

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

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

  • 構建

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

  • 模塊映射

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

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

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

  • 3、為什么火起來

    • ES語法基本確定

    • http2普及

    • 新瀏覽器普及

    • 開發與發布代碼一致

    • 啟動快

    • 全新加載模式

    目前瀏覽器支持:

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

    4、為什么還沒火起來

    • 部分瀏覽器的兼容性

    • 歷史包袱悠久

    • 生態不完善

    實戰

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

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

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

    2. 依賴庫加載

    • node_modules代碼服務化

    • 兼容cjs

  • 加載包內部es目錄

  • cjstoesm

    • CDN(network for npm)

  • https://unpkg.com/

  • 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

    • 托管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",并且在代碼中使用 import 和 export 。同時,更多的模塊功能也正在研究中。比如動態導入提案已經處于 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


    總結

    以上是生活随笔為你收集整理的浏览器中的 ESM的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。