node模塊化1

一、模塊化簡(jiǎn)介

安裝:https://www.cnblogs.com/coder-lzh/p/9232192.html

隨著前端js代碼復(fù)雜度的提高,JavaScript模塊化這個(gè)概念便被提出來(lái),前端社區(qū)也不斷地實(shí)現(xiàn)前端模塊化,直到es6對(duì)其進(jìn)行了規(guī)范。

1.什么是模塊化

一個(gè)模塊就是一個(gè)文件

包 : 一堆模塊
包 組成項(xiàng)目

二、第一階段:無(wú)模塊化

JavaScript最初的作用僅僅是驗(yàn)證表單,后來(lái)會(huì)添加一些動(dòng)畫(huà),但是這些js代碼很多在一個(gè)文件中就可以完成了,所以,我們只需要在html文件中添加一個(gè)script標(biāo)簽。

后來(lái),隨著前端復(fù)雜度提高,為了能夠提高項(xiàng)目代碼的可讀性、可擴(kuò)展性等,我們的js文件逐漸多了起來(lái),不再是一個(gè)js文件就可以解決的了,而是把每一個(gè)js文件當(dāng)做一個(gè)模塊。那么,這時(shí)的js引入方式是怎樣的呢?大概是下面這樣:

    <script src="jquery.js"></script>
  <script src="jquery_scroller.js"></script>
  <script src="main.js"></script>
  <script src="other1.js"></script>
  <script src="other2.js"></script>
  <script src="other3.js"></script>

即簡(jiǎn)單的將所有的js文件統(tǒng)統(tǒng)放在一起。但是這些文件的順序還不能出錯(cuò),比如jquery需要先引入,才能引入jquery插件,才能在其他的文件中使用jquery。

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

相比于使用一個(gè)js文件,這種多個(gè)js文件實(shí)現(xiàn)最簡(jiǎn)單的模塊化的思想是進(jìn)步的。

2.缺點(diǎn):

污染全局作用域。 因?yàn)槊恳粋€(gè)模塊都是暴露在全局的,簡(jiǎn)單的使用,會(huì)導(dǎo)致全局變量命名沖突,當(dāng)然,我們也可以使用命名空間的方式來(lái)解決。

對(duì)于大型項(xiàng)目,各種js很多,開(kāi)發(fā)人員必須手動(dòng)解決模塊和代碼庫(kù)的依賴(lài)關(guān)系,后期維護(hù)成本較高。

依賴(lài)關(guān)系不明顯,不利于維護(hù)。 比如main.js需要使用jquery,但是,從上面的文件中,我們是看不出來(lái)的,如果jquery忘記了,那么就會(huì)報(bào)錯(cuò)。

三、第二階段: CommonJS規(guī)范

CommonJS就是一個(gè)JavaScript模塊化的規(guī)范,該規(guī)范最初是用在服務(wù)器端的node的,前端的webpack也是對(duì)CommonJS原生支持的。

根據(jù)這個(gè)規(guī)范,每一個(gè)文件就是一個(gè)模塊,其內(nèi)部定義的變量是屬于這個(gè)模塊的,不會(huì)對(duì)外暴露,也就是說(shuō)不會(huì)污染全局變量。

CommonJS的核心思想就是通過(guò) require 方法來(lái)同步加載所要依賴(lài)的其他模塊,然后通過(guò) exports 或者 module.exports 來(lái)導(dǎo)出需要暴露的接口。如下所示:

// a.js
var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

這里的a.js就是一個(gè)CommonJS規(guī)范的模塊了。 這里的module就代表了這個(gè)模塊,module的exports屬性就是對(duì)外暴露的接口,可以對(duì)外導(dǎo)出外部可以訪問(wèn)的變量,比如這里的x和addX。

exports 是對(duì) module.exports 的引用。比如我們可以認(rèn)為在一個(gè)模塊的頂部有這句代碼:

exports = module.exports

所以,我們不能直接給exports賦值,比如number、function等。
然后我們就可以在其他模塊中引入這個(gè)模塊使用了:

vara = require('./a.js');
console.log(example.x); // 5
console.log(example.addX(1)); // 6

這里的require就會(huì)獲取到a.js所暴露的module.exports變量,然后就可以使用其暴露的x和addX了。

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

CommonJS規(guī)范在服務(wù)器端率先完成了JavaScript的模塊化,解決了依賴(lài)、全局變量污染的問(wèn)題,這也是js運(yùn)行在服務(wù)器端的必要條件。

2.缺點(diǎn):

此文主要是瀏覽器端js的模塊化, 由于 CommonJS 是同步加載模塊的,在服務(wù)器端,文件都是保存在硬盤(pán)上,所以同步加載沒(méi)有問(wèn)題,但是對(duì)于瀏覽器端,需要將文件從服務(wù)器端請(qǐng)求過(guò)來(lái),那么同步加載就不適用了,所以,CommonJS是不適用于瀏覽器端的。

四、第三階段: AMD規(guī)范

之前提到: CommonJS規(guī)范加載模塊是同步的,也就是說(shuō),只有加載完成,才能執(zhí)行后面的操作。AMD規(guī)范則是非同步加載模塊,允許指定回調(diào)函數(shù)。由于Node.js主要用于服務(wù)器編程,模塊文件一般都已經(jīng)存在于本地硬盤(pán),所以加載起來(lái)比較快,不用考慮非同步加載的方式,所以CommonJS規(guī)范比較適用。但是,如果是瀏覽器環(huán)境,要從服務(wù)器端加載模塊,這時(shí)就必須采用非同步模式,因此瀏覽器端一般采用AMD規(guī)范。而AMD規(guī)范的實(shí)現(xiàn),就是大名鼎鼎的require.js了。
AMD標(biāo)準(zhǔn)中,定義了下面兩個(gè)API:

   1.require([module], callback)

   2. define(id, [depends], callback)

即通過(guò)define來(lái)定義一個(gè)模塊,然后使用require來(lái)加載一個(gè)模塊。 并且,require還支持CommonJS的模塊導(dǎo)出方式。
定義alert模塊:

define(function () {
    var alertName = function (str) {
      alert("I am " + str);
    }
    var alertAge = function (num) {
      alert("I am " + num + " years old");
    }
    return {
      alertName: alertName,
      alertAge: alertAge
    };
  });
引入模塊:
require(['alert'], function (alert) {
  alert.alertName('JohnZhu');
  alert.alertAge(21);
});

但是,在使用require.js的時(shí)候,我們必須要提前加載所有的依賴(lài),然后才可以使用,而不是需要使用時(shí)再加載。

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

適合在瀏覽器環(huán)境中異步加載模塊??梢圆⑿屑虞d多個(gè)模塊。

2.缺點(diǎn):

提高了開(kāi)發(fā)成本,并且不能按需加載,而是必須提前加載所有的依賴(lài)。

五、第四階段:CMD規(guī)范

CMD規(guī)范是阿里的玉伯提出來(lái)的,實(shí)現(xiàn)js庫(kù)為sea.js。 它和requirejs非常類(lèi)似,即一個(gè)js文件就是一個(gè)模塊,但是CMD的加載方式更加優(yōu)秀,是通過(guò)按需加載的方式,而不是必須在模塊開(kāi)始就加載所有的依賴(lài)。如下:

define(function(require, exports, module) {
  var $ = require('jquery');
  var Spinning = require('./spinning');
  exports.doSomething = ...
  module.exports = ...
})

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

同樣實(shí)現(xiàn)了瀏覽器端的模塊化加載。
可以按需加載,依賴(lài)就近。

2.缺點(diǎn):

依賴(lài)SPM打包,模塊的加載邏輯偏重。
其實(shí),這時(shí)我們就可以看出AMD和CMD的區(qū)別了,前者是對(duì)于依賴(lài)的模塊提前執(zhí)行,而后者是延遲執(zhí)行。 前者推崇依賴(lài)前置,而后者推崇依賴(lài)就近,即只在需要用到某個(gè)模塊的時(shí)候再require。 如下:

// AMD
define(['./a', './b'], function(a, b) {  // 依賴(lài)必須一開(kāi)始就寫(xiě)好  
   a.doSomething()    
   // 此處略去 100 行    
   b.doSomething()    
   ...
});
// CMD
define(function(require, exports, module) {
   var a = require('./a')   
   a.doSomething()   
   // 此處略去 100 行   
   var b = require('./b') 
   // 依賴(lài)可以就近書(shū)寫(xiě)   
   b.doSomething()
   // ... 
});

六、第五階段: ES6模塊化

之前的幾種模塊化方案都是前端社區(qū)自己實(shí)現(xiàn)的,只是得到了大家的認(rèn)可和廣泛使用,而ES6的模塊化方案是真正的規(guī)范。 在ES6中,我們可以使用 import 關(guān)鍵字引入模塊,通過(guò) export 關(guān)鍵字導(dǎo)出模塊,功能較之于前幾個(gè)方案更為強(qiáng)大,也是我們所推崇的,但是由于ES6目前無(wú)法在瀏覽器中執(zhí)行,所以,我們只能通過(guò)babel將不被支持的import編譯為當(dāng)前受到廣泛支持的 require。

雖然目前import和require的區(qū)別不大,但是還是推薦使用使用es6,因?yàn)槲磥?lái)es6必定是主流,對(duì)于代碼的遷移成本還是非常容易的。 如:

  import store from '../store/index'
  import {mapState, mapMutations, mapActions} from 'vuex'
  import axios from '../assets/js/request'
  import util from '../utils/js/util.js'

  export default {
    created () {
      this.getClassify(); 

      this.RESET_VALUE();
      console.log('created' ,new Date().getTime());

    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容