學習筆記(九)——模塊化開發

模塊化開發

模塊化只是一種思想

模塊化演變過程

  • Stage 1 - 文件劃分方式
    • 將功能與數據放置到不同的文件當中
    • 約定每個文件都是一個獨立的模塊
    • 缺點:
      • 每個模塊都在全局作用域下工作,污染全局作用域,容易出現命名沖突
      • 無法管理模塊之間的依賴關系
      • 模塊內的成員可以被其他模塊隨意修改
      • 完全依靠約定,當項目變得龐大以后,難以維護
  • Stage 2 - 命名空間方式
    • 每個模塊只暴露一個全局對象
    • 所有成員與方法都掛載在這個全局對象下
    • 解決了全局作用域污染與命名沖突的問題
    • 缺點:
      • 依然無法管理模塊之間的依賴關系
      • 模塊的內的成員依然可以被修改
  • Stage 3 - IIFE(立即執行函數)方式
    • 使用立即執行函數,為模塊創建私有空間
    • 對于需要對外暴露的內容,可以掛載到window對象上
    • 解決了模塊內成員可以被隨意修改的問題
  • Stage 4 - 模塊化規范出現
    • CommonJS規范 - NodeJS模塊化規范
      • 一個文件就是一個模塊
      • 每個模塊有單獨的作用域
      • 通過module.exports導出成員
      • 通過require函數加載模塊
      • 同步模式加載模塊(在瀏覽器環境效率不高)
    • AMD(Asynchronous Module Definition)- 異步模塊定義規范
      • require.js實現了AMD規范,同時是一個功能強大的模塊加載器
      • 約定使用define函數定義一個模塊,接收三個參數
        • 第一個參數:模塊名稱
        • 第二個參數:聲明依賴數組
        • 第三個參數:提供私有空間的函數,通過return向外部導出成員
      • 使用require函數加載模塊
      • 絕大多數第三方庫都支持AMD規范
      • AMD模塊使用起來相對復雜
      • 模塊JS請求相對頻繁
    • CMD(Common Module Definition)- 通用模塊定義規范
      • 由淘寶前端團隊推出的sea.js定義并實現了CMD規范
      • 類似CommonJS規范
      • 通過require加載依賴
      • 通過module.exports或exports對外暴露成員
      • 被require.js兼容

模塊化標準規范

ES Module - ES2015中定義,并在語言層面實現的模塊化規范

模塊化的最佳實踐,NodeJS環境下使用CommonJS規范,瀏覽器環境下使用ES Module

ES Module特性

  • 自動采用嚴格模式
  • 運行在獨立私有作用域中
  • 通過CORS方式請求外部JS模塊
    • 即script被標識為type=module方式引入外部資源時,會受到瀏覽器同源策略限制
  • script加載外部JS時,會延遲執行腳本,等同于使用defer屬性,不影響頁面渲染,執行順序不按引用順序

ES Module的導入導出

  • 通過export導出

    • 常見用法

      export const a = 1
      export const fn = () => {}
      export default 123
      export { a, fn as b }
      export t from './module.js'
      
    • 注意事項

      • export { obj }export default { obj }
        • export { obj } export后面跟的不是字面量對象,而是固定的語法
        • export default { obj } export default后面跟的是一個值,這里{ obj }表示字面量對象
      • export導出的是成員的引用,而不是成員值的拷貝,這與CommonJS不同
  • 通過import導入

    • 常見用法

      import { a, b, default as n } from './es-module.js'
      
    • 注意事項

      • import { obj } from xxx import后面的括號不是解構寫法,而是固定的語法
      • import導入的對象是只讀的,不允許修改
      • import導入文件路徑不可省略(相對路徑或者絕對路徑)
      • 不支持表達式方式,如果需要動態加載模塊,可以使用import()函數,該函數返回一個Promise對象

ES Module瀏覽器環境polyfill

browser-es-module-loader

  • 工作原理:
    • 讀取ES Module腳本
    • 交給babel進行轉換
    • 執行轉換后的代碼
  • 注意事項
    • 在支持ES Module的瀏覽器環境下,會導致重復執行
    • 可以使用script的nomodule屬性,只會在不支持ES Module的瀏覽器環境下加載腳本

ES Module in Node.js

  • Node.js中目前可以使用ES Module語法加載或者導出模塊,屬于實驗特性

  • 要在node環境下使用ES Module

    • JS文件需要使用.mjs結尾(新版本node在package.json中標識type: module時,可以直接使用.js文件后綴,此時想使用CommonJS模塊,需使用.cjs結尾)

    • 執行時,需要添加--experimental-modules參數開啟實驗特性

      // 注意,必須先跟--experimental-modules參數,再接文件名
      node --experimental-modules import.mjs
      
  • 使用import加載其他模塊

    • 第三方模塊:無法使用提取成員的方式
    • 系統內置模塊:官方做了兼容性處理,可以正常提取成員
    • CommonJS模塊:導出一個對象,因此無法使用提取成員的方式加載模塊,可以使用加載default默認對象的方式
  • CommonJS模塊無法直接加載ES Module

  • ES Module與CommonJS模塊的差異

    • ES Module下無法訪問CommonJS內置成員及方法require、module、exports、__filename、__dirname
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容