寫給前端新手看的一些模塊化知識

大家好,我是若川。最近組織了源碼共讀活動,感興趣的可以點此加我微信ruochuan12?進群參與,每周大家一起學習200行左右的源碼,共同進步。已進行三個月了,很多小伙伴表示收獲頗豐。

一、 為什么需要模塊化

以前沒有模塊化時,我們可能會按如下方式劃分模塊:
通過 <script> 標簽引入各個文件,把每個文件看成是一個模塊,每個模塊的接口通常是暴露在全局作用域下的,也就是定義在 window 對象中。

<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="module3.js"></script>

如果通過這種方式做模塊化,當項目變得越來越大時,很容易造成全局變量沖突,項目也會變得越來越難以管理。

因此我們需要找到一種合適的方式來幫助我們模塊化,模塊化能給我們帶來哪些好處呢?具體來說,主要包含以下幾個方面:

  1. 減少全局變量污染

  2. 控制依賴

  3. 增強代碼的可維護性

  4. 增加代碼的復用性

  5. 分治思想的實踐

二、模塊化標準現狀

1. CommonJS

規范

  1. 模塊的標識應遵循一定的書寫規則。

  2. 定義全局函數?require(dependency),通過傳入模塊標識來引入其他依賴模塊,執行的結果即為別的模塊暴漏出來的 API。

  3. 如果被 require 函數引入的模塊中也包含外部依賴,則依次加載這些依賴。

  4. 如果引入模塊失敗,那么 require 函數應該拋出一個異常。

  5. 模塊通過變量 exports 來向外暴露 API,exports 只能是一個 Object 對象,暴露的 API 須作為該對象的屬性。

使用方式

導出模塊:

// math.js
var num = 0;
function add(a, b) {return a + b;
}
module.exports = {num: num,add: add
}

加載模塊:

// 引入自定義的模塊時,參數包含路徑,可省略.js
// 引入核心模塊時,不需要帶路徑,如var http = require("http");
var math = require('./math');
math.add(1, 2) //3

優點

  1. 簡單易用。

  2. 解決了模塊依賴的問題。

  3. 減少了全局變量污染。

缺點

  1. 無法在瀏覽器端使用。

  2. 無法非阻塞的并行加載多個模塊。

2. AMD(Async Module Definition)

代表作 RequireJS。

規范

  1. 模塊的標識遵循 CommonJS Module Identifiers。

  2. 定義全局函數?define(id, dependencies, factory),用于定義模塊。dependencies 為依賴的模塊數組,在 factory 中需傳入形參與之一一對應。

  3. 如果 dependencies 的值中有 require、exports 或 module,則與 CommonJS 中的實現保持一致。

  4. 如果 dependencies 省略不寫,則默認為 ['require', 'exports', 'module'],factory 中也會默認傳入三者。

  5. 如果 factory 為函數,模塊可以通過以下三種方式對外暴漏 API:return 任意類型;exports.XModule = XModule、module.exports = XModule

  6. 如果 factory 為對象,則該對象即為模塊的導出值。

使用方式

定義模塊

  • 獨立模塊

define({method1: function() {},method2: function() {},
});// 函數的返回值就是輸出的模塊
define(function () {return {method1: function() {},method2: function() {},};
});
  • 有依賴的模塊

define(['module1', 'module2'], function(m1, m2) {
...
});
// module1模塊和module2模塊指的是,當前目錄下的module1.js文件和module2.js文件,等同于寫成['./module1', './module2']

需要注意的是,回調函數必須返回一個對象,這個對象就是你定義的模塊。

調用模塊

require(['foo', 'bar'], function ( foo, bar ) {foo.doSomething();
});

優點

  1. 可以用于瀏覽器。

  2. 異步加載模塊。

  3. 可以并行加載多個模塊。

缺點

  1. 提高了開發成本。

  2. 不能按需加載,而是提前加載所有的依賴。

* RequireJS 從 2.0 開始,也改成了可以延遲執行。

3. CMD (Common Module Definition)

CMD 是?sea.js?在推廣過程中對模塊定義的規范化產出,屬于 CommonJS 的一種規范。

使用方式

定義模塊:

define(function (require, exports, module) {var add = function (a, b) {return a + b;}exports.add = add;
})

使用模塊:

seajs.use(['math.js'], function (math) {var sum = math.add(1, 2);
});

優點

  1. 實現了瀏覽器端的模塊化加載。

  2. 可以按需加載。

  3. 依賴就近,延遲執行。

缺點

  1. 依賴 SPM 打包,模塊加載邏輯偏重。

4. UMD (Universal Module Definition)

UMD 是一種 JavaScript 通用模塊定義規范,讓你的模塊能在 JavaScript 所有運行環境中發揮作用。

規定如下:

  1. 優先判斷是否存在 exports 方法,如果存在,則采用 CommonJS 方式加載模塊;

  2. 其次判斷是否存在 define 方法,如果存在,則采用 AMD 方式加載模塊;

  3. 最后判斷 global 對象上是否定義了所需依賴,如果存在,則直接使用;反之,則拋出異常。

5. ES Module

使用方式

導出模塊:

// 導出
exportfunction hello() { };
exportdefault {// ...
};

引入模塊:

import { readFile } from'fs';
import React from'react';

優點

  1. 語法層面的支持,使用簡單。

缺點

  1. 瀏覽器還沒有完全兼容,必須通過工具轉換成標準的 ES5 后才能正常運行。

瀏覽器的支持情況

4cc1aa95b7319b748b9f66c62cdf3914.png

三、模塊化的演變歷史

2009 年的時候,Mozilla 的工程師 Kevin Dangoor 與同事們一起制定了一套 JsaveScript 模塊化標準,并取名為 ServerJS。ServerJS 最早是用于服務端的,目的是為了在自動化測試的工作中提供模塊化導入的功能。之后 ServerJS 更名為了 CommonJS。

同年 9 月,Ryan Dahl 創造了 Node.js,而一開始 Node.js 還沒有包管理工具,隨后采用 CommonJS 規范的 npm (即 node package manager) 誕生了。隨著 Node.js 的快速發展,CommonJS 規范也漸漸進入廣大前端開發者的視野。至此,JavaScript 第一個模塊化規范,也正式登入歷史舞臺。

隨著 npm 的流行,廣大前端開發者也希望引入這種模塊化的方案到日常的開發工作中。但是 CommonJS 只能應用于服務端,因此勢必需要重新制定規范標準。而此時,關于如何制定新的標準,主要有三大流派:

保守派

CommonJS 已經在服務端成功應用了,那么在瀏覽器加載模塊前,我們先通過工具將模塊轉換成瀏覽器能夠執行的代碼就可以了。該想法與如今的 babel 等工具思路是相似的,通過將高版本的代碼轉換為低版本的代碼,目的都是為了兼容。而 browserify 就是這一觀點下的產物。

激進派

瀏覽器與服務端存在很大的差異,我們應該根據瀏覽器的特點,放棄 require 的方式而是使用回調的方式引入模塊。將同步加載模塊更改為異步加載模塊。

中間派

CommonJS 中的 require 等規范還是有可取之處,在盡可能與現有的 CommonJS 規范保持一致的前提下,我們也可以引入一些好的特性,比如 exports 可以導出更多類型而不是局限于 Object。

各自進展

激進派

激進派的 James Burke 在 2009 年開發出了 RequireJS 模塊加載器。2011 年,在 RequireJS 社區的基礎上,誕生了 AMD(Async Module Definition)社區。AMD 是第一個支持瀏覽器端的 Javascript 模塊化解決方案,RequireJS 迅速被廣大開發者熟知和采用。

中間派

中間派的故事比較曲折。CommonJS 的主要貢獻者之一 Wes Garland 給出了一個名為 BravoJS 的實現。Wes Garland 本人是學院派,理論功底十分強,但寫出的作品卻不很實用。另一位實戰派大佬提出了 Modules/Wrappings 的方案,并給出了一個名為 FlyScript 的實現。而兩位大佬對具體的實現發生了一些爭論,最后以 FlyScript 的 GitHub 倉庫被刪除而結束這段恩怨。

2011 年 4 月,阿里巴巴的前端大佬玉伯,因為給 RequireJS 提出的建議被不斷拒絕后,在參考了 AMD 和 CommonJS 的方案后,便自己寫了一個模塊加載器 Sea.JS,同時提出了 CMD 規范。CMD 規范的主要內容與 AMD 相似,但是保留了 CommonJS 中延遲加載和就近聲明的特性。

UMD

2014 年 9 月,美籍華裔 Homa Wong 提交了 UMD 第一個版本的代碼。UMD 即 Universal Module Definition 的縮寫,它本質上并不是一個真正的模塊化方案,而是將 CommonJS 和 AMD 相結合。

ES Module

2016 年 5 月,經過了兩年的討論,ECMAScript 6.0 終于正式通過決議,成為了國際標準。在這一標準中,首次引入了 import 和 export 兩個 JavaScript 關鍵字,并提供了被稱為 ES Module 的模塊化方案。2017 年 9 月, Chrome 的 61.0 版本首次在瀏覽器端支持了 ES Module。目前已經有很多瀏覽器原生支持了 ES Module。而伴隨著 ES Module 的興起,也出現了像 Vite 這樣的構建工具。

最近組建了一個湖南人的前端交流群,如果你是湖南人可以加我微信?ruochuan12?私信 湖南 拉你進群。

推薦閱讀

1個月,200+人,一起讀了4周源碼
我歷時3年才寫了10余篇源碼文章,但收獲了100w+閱讀

老姚淺談:怎么學JavaScript?

我在阿里招前端,該怎么幫你(可進面試群)

98144e6e71d04c8c87294909f5407e88.gif

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》10余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助1000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。

7293914ca44b3697a140868cea785ef1.png

識別方二維碼加我微信、拉你進源碼共讀

今日話題

略。分享、收藏、點贊、在看我的文章就是對我最大的支持~

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

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

相關文章

重學前端學習筆記(八)--JavaScript中的原型和類

筆記說明 重學前端是程劭非&#xff08;winter&#xff09;【前手機淘寶前端負責人】在極客時間開的一個專欄&#xff0c;每天10分鐘&#xff0c;重構你的前端知識體系&#xff0c;筆者主要整理學習過程的一些要點筆記以及感悟&#xff0c;完整的可以加入winter的專欄學習【原文…

代碼實現照片素描_我的代碼素描之旅

代碼實現照片素描In 2018 I started the process of consistently creating and posting my code sketches online. These are small animations I make with code and post on instagram. Through these sketches I tried to visually express my ideas using color, animatio…

GCC參數詳解

轉自&#xff1a;http://www.cnblogs.com/fence/archive/2009/12/18/1627138.html GCC參數詳解 gcc and g分別是gnu的c & c編譯器 gcc/g在執行編譯工作的時候&#xff0c;總共需要4步1.預處理,生成.i的文件[預處理器cpp]2.將預處理后的文件不轉換成匯編語言,生成文件.s[編…

真效率神器,UI稿智能轉換成前端代碼,準確率極高

大家好&#xff0c;我是若川。在這充滿網絡促銷活動的幾個月&#xff0c;倍感壓力的&#xff0c;除了你的口袋&#xff0c;是否還有程序員的發量呢&#xff1f;每年的雙十一、雙十二購物狂歡節&#xff0c;各大電商平臺都會上線讓消費者充滿購買欲望的活動頁面&#xff0c;而這…

PPT圖標的正確使用和插入與編輯形狀

PPT圖標的正確使用和插入與編輯形狀 通過圖標可以以符號的形式直觀地傳遞信息。 一&#xff0c;實戰&#xff1a;在銷售工作計劃中插入圖標 PowerPoint 2016中提供了多種類型的圖標&#xff0c;用戶可根據需要在幻燈片中插入所需的圖標。 二&#xff0c;實戰&#xff1a;更改銷…

幾個用于序列化的代碼片段

參考JavaScriptSerializer,一般用來做JSON格式化http://msdn.microsoft.com/zh-cn/library/system.web.script.serialization.javascriptserializer.aspx http://msdn.microsoft.com/zh-cn/library/system.web.script.serialization.javascriptconverter.aspxDataContractSeria…

桌面圖標擺放圖案_用圖標制作醒目的圖案

桌面圖標擺放圖案Level up your video calls with a custom backdrop created using Noun Project icons.使用使用Noun Project圖標創建的自定義背景來升級視頻通話。 The only thing more visually pleasing than a well-designed icon is a neat, eye-catching pattern made…

3個多月,近3000人參與的源碼共讀,誠邀加入~

大家好&#xff0c;我是若川。眾所周知&#xff0c;從8月份開始&#xff0c;我組織了源碼共讀活動&#xff0c;每周學習200行左右的源碼&#xff0c;到現在持續了3個多月&#xff0c;堅持答疑解惑。幫助了不少人&#xff0c;還是挺開心的。另外&#xff0c;涌現了很多優秀的讀者…

upc 組隊賽18 STRENGTH【貪心模擬】

STRENGTH 題目鏈接 題目描述 Strength gives you the confidence within yourself to overcome any fears, challenges or doubts. Feel the fear and do it anyway! If you have been going through a rough time and feel burnt out or stressed, the Strength card encourag…

JSONNull

最近用JSONObject&#xff0c;感覺比xml好用一些&#xff0c;json的打包和解包都比較清晰和容易&#xff0c;最近遇到一個問題&#xff0c;將一個JSON對象解析&#xff0c;存到hashmap中去&#xff0c;然后再從hashmap取出數據&#xff0c;遇到jsonnull的問題&#xff0c;本以為…

“這張圖告訴你什么?”

For data to be impactful, it must be understood.為了使數據具有影響力&#xff0c;必須理解它。 I’ve happily spent hundreds and hundreds of hours of my life watching users misunderstand data visualizations. I’m strangely hooked on it.我快樂地度過了數百個小…

我們從 UmiJS 遷移到了 Vite

大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以點此加我微信ruochuan12 進群參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。已進行三個月了&#xff0c;很多小伙伴表示收獲頗豐。我們從 UmiJS遷移到 Vite 已經上線半年…

將DataTable的內容以EXCEl的形式導出到本地

1.在搞項目的時候一般會遇到&#xff0c;將GridView或者Repeater的內容以Excel的形式保存到本地&#xff0c;即導出功能。我總結了兩個方法。 方法一&#xff1a; 1 DataTable dt query.GetItems().GetDataTable();2 if (dt ! null)3 {4 …

智能家居數據庫設計_設計更智能的數據表

智能家居數據庫設計重點 (Top highlight)Data tables are hard. There are many different ways to think about them. So, naturally, the first step would be to figure out what your users need.數據表很難。 有許多不同的方式來考慮它們。 因此&#xff0c;自然地&#x…

可能是全網首個前端源碼共讀活動,誠邀你加入一起學習

大家好&#xff0c;我是若川。眾所周知&#xff0c;從8月份開始&#xff0c;我組織了源碼共讀活動&#xff0c;每周學習200行左右的源碼&#xff0c;到現在持續了3個多月&#xff0c;堅持答疑解惑。幫助了不少人&#xff0c;還是挺開心的。另外&#xff0c;涌現了很多優秀的讀者…

vsftpd 的配置項目

基本配置說明&#xff1a; 1&#xff09;local_root/ftpfile(當本地用戶登入時&#xff0c;將被更換到定義的目錄下&#xff0c;默認值為各用戶的家目錄) 2&#xff09;anon_root/ftpfile(使用匿名登入時&#xff0c;所登入的目錄) 3&#xff09;use_localtimeYES(默認是GMT時…

線段樹專輯——pku 3667 Hotel

http://poj.org/problem?id3667 哈哈&#xff0c;經典中的經典題啊。利用線段樹求最大連續空閑區間&#xff0c;并返回空閑區間的起點坐標。 View Code 1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 using namespace std; 5 6 …

houseparty不流暢_重新設計Houseparty –用戶體驗案例研究

houseparty不流暢Houseparty has become very popular during the COVID-19 period because it helps you connect with others in a fun way. The concept is simple, you open the app and jump on a video call with your friends. You can even play online games with the…

你不知道的 Node.js 工具函數

從類型判斷說起在 JavaScript 中&#xff0c;進行變量的類型校驗是一個非常令人頭疼的事&#xff0c;如果只是簡單的使用 typeof 會到各種各樣的問題。舉幾個簡單的&#x1f330;&#xff1a;console.log(typeof null) // object console.log(typeof new Array) // object cons…

Java應用集群下的定時任務處理方案(mysql)

今天來說一個Java多機部署下定時任務的處理方案。 需求: 有兩臺服務器同時部署了同一套代碼&#xff0c; 代碼中寫有spring自帶的定時任務&#xff0c;但是每次執行定時任務時只需要一臺機器去執行。 當拿到這個需求時我腦子中立馬出現了兩個簡單的解決方案&#xff1a; 利用ip…