亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

rollup輸出的6種格式詳解

 更新時(shí)間:2022年07月07日 10:13:30   作者:摸魚的春哥  
這篇文章主要為大家介紹了rollup輸出的6種格式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

學(xué)習(xí)本文 ??

之前找工作的時(shí)候因?yàn)樵诤?jiǎn)歷上寫“熟練使用 rollup.js 進(jìn)行構(gòu)建”,但回答不出 rollup 能打包出哪幾種格式,我差點(diǎn)被面試官鄙視。你將:

  • 弄明白vite和rollup輸出的幾種格式,了解它們之間的關(guān)系和使用場(chǎng)景。
  • 獲得一份最簡(jiǎn)單的 rollup.js 打包 demo 一份。
  • 這份 demo 還為每個(gè)打包結(jié)果準(zhǔn)備了一個(gè)可執(zhí)行 demo of demo

為什么要學(xué)這個(gè)?

伴隨著 vite.js 越來(lái)越火,它也變成了工作生產(chǎn)和面試問(wèn)答時(shí)被經(jīng)常提及的問(wèn)題。

眾所周知,vite.js 構(gòu)建的核心是 rollup.js。

那為什么在學(xué)習(xí)它們之前,有必要先學(xué)習(xí) js 模塊化規(guī)范?

因?yàn)槲覀冃枰斫馑鼈冏罱K的產(chǎn)物是什么,是如何運(yùn)作的。

“崇拜魔法”是編程學(xué)習(xí)者的大忌,“好奇心”才是我們成長(zhǎng)與進(jìn)步的階梯。

讓我們解開(kāi)神秘的面紗,看看那些打包后的代碼,都是些“什么玩意兒”!

DEMO與示例構(gòu)建

請(qǐng)配合 demo 食用,你會(huì)收獲更多!

我為本文構(gòu)建了一個(gè)簡(jiǎn)單的 demo 實(shí)例,源碼就放在 github 上。

demo 地址: github.com/zhangshichu…demo 的代碼結(jié)構(gòu)如下:

├── answer.js
├── index.js
├── out
├── package.json
├── rollup.config.js
└── yarn.lock

其中 index.jsanswer.js 屬于業(yè)務(wù)代碼,是需要被打包的對(duì)象。

index.js 中依賴了 answer.js。

如下:

// answer.js
export default 42
// index.js
import answer from "./answer";
import { repeat } from 'lodash'
// 定義一個(gè)無(wú)用變量, 測(cè)試 tree-shaking
const unusedVar = 'May the 4th'
export const printAnswer = () => {
  // 打印
  console.log(`the answer is ${answer}`)
  // 測(cè)試 lodash 的能力,打印42個(gè)1
  console.log(repeat('1', answer))
}

rollup.config.jsrollup 的配置文件,在此文件中我們分別指定其輸出 amd , cjs , esm , iife , umd , system 六種格式的文件。

輸出的文件會(huì)被打包到 out 文件夾下。

當(dāng)我們執(zhí)行 yarn build 或者 npm build 之后,會(huì)在 out 下產(chǎn)生如下格式的代碼:

├── out
│   ├── amd
│   │   └── bundle.js
│   ├── cjs
│   │   └── bundle.js
│   ├── ems
│   │   └── bundle.js
│   ├── iife
│   │   └── bundle.js
│   ├── system
│   │   └── bundle.js
│   └── umd
│       └── bundle.js

為了弄清楚每種格式的 bundle.js 文件是如何運(yùn)作的,我專門為它們訂制添加了一些附屬的小 demo。

接下來(lái),就讓我們一種格式一種格式地學(xué)習(xí)和分析吧。

一、IIFE 自執(zhí)行函數(shù)

IIFE 的全稱是 “immediately invoked function expression”。

1.1 打包結(jié)果分析

讓我們先看看本 demoiife 格式打出來(lái)的包長(zhǎng)什么樣。

對(duì)上述代碼做一些簡(jiǎn)化:

var Test = (function (exports, lodash) {
  'use strict'; // 自帶嚴(yán)格模式,避免一些奇怪的兼容性問(wèn)題
  /**
   * 下面折行無(wú)用代碼被 tree-shaking 掉了
   * const unusedVar = 'May the 4th'
   * */
  var answer = 42; // 業(yè)務(wù)中被單一引用的模塊,被直接抹平了
  const printAnswer = () => {
    console.log(`the answer is ${answer}`);
    console.log(lodash.repeat('1', answer));
  };
  exports.printAnswer = printAnswer; // 把要export的屬性掛在到exports上
  return exports;
})({}, $); // exports是第一個(gè)入?yún)?,依賴的jquery是第二個(gè)入?yún)?

IIFE 是前端模塊化早期的產(chǎn)物,它的核心思路是:

  • 構(gòu)建一個(gè)匿名函數(shù)
  • 立刻執(zhí)行這個(gè)匿名函數(shù),對(duì)外部的依賴通過(guò)入?yún)⒌男问絺魅?/li>
  • 返回該模塊的輸出

1.2 如何運(yùn)行

IIFE 的運(yùn)行其實(shí)很容易,如果它沒(méi)有其他依賴,只需要去引入文件,然后在 window 上取相應(yīng)的變量即可。
如:

  <script src="http://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  <script> 
    // jquery 就是典型的自執(zhí)行函數(shù)模式,當(dāng)你引入后,他就會(huì)掛在到 window.$ 上
    window.$ // 這樣就能取到 jquery 了
  </script>

但是如果你像本 demo 中那樣依賴了其他的模塊,那你就必須保證以下兩點(diǎn)才能正常運(yùn)行:

  • 此包所依賴的包,已在此包之前完成加載。
  • 前置依賴的包,和 IIFE 只執(zhí)行入?yún)⒌淖兞棵且恢碌摹?/li>

以本 demoIIFE 構(gòu)建結(jié)果為例:

  • 它前置依賴了 lodash,因此需要在它加載之前完成 lodash 的加載。
  • IIFE 的第二個(gè)入?yún)⑹?lodash,作為前置條件,我們需要讓 window.lodash 也指向 lodash

因此,運(yùn)行時(shí),代碼如下:

<head>
  <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
  <script>window.lodash = window._</script>  
  <script src="./bundle.js"></script>
</head>
<body>
  <script>
    window.Test.printAnswer();
  </script>
</body>

1.3 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 通過(guò)閉包營(yíng)造了一個(gè)“私有”命名空間,防止影響全局,并防止被從外部修改私有變量。
  • 簡(jiǎn)單易懂
  • 對(duì)代碼體積的影響不大

缺點(diǎn):

  • 輸出的變量可能影響全局變量;引入依賴包時(shí)依賴全局變量。
  • 需要使用者自行維護(hù) script 標(biāo)簽的加載順序。

優(yōu)點(diǎn)就不細(xì)說(shuō)了,缺點(diǎn)詳細(xì)解釋一下。

缺點(diǎn)一:輸出的變量可能影響全局變量;引入依賴包時(shí)依賴全局變量。

前半句:輸出的變量可能影響全局變量; 其實(shí)很好理解,以上面 demo 的輸出為例: window.Test 就已經(jīng)被影響了。
這種明顯的副作用在程序中其實(shí)是有隱患的。

后半句:引入依賴包時(shí)依賴全局變量; 我們?yōu)榱俗?demo 正常運(yùn)行,因此加了一行代碼讓 window.lodash 也指向 lodash,但它確實(shí)是太脆弱了。

<!-- 沒(méi)有這一行,demo就無(wú)法正常運(yùn)行 -->
<script>window.lodash = window._</script>

你瞧,IIFE 的執(zhí)行對(duì)環(huán)境的依賴是苛刻的,除非它完全不依賴外部包。(Jquery: 正是在下?。?/p>

雖然 IIFE 的缺點(diǎn)很多,但并不妨礙它在 Jquery 時(shí)代極大地推動(dòng)了 web 開(kāi)發(fā)的進(jìn)程,因?yàn)樗_實(shí)解決了 js 本身存在的很多問(wèn)題。

那么?后續(xù)是否還有 更為優(yōu)秀 的前端模塊化方案問(wèn)世呢?

當(dāng)然有,往下看吧。

二、CommonJS

2.1 分析打包結(jié)果

先看看 CommonJs 打包的結(jié)果:

簡(jiǎn)化一下,就長(zhǎng)這樣了:

'use strict';
var lodash = require('lodash');
var answer = 42;
const printAnswer = () => {
  // 打印
  console.log(`the answer is ${answer}`);
  // 測(cè)試 lodash 的能力,打印42個(gè)1
  console.log(lodash.repeat('1', answer));
};
exports.printAnswer = printAnswer;

以上格式,就是 CommonJS 規(guī)范的寫法。

// CommonJS 通過(guò)一個(gè)全局 require 方法進(jìn)行模塊的引入 
var lodash = require('lodash');
// CommonJS 進(jìn)行模塊內(nèi)方法輸出的方式
module.exports.printAnswer = printAnswer;
// 上面寫法也等價(jià)于:
exports.printAnswer = printAnswer;
// 因?yàn)?exports 變量等價(jià)于 module.exports

為了解決 node.js 在模塊化上的缺失, 2009年10月 CommonJS 規(guī)范首次被提出。

注意這個(gè)關(guān)鍵詞: node.js。

是的,CommonJS 并不是在瀏覽器環(huán)境運(yùn)行的規(guī)范,而是在 node.js 環(huán)境下運(yùn)行的。

2.2 如何運(yùn)行

因此,我寫了一個(gè) run.js 腳本。 如下:

// run.js
const Test = require('./bundle.js')
Test.printAnswer()

然后,執(zhí)行以下命令:

# 執(zhí)行腳本
node ./out/cjs/run.js 
# 輸出1: 
> the answer is 42
# 輸出2: 
> 111111111111111111111111111111111111111111

可以看出,node.js 環(huán)境是天然支持 CommonJS 的。

2.3 優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

完善的模塊化方案,完美解決了 IIFE 的各種缺點(diǎn)。

缺點(diǎn)

不支持瀏覽器環(huán)境,因?yàn)檫@種同步的引入方式可能導(dǎo)致瀏覽器假死。

因此,前端界迫切地需要一種能在瀏覽器環(huán)境完美運(yùn)行,完善的模塊化方案。

三、AMD 和 requirejs !

AMD,YES!

2011年, amdjs-api 在業(yè)內(nèi)被正式提出。

3.1 打包結(jié)果分析

amd 格式的打包結(jié)果如下:

可以看到,核心內(nèi)容是一個(gè)全局方法 define 。

define 方法有三個(gè)入?yún)ⅲ謩e是:

  • "Test", 模塊名稱
  • [exports, lodash] 分別表示模塊的輸出和外部依賴
  • 一個(gè)以 exportslodash 作為入?yún)⒌姆椒?,代表模塊的實(shí)際內(nèi)容。

相比于 IIFECommonJs 而言,AMD 的寫法無(wú)疑是復(fù)雜且別扭的。

但它卻實(shí)實(shí)在在是解決了 IIFECommonJS 所面臨的問(wèn)題,對(duì)“瀏覽器里完善的JS模塊方法” 提供了一套完善的方案。

尤其是 amd 標(biāo)準(zhǔn)的實(shí)現(xiàn)方案:requirejs

requirejs 所實(shí)現(xiàn)的 AMD 不僅解決了 CommonJS 在瀏覽器端的不適,通過(guò)異步的方式進(jìn)行模塊加載實(shí)現(xiàn)了不會(huì)導(dǎo)致假死的能力;更是完全彌補(bǔ)了 IIFE 存在的各類缺陷。

requirejs 在使用時(shí),一般情況下是以下四步法:

  • 在瀏覽器內(nèi)引入 require.js
  • 通過(guò) requirejs.config 方法定義全局的依賴
  • 通過(guò) requirejs.define 注冊(cè)模塊
  • 通過(guò) requirejs() 完成模塊引入。

3.2 如何運(yùn)行

out/amd 打包目錄下的 index.html 里,按如下方式編排代碼:

<head>
  <!-- 1. 引入 require.js -->
  <script src="./require.js"></script>
  <!-- 2. 定義全局依賴 -->
  <script>
    window.requirejs.config({
      paths: {
        "lodash": "https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min"
      }
    });
  </script>
  <!-- 3. 定義模塊 -->
  <script src="./bundle.js"></script>
</head>
<body>
  <script>
    // 4. 開(kāi)銷模塊
    window.requirejs(
      ['Test'],
      function   (test) {
        test.printAnswer()
      }
    );
  </script>
</body>

打開(kāi)瀏覽器,我們可以正常地看到]控制臺(tái)里被打印出來(lái)的 4242個(gè)1 了。

3.3 優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

  • 解決了 CommonJS 的缺點(diǎn)
  • 解決了 IIFE 的缺點(diǎn)
  • 一套完備的瀏覽器里 js 文件模塊化方案

缺點(diǎn)

  • 代碼組織形式別扭,可讀性差

但好在我們擁有了各類打包工具,瀏覽器內(nèi)的代碼可讀性再差也并不影響我們寫出可讀性ok的代碼。

現(xiàn)在,我們擁有了面向 node.jsCommonJs面向?yàn)g覽器的 AMD 兩套標(biāo)準(zhǔn)。

如果我希望我寫出的代碼能同時(shí)被瀏覽器nodejs識(shí)別,我應(yīng)該怎么做呢?

四、UMD 偉大的整合

它沒(méi)有做什么突破性的創(chuàng)造,但它是集大成者。

4.1 打包分析

umd 格式構(gòu)建出來(lái)的代碼的可讀性進(jìn)一步降低了。

我相信任何正常人看到下面這段代碼都會(huì)感到一陣頭大:

是的,整整一大段代碼,只是在處理兼容性問(wèn)題,判斷當(dāng)前應(yīng)該使用 amd 亦或是 CommonJS。

因此 umd 的代碼和實(shí)現(xiàn)不在此進(jìn)行過(guò)多分析,它所做的無(wú)非便是讓同一段代碼兼容了 amdCommonJS。

4.2 如何運(yùn)行?

  • 在瀏覽器端,它的運(yùn)行方式和 amd 完全一致,可以完全參考 3.2 節(jié)的 demo。
  • 在node.js端,它則和 CommonJS 的運(yùn)行方式完全一致,在此就不贅述了。

4.3 優(yōu)缺點(diǎn)

優(yōu)點(diǎn)

抹平了一個(gè)包在 AMDCommonJS 里的差異

缺點(diǎn)

會(huì)為了兼容產(chǎn)生大量不好理解的代碼。(理解難度與包體積)

雖然在社區(qū)的不斷努力下,CommonJS 、 AMD 、 UMD 都給業(yè)界交出了自己的答卷。

但很顯然,它們都是不得已的選擇。

瀏覽器應(yīng)該有自己的加載標(biāo)準(zhǔn)。

ES6 草案里,雖然描述了模塊應(yīng)該如何被加載,但它沒(méi)有 “加載程序的規(guī)范”。

五、SystemJs

因此 WHATWG(Web Hypertext Application Technology Working Group) 即網(wǎng)頁(yè)超文本應(yīng)用技術(shù)工作小組,提出了一套更有遠(yuǎn)見(jiàn)的規(guī)范:whatwg/loader。

也就是 JavaScript Loader Standard (JS 加載標(biāo)準(zhǔn))。

本規(guī)范描述了從 JavaScript 宿主環(huán)境中加載 JavaScript 模塊的行為。它還提供了用于攔截模塊加載過(guò)程和自定義加載行為的 api。

基于此規(guī)范,SystemJS 誕生了。

SystemJS 是目前 whatwg/loader 規(guī)范的最佳實(shí)踐者。

可以看出來(lái),system 的打包結(jié)果其實(shí)和 amd 類似,提供了全局的對(duì)象 System,并提供了注冊(cè)的方式和統(tǒng)一的寫法。

就單純的從打包結(jié)果上,其實(shí)看不出它相比對(duì) AMD + require.js 有什么優(yōu)勢(shì),難道只是寫法上存在差異?

并不止于此!

相比于 require.js,SystemJSSystem.import('module/name') 方式允許你更為“懶”地加載模塊,這意味著你無(wú)需每次都加載一大堆的 bundle,用戶只需要為他能看見(jiàn)的頁(yè)面開(kāi)銷帶寬。

另外,正因?yàn)?SystemJS 是面向 whatwg/loader 規(guī)范實(shí)踐的,因此它是面向未來(lái)的模塊依賴方式。

抱歉,這個(gè)的 demo 我也沒(méi)玩明白,就不誤導(dǎo)大家了。希望有明白的大佬可以幫忙完善下demo。

六、ESM

ECMAScript modules, 也叫 ESM, Javascript 模塊化官方標(biāo)準(zhǔn)格式。

6.1 打包分析

ESM 被提出來(lái)之前,JavaScript 一直沒(méi)有真正意義上的模塊(module)體系。

它的規(guī)范是通過(guò) export 命令顯式指定輸出的代碼,再通過(guò) import 命令輸入。

// 導(dǎo)入模塊
import { foo } from 'bar';
// 導(dǎo)出命令
export { zap };

這也是我們?nèi)粘i_(kāi)發(fā)中最為熟悉的寫法。

因此,esm 格式打出來(lái)的包,可讀性確實(shí)非常棒:

和閱讀我們平時(shí)所寫的業(yè)務(wù)代碼完全沒(méi)有區(qū)別。(rollup 依然沒(méi)忘記做 tree-shaking

6.2 如何運(yùn)行

祝賀你,是這個(gè)時(shí)代的前端開(kāi)發(fā)。

部分現(xiàn)代瀏覽器已經(jīng)開(kāi)始實(shí)裝 <script type="module> 了,因此在瀏覽器上直接使用 esm 已成為現(xiàn)實(shí)。

但運(yùn)行起來(lái)扔需要做一些前置步驟。

  • 在js-modules目錄下起一個(gè)本地靜態(tài)服務(wù)
# 在js-modules目錄下起一個(gè)本地靜態(tài)服務(wù)
cd js-modules && http-server
  • esm/bundle.js 文件的第一行修改為:
import repeat from '../../node_modules/lodash-es/repeat.js';
// 因?yàn)槟J(rèn)的lodash并不是輸出的 esm 格式,因此為了demo我們需要做一些特殊處理
  • 在瀏覽器打開(kāi)頁(yè)面(假設(shè)端口是8080),則打開(kāi):http://127.0.0.1:8080/out/esm/index.html

這樣一來(lái),代碼就能成功運(yùn)行,控制臺(tái)就可以成功打印 42 和 42個(gè)1 了。

總結(jié):分別適合在什么場(chǎng)景使用?

  • IIFE: 適合部分場(chǎng)景作為SDK進(jìn)行使用,尤其是需要把自己掛到 window 上的場(chǎng)景。
  • CommonJS: 僅node.js使用的庫(kù)。
  • AMD: 只需要在瀏覽器端使用的場(chǎng)景。
  • UMD: 既可能在瀏覽器端也可能在node.js里使用的場(chǎng)景。
  • SystemJs: 和UMD類似。目前較出名的 Angular 用的就是它。
  • ESM: 1. 還會(huì)被引用、二次編譯的場(chǎng)景(如組件庫(kù)等);2.瀏覽器調(diào)試場(chǎng)景如 vite.js的開(kāi)發(fā)時(shí)。3.對(duì)瀏覽器兼容性非常寬松的場(chǎng)景。

以上就是rollup輸出的6種格式詳解的詳細(xì)內(nèi)容,更多關(guān)于rollup輸出6種格式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 業(yè)務(wù)層hooks封裝useSessionStorage實(shí)例詳解

    業(yè)務(wù)層hooks封裝useSessionStorage實(shí)例詳解

    這篇文章主要為大家介紹了業(yè)務(wù)層hooks封裝useSessionStorage實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 使用compose函數(shù)優(yōu)化代碼提高可讀性及擴(kuò)展性

    使用compose函數(shù)優(yōu)化代碼提高可讀性及擴(kuò)展性

    這篇文章主要為大家介紹了使用compose函數(shù)提高代碼可讀性及擴(kuò)展性,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 微信小程序 wx.uploadFile在安卓手機(jī)上面the same task is working問(wèn)題解決

    微信小程序 wx.uploadFile在安卓手機(jī)上面the same task is working問(wèn)題解決

    這篇文章主要介紹了微信小程序 wx.uploadFile在安卓手機(jī)上面the same task is working問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • 最新評(píng)論