<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          在Nodejs或瀏覽器運行ESM代碼

          共 3100字,需瀏覽 7分鐘

           ·

          2021-10-08 17:38

          前言

          經(jīng)典面試題目就是《Common.js 和 ES module 的區(qū)別》,這一題很多人都會熟練地背出答案。

          Commonjs

          • CommonJs 可以動態(tài)加載語句,代碼發(fā)生在運行時
          • CommonJs 導(dǎo)出值是拷貝, 不好排查引起變量污染

          ES module(后續(xù)簡稱 esm)

          • ESM 是靜態(tài)的,代碼發(fā)生在編譯時
          • ESM 導(dǎo)出是引用值之前都存在映射關(guān)系,并且值都是可讀的,不能修改 參考聊聊什么是 CommonJs 和 Es Module 及它們的區(qū)別[1]

          esm 是 JavaScript 模塊化的未來。因為它解決了變量污染,代碼維護,代碼依賴的問題。它讓你的代碼更加科學(xué)。這也是 deno 默認采用 esm 的原因。

          回歸正題,我們有什么方法在 Nodejs 或者瀏覽器直接運行 esm 代碼,這是個有趣而又實際的問題。

          如何在 Nodejs 環(huán)境允許

          1.利用編譯工具運行 esm

          最常見的方式是利用webpack[2]等打包工具搭配 babel 使用。隨著 webpack 和 vue 的大熱,這些工具似乎成為了標配,但是 webpack 的缺點也很明顯,它能讓 commonjs 和 esm 的混寫,導(dǎo)致代碼存在一些寫法不規(guī)范的情況,我相信這種情況是普遍出現(xiàn)在業(yè)務(wù)代碼里面,也存在于 antd3 這樣的知名第三方組件庫中。

          rollup[3]則是基于 ES6 的語法規(guī)范進行編譯,它的輕便小巧,非常適合 npm 庫的打包。新興的打包工具例如esbuild[4]和swc[5],也可以實現(xiàn)編譯打包,即使速度越來越快,但是還是需要編譯的過程。這些倉庫很重要的一個特點就是使用 esm 語法。

          以上這些工具都可以應(yīng)用于 esm 語法編譯,但是有很多項目不一定需要打包編譯這樣耗時的流程的,例如一些 cli 工具、簡易微服務(wù)等,如何保證高效正確的運行 esm 代碼呢?

          2. 利用第三方庫運行 esm

          在 Nodejs 版本較低的情況,我們可以利用一些工具,工具的使用形式有幾種,一種是 Module Loader,另一種是 Command Line(簡稱為 cli)。

          Module Loader,這里介紹standard-things/esm[6],它可以 preload 第三方提供的 esm 包,從此,可以做到 babelless, bundleless。你不需要使用大型編譯工具也可以直接運行 esm 代碼,使用方式如下。

          node -r esm index.js

          同樣,egoist/esbuild-register[7]這個庫在 esbuild 的支持下,同樣可以做到 Module Loader 的效果,利用 esbuild 的高性能特性,代碼運行效率更高。

          node -r esbuild-register index.js

          Command Line,基于封裝后的 cli,不過是換一種形式進行模塊的提前處理。babel-node[8]直接利用它的 babel 語法優(yōu)勢來運行 esm 代碼。由于 babel 本身還是 js 的實現(xiàn),它的官方文檔也表明了不建議在生產(chǎn)環(huán)境使用,會導(dǎo)致內(nèi)存高占用的問題,這也是這一類工具的通病。

          babel-node index.js

          同樣,esno[9]可以直接在命令行運行 esm 代碼。原理基于 esbuild。在這里更推薦使用這種方式,鑒于 esbuild 是由 go 語言實現(xiàn),能夠較大程度解決內(nèi)存高占用的問題,保證了一定的執(zhí)行性能。

          esno index.ts
          esmo index.ts

          這一類第三方倉庫適合在低版本 nodejs 且非生產(chǎn)環(huán)境使用,它們的存在是為了便利性,而并非實用性和穩(wěn)定性。怎么樣才能高效地運行 esm 代碼?

          3.Native Nodejs 運行 esm

          Node verison 13.2.0 起開始正式支持 ES Modules 特性

          所以利用 Native Nodejs 環(huán)境運行 esm 代碼是非常必要的,高版本的 Nodejs 提供了直接運行 esm 的功能,這里建議使用 lts14 版本。有兩種方式運行 esm 代碼:

          第一種,package.json 中填寫 type: "modules",表明模塊的類型。此后,直接運行node index.js即可。

          // pakage.json
          {
          ...
          "type": "modules"
          }

          第二種,則是將文件名改成.mjs,標明該文件是 esm 代碼。這兩種方式最大的區(qū)別則是模塊作用域。前者是包的作用域,它的聲明是以 package 為維度。后者則是以文件為維度,不受限于包的作用域。

          如何在瀏覽器運行 esm

          6f25eb16bad196e471d15cb49780d02b.webp

          瀏覽器script type="module"兼容性

          瀏覽器的情況有別于 Nodejs 環(huán)境,在大部分的新版本瀏覽器都支持 esm 的運行。esm 級別的代碼編譯和打包,可以有效地減少包的體積和資源傳輸速度。這也是為什么像 vite 這樣的框架會采用現(xiàn)代瀏覽器的打包模式(外加 legacy 兼容模式)的原因。具體的原理是在 html 當中的 script 標簽加入type="module" 則表明它引入的是 esm 代碼,當舊瀏覽器沒法支持 esm 的情況下,它會讀取nomodule script中的地址,讀取兼容版本的 js 代碼。這樣一來,可以有效地減少大部分瀏覽器加載的 js 體積,又保證了老瀏覽器的兼容性問題。

          <script type="module" src="dist/index.js">script>
          <script nomodule src="dist/index.legacy.js">script>

          總結(jié)

          如今 Nodejs 和瀏覽器環(huán)境都能對 esm 語法有了很好的 Native 支持。作為前端工程師的我們,應(yīng)該要保持著技術(shù)的前瞻性,在寫一個倉庫的時候,我們要想到要用 typescript,esm 還是 common.js 呢?為什么我們不選擇比較新的 js 運行環(huán)境,迎接 Javascript 的第三個時代,參考《ESM Import 與 Bundleless》[10]。

          參考資料

          2020 年我們可以在 Node 中使用 ES Modules 了嗎[11]

          參考資料

          [1]

          聊聊什么是 CommonJs 和 Es Module 及它們的區(qū)別: https://juejin.cn/post/6938581764432461854

          [2]

          webpack: https://webpack.js.org/

          [3]

          rollup: https://github.com/rollup/rollup

          [4]

          esbuild: https://github.com/evanw/esbuild

          [5]

          swc: https://github.com/swc-project/swc

          [6]

          standard-things/esm: https://github.com/standard-things/esm

          [7]

          egoist/esbuild-register: https://github.com/egoist/esbuild-register

          [8]

          babel-node: https://babeljs.io/docs/en/babel-node

          [9]

          esno: https://github.com/antfu/esno

          [10]

          《ESM Import 與 Bundleless》: https://www.jianshu.com/p/ab0d5cc9b062

          [11]

          2020 年我們可以在 Node 中使用 ES Modules 了嗎: https://zhuanlan.zhihu.com/p/337796076


          瀏覽 124
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情五月丁香婷婷 | 丁香婷婷综合网 | 日韩国产一区 | 国产大鸡吧在线观看 | 国产免看一级a一片成人aⅴ |