基於JS模塊化現狀談談選擇ES6模塊的緣由

這篇文章,咱們將瞭解爲何JS社區有必要選擇ES6模塊。html

現狀

要明白這種重要性,首先咱們須要描述一下JS的實際狀況。過去5年,JavaScript 發展得很是迅猛,大多數開發人員幾乎沒意識到當前已經有 5 種方式,能夠爲 JavaScript 腳本和應用建立模塊了!前端

  • 原始的 IIFE () : 這是最古老,也是比較簡單的建立 JS 模塊的方法了。如下是用 IIFE 實現的簡單模塊化示例:
   const myModule = (function (...deps){
       // JavaScript chunk
       return {hello : () => console.log(‘hello from myModule’)};
    })(dependencies);

相信你們對這段代碼都不陌生,它只是把變量和方法都封裝在自己做用域內的一種普通模式。其存在的缺點就是沒有幫咱們處理依賴。node

  • requirejsAMD (異步模塊依賴) : Require.js 很受歡迎,它能夠給模塊注入依賴,還容許動態地加載 JS 塊。
  <pre>define(‘myModule’, [‘dep1’, ‘dep2’], function (dep1, dep2){
        // JavaScript chunk, with a potential deferred loading
        return {hello: () => console.log(‘hello from myModule’)};
    });
    // anywhere else
    require([‘myModule’], function (myModule) {
        myModule.hello() // display ‘hello form myModule’
    });

效率高,惋惜有點冗長,並且不能在 Node.js 本地運行。es6

  • CommonJs : Node.js 平臺的默認格式. 一般用法相似這樣:
  // file1.js
    modules.export = {
        hello : () => console.log(‘hello from myModule’)
    }

    // file2;
    const myModule = require('./file1.js');
    myModule.hello();

nodejs

感受這種方式更酷吧,不只能夠定義變量的做用域,還能夠定義模塊之間的依賴。惋惜這是專爲 Node 設計的,不支持在瀏覽器運行,也不能異步加載模塊。可是,它能夠在前端app使用,藉助 Browserify 或者其餘工具來轉換,就可讓它在瀏覽器運行了。瀏覽器

  • UMD (通用模塊依賴) : 到這裏,咱們發現尚未一種既能夠同時兼容瀏覽器和 Node 服務器的解決方案。AMD 適合瀏覽器,CommonJS 適合 Node.

UMD 就來嘗試解決這個問題了。它經過把 AMD 和 CommonJS 結合起來,使之在各類需求下都是可集成的,代碼大概以下:服務器

 (function (global, factory) {
        typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
        typeof define === 'function' && define.amd ? define(factory) :
    (factory());
    }(this, function () {
        // JavaScript chunk
        return {
           hello : () => console.log(‘hello from myModule’)
        }
    });

該模式根據內容來判斷選擇 AMD 仍是 CommonJS. 這種模式對於打包 多環境 的庫,如 lodash 或者 moment.js 是十分適合的。app

所以,爲什麼要加一個新模塊類型 ?

首先,這些解決方案沒有一個是由TC39團隊定義的標準。ECMA6 如今已經被大量的開發者所使用,那爲什麼不選擇該版本JS定義的標準(ES6模塊)呢?異步

這個標準提供了一個更加靈活有力的解決方式。我推薦你看這篇文章, 瞭解 ES6模塊的所有屬性,由於這篇文章,我把重點放在了ES6模塊這個性質上。它可以更加精確地定義模塊間哪些須要被 exposed/imported。一塊兒看看下面的代碼:模塊化

// file1.js
const f1 = ()=> console.log(‘f1’);
const f2 = ()=> console.log(‘f2’);
const f3 = ()=> console.log(‘f3’);
export {f1, f2, f3};

// file2.js
import {f1, f2} from 「./file1」;
f1(); // display ‘f1’
f2(); // display ‘f2’

 

從這裏能夠看出,只須要靜態地聲明咱們想要 import 的內容就能夠。與其它模式不一樣,像 CommonJS 咱們能夠動態加載須要的文件。若是咱們在 CommonJS 裏面使用這個例子,就會有點不一樣:工具

// file1.js
const f1 = ()=> console.log(‘f1’);
const f2 = ()=> console.log(‘f2’);
const f3 = ()=> console.log(‘f3’);
modules.exports = {f1,f2,f3};

// file2.js
const file1 = require(‘./file1’);
file1.f1(); // display ‘f1’
file1.f2(); // display ‘f2’
file1[process.ENV.funcName]();

 

很明顯,最後一行沒法呈現成真正的代碼,但它代表了一些值超出了可控範圍,沒法在靜態分析中被預知。這裏,咱們實質上是能夠調用 f3,由於用 CommonJs (AMD、IIFE 或者 UMD) 咱們都是沒法限制 import 的內容。

tree-shacking

因此?瞭解代碼的靜態分析是使用什麼是否是也很重要呢?

答案是確定的!

由於有了這個控制,開發者工具能夠檢測到一些 bug。 若是你使用 WebPack 2 或者 Rollup.js 將會更有趣,結合 Tree Shaking, 你編譯的文件將會更小。Tree Shaking 的功能就是把不用用到的代碼移除掉。

這就是 tree shaking 的一個例子 :

原文件
//-------------
// main.js
import {cube} from './maths.js';
console.log( cube( 5 ) ); // 125

//-------------
// maths.js
export function square ( x ) {
   return x * x;
}

// This function gets included
export function cube ( x ) {
   return x * x * x;
}

 

輸出文件
function cube ( x ) {
   return x * x * x;
}

console.log( cube( 5 ) ); // 125

 

Mathieu Breton CTO chez JS-Republic

 

原文連接https://www.zcfy.cc/article/1010

相關文章
相關標籤/搜索