一文帶你首先弄懂什麼是Web-modules 前端模塊化

歡迎關注個人我的博客分享一些前端技術、面試題、面試技巧等前端

模塊化的開發方式能夠提升代碼的服用效率,方便進行代碼的管理。模塊化主要體現的是一種分而治之的思想。分而治之是複雜系統開發和維護的基石,模塊化則是前段最流行的分治階段。node

n4PnU0.jpg

模塊化簡介

具備相同屬性和行爲的事物的集合,在前端中,將一些屬性比較相似和行爲比較相似的內容放在同一個 JS 文件裏面,把這個 JS 文件稱爲一個模塊,爲了每一個 JS 文件只關注自身有關的事情,讓每一個 JS 文件各行其職jquery

模塊化要有幾個特色:獨立完整依賴關係git

在最開始的階段,JS 並無模塊化機制,各類 JS 處處飛,也就是所謂的野生代碼,得不到妥善的管理。後來前端圈開始制定規範,最耳熟能詳的是CommonJSAMDnode.js 就是CommonJS規範的產物。可是因爲CommonJS同步加載更適合服務端,因此迫切須要一個關於客戶端的規範,既又出現了不少客戶端,耳熟能詳的AMDgithub

模塊化的實現

  • 函數
  • 對象的寫法
  • 匿名函數、返回對象
  • 以來傳入實參
  • 以上缺點依賴關係很差處理,須要按順序加載,可能會阻塞頁面

模塊化的好處

  • 避免命名衝突
  • 更好的分離,按需加載
  • 更高複用性
  • 高可維護性

同步加載 CommonJS

n4CJtf.png

根據CommonJS規範,每個文件就是一個模塊,其內部定義的變量是屬於這個模塊的,不會對外暴露,也就是說不會污染全局變量。面試

該規範最初是用來服務器端的 node,前端的 Webpack 也是對 CommonJS 原生支持編程

CommonJS 的核心思想就是經過 require 方法來同步加載所要依賴的其餘模塊,而後經過 exports 或者 mode.exports來導出須要暴露的接口瀏覽器

使用

// index.js
var module = require('module.js)
module.aa('hello')

// module.js
module.exports = {
  aa: function (str) {
    console.log(str)
  }
}
複製代碼

特色

  • 全部代碼都運行在模塊做用域,不會污染全局做用域
  • 模塊能夠屢次加載,可是隻會在第一次加載時運行一次,而後運行結果就被緩存了,之後再加載,就直接讀取緩存結果。要想讓模塊再次運行,必須清除緩存
  • 模塊加載的順序,按照其在代碼中出現的順序

require命令的基本功能是,讀取並執行一個 JavaScript 文件,而後返回該模塊的 exports 對象。若是沒有發現指定模塊,會報錯!緩存

模塊加載機制

CommonJS模塊的加載機制是,輸入的是被輸出的值的拷貝。也就是說,一旦輸出一個值,模塊的內部變化就影響不到這個值服務器

// module.js
let counter = 3;
function addCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  addCounter: addCounter
};

// index.js
let counter = require("module.js").counter;
let addCounter = require("module.js").addCounter;

console.log(counter); // 3
addCounter();
console.log(counter); // 3
複製代碼

上面的代碼說明,當module.js中的值被輸出以後,模塊內部的變化已經就影響不到這個值了。這是由於 counter 是一個原始類型值,會被緩存。除非寫成一個函數,才能獲得內部變更的值

注意: 瀏覽器不兼容 CommonJS,緣由是瀏覽器缺乏 moduleexportsrequireglobal 四個環境變量。如要使用須要工具轉換。

CommonJS 採用同步加載不一樣模塊文件,適用於服務端 由於模塊文件都存放在服務器的各個硬盤上,讀取加載時間快,適合服務端,不適應瀏覽器

異步加載 AMD

nhq259.png

CommonJS 爲服務器端而生,採用的同步加載方式。所以不適用與瀏覽器。由於瀏覽器須要到服務器加載文件,請求時間遠大於本機讀取時間,假若文件較多,網絡遲緩就會致使頁面癱瘓,因此瀏覽器更但願可以實現異步加載的方式。

AMD 規範是實現異步加載模塊,容許指定回調函數,等模塊異步加載完成後便可調用回調函數。

AMD 的核心思想就是經過 define 來定義一個模塊,而後使用 require 來加載一個模塊

使用

// main.js
// 使用模塊
require(["jquery", "math", "module"], function($, math) {
  // your code
});

// math.js
// 定義沒有依賴的模塊
define(function() {
  // your code
  return 模塊;
});

// module.js
// 定義有依賴的模塊
define(["module"], function() {
  return 模塊;
});
複製代碼

AMD 模塊定義的方法很是清晰,不污染全局環境,可以清除的顯示依賴關係。AMD 模式能夠用於瀏覽器環境,而且容許非同步加載模塊,也能夠根據須要動態加載模塊。

異步加載 CMD

nhj1iQ.png

CMD 異步加載,跟 AMD 的主要區別在於,AMD 依賴前置,提早加載依賴。而 CMD 就近加載,按需加載。

CMD 的核心思想就是經過 define 來定義一個模塊,而後使用 require 來加載一個模塊。

使用

// module1.js
// 定義沒有依賴的模塊
define(function(require, exports, module) {
  exports.xxx = val;
  module.exports = value;
});

// module2.js
// 定義有依賴的模塊
define(function(require, exports, module) {
  // 引入依賴模塊(同步)
  let module1 = require("./module1.js");
  // 引入依賴模塊(異步)
  require.async("./module1.js", function(m1) {
    // your code
  });
  // 暴露模塊
  exports.xxx = value;
});

// index.js
define(function(require) {
  let m1 = require("./module1");
  let m2 = require("./module2");
  m1.show();
  m2.show();
});
複製代碼

ES6 模塊化

n4CnpD.png

ES6 自帶模塊化,可使用 import 關鍵字引入模塊,經過 export 關鍵字導出模塊,功能較以前的幾個方案更爲強大,也是咱們所推崇的,可是 ES6 目前沒法在瀏覽器中執行,因此,咱們只能經過 babel 將不被支持的 import 編譯爲當前受到普遍支持的 require

使用

// index.js
import tool from "tool.js";

// tool.js
export class show {
  // 導出
  constructor() {
    this.age = 18;
  }
  showName() {
    return this.age;
  }
}
複製代碼

ES6 模塊與 CommonJS 模塊的差別

  1. CommonJS 模塊輸出的是一個值的拷貝,ES6 模塊輸出的是值的引用
  2. CommonJS 模塊是運行時加載,ES6 模塊是編譯時輸出接口
  3. ES6 模塊是動態引用的,而且不會緩存值,模塊裏邊的變量綁定其所在的模塊

總結

  • CommonJS 規範主要用於服務端編程,加載模塊是同步的,這並不適合在瀏覽器環境中使用,由於同步意味着阻塞加載,瀏覽器資源是異步加載的,所以有了 AMD 和 CMD 解決方案
  • AMD 規範在瀏覽器環境中異步加載模塊,並且能夠並行加載多個模塊。不過 AMD 規範開發成本高,代碼的閱讀和書寫比較困難,模塊定義的方式語義不暢
  • CMD 規範與 AMD 規範很類似,都用於瀏覽器編程,依賴就近,延遲執行,能夠很容易在 Node.js 中運行。不過,依賴 SPM 打包,模塊的加載邏輯偏重
  • ES6 在語言標準層面上,實現模塊功能,並且實現的至關簡單,徹底能夠取代 CommonJS 和 AMD 規範,成爲瀏覽器和服務器通用的模塊解決方案

但願對讀完本文的你有幫助、有啓發,若是有不足之處,歡迎批評指正交流!

歡迎關注個人我的博客分享一些前端技術、面試題、面試技巧等

辛苦整理良久,還望手動點贊鼓勵~


'摘抄'不是單純的「粘貼->複製」,而是眼到,手到,心到的一字一句敲打下來。

博客聲明:全部轉載的文章、圖片僅用於做者本人收藏學習目的,被要求或認爲適當時,將標註署名與來源。若不肯某一做品被轉用,請及時通知本站,本站將予以及時刪除。

相關文章
相關標籤/搜索