淺談NodeJs的模塊機制

  J歷史php

  咱們都知道,js在剛被建立的時候,只是爲了在網頁上寫一些小腳本而已,好比網頁特效,表單驗證等等,創立者也許沒覺悟到之後的js會發展到如此規模。這是web1.0時代。前端

  在web 2.0時代,各類前端庫,前端框架被開發出來,jquery,angular就是表明。此時js的功能也就從寫寫小特效啥的躍遷到了應用開發的級別上。能夠說,js經歷了工具類庫,組件庫,前端框架,前端應用的變遷。java

  因而在愈來愈普遍的應用中,js暴露了它先天就缺少的一項功能:模塊。在其它高級語言,都有模塊的定義,java有類,python有import機制,ruby有require,php有require和include。而js此時還單純的用script標籤引入,用命名空間來約束代碼,雜亂無章,因而,commonjs規範便應運而出。node

  commonJS的模塊規範python

  commonjs規範的出發點就是讓js在任何地方都能運行。它彌補了js此時的幾點缺陷:jquery

  沒有模塊概念web

  標準庫較少json

  沒有標準接口後端

  沒有包管理系統瀏覽器

  固然,現在commonjs規範已經解決了大部分問題,並且涵蓋了模塊,二進制,Buffer,字符集編碼,I/O流,單元測試,web服務網關接口,包管理,等。

  commonjs對模塊的定義很簡單,包含了模塊定義,模塊引用,模塊標識3個部分。

  模塊引用

  var xx = require('xxx')

  關鍵字require來接受模塊標識,引入這個模塊的API到上下文中。

  模塊定義

  一個例子來解釋:

  //add.jsfunction add(a,b){ return a+b;

  }// 這樣導出的 add是做爲 exports 的一個方法被導出的exports.add = add;// main.jsvar Add = require('add');console.log(Add.add(1,2));//Add是require引入的模塊名,add是方法名。

  node在編譯的時候,會把代碼封裝成以下的樣子

  // require 是對 Node.js 實現查找模塊的 Module._load 實例的引用// __finename 和 __dirname 是 Node.js 在查找該模塊後找到的模塊名稱和模塊絕對路徑(function(exports,require,module,__filename,__dirname){ function add (a,b){ return a+b;

  }

  exports.add = add;

  })

  爲了將函數直接導出成一個模塊,而不是一個方法,用到了全局變量module,下面就是咱們常見的樣子了:

  // add.jsfunction add (a,b){ return a+b ;

  }module.exports = add;// main.jsvar add = require('add');console.log(add(1,2));

  模塊標識

  模塊標識就是require()裏的參數,必須是小駝峯命名的字符串,或者是路徑(./ 或../)。能夠沒有後綴.js

  Node的模塊機制

  Node並非徹底按照commonjs規範來實現,而是進行了一些取捨,並增長了本身的一些特性。

  Node中引入模塊,經歷3個步驟:

  路徑分析

  文件定位

  編譯執行

  Node中模塊分爲2種,核心模塊(Node提供的)和文件模塊(用戶本身編寫的)

  Node對引入過的模塊會進行緩存,就像前端瀏覽器會緩存靜態腳原本提升性能同樣。require()方法在對同一模塊的二次加載一概採用緩存優先的方式。可是對核心模塊的緩存檢查優先於對文件模塊的緩存檢查。

  路徑分析

  就是對模塊標識的分析唄。

  模塊標識符在Node中分如下幾類:

  核心模塊,如http,path

  ./ ../相對路徑

  / 絕對路徑

  非路徑形式的文件模塊。

  文件分析

  若是模塊標識符沒有後綴,默認補上後綴從.js,.json,.node來次序查找。

  模塊編譯

  js編譯上面已經提到了。Node對JS文件進行了包裝,在頭部添加了(function (exports, require, module, __filename, __dirname) {...})。這樣每一個模塊都進行了做用域隔離。包裝以後經過vm原生模塊的runInThisContext()方法執行(相似eval,只是具備明確上下文,不污染全局)返回一個function。而後將上述參數傳給這個function執行。

  json編譯更簡單,Node直接用JSON.parse()方法編譯json內容,獲得的對象賦給exports。

  包和NPM

  commonjs的包規範包含2個組成部分,包結構和包描述文件

  包描述文件:package.json

  包結構:

  package.json 包描述文件

  bin: 存放可執行二進制文件的目錄

  lib 存放js代碼的目錄

  doc. 存放文檔的目錄

  test: 存放單元測試用例的代碼

  NPM的用法就很少說了。

  先後端公用模塊

  自從Node出來之後,js也能夠運用在後端。可是先後端的JS扮演的角色不一樣,瀏覽器端的js須要經歷從同一個服務器分發到多個客戶端執行。服務端的js則是相同的代碼屢次執行。前者的瓶頸在於帶寬。後者的瓶頸在於CUP和內存。前者須要經過網絡加載。後者從磁盤中加載。

  由於Node基於commonjs規範來同步的加載模塊的。前端若用同步方式來加載模塊,在用戶體驗上會形成很大的問題。UI在初始化的時候須要等待很長時間來加載js腳本。因此提出了異步模塊定義AMD和CMD。這在個人另外一篇博客中有提到。就很少說了。

  爲了寫個能兼容先後端的模塊規範,類庫的開發者要把代碼包裝在一個 閉包裏。這樣就能兼容Node,AMD,CMD和常見的瀏覽器。


相關文章
相關標籤/搜索