這篇文章給大家分享的是有關(guān)Node.js 的模塊有哪些的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧。
目前創(chuàng)新互聯(lián)已為千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、納雍網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。JavaScript 做為一門(mén)為網(wǎng)頁(yè)添加交互功能的簡(jiǎn)單腳本語(yǔ)言問(wèn)世,在開(kāi)始并不包含模塊系統(tǒng),隨著 JavaScript 解決問(wèn)題越來(lái)越復(fù)雜,把所有代碼寫(xiě)在一個(gè)文件內(nèi),用 function 區(qū)分功能單元已經(jīng)不能支撐復(fù)雜應(yīng)用開(kāi)發(fā)了,ES6 帶來(lái)了大部分高級(jí)語(yǔ)言都有的 class 和 module,方便開(kāi)發(fā)者組織代碼
import _ from 'lodash'; class Fun {} export default Fun;
上面三行代碼展示了一個(gè)模塊系統(tǒng)最重要的兩個(gè)要素 import 和 export
export
用于規(guī)定模塊的對(duì)外接口
import
用于輸入其他模塊提供的功能
而在 ES6 之前,社區(qū)出現(xiàn)了很多模塊加載方案,最主要的有 CommonJS 和 AMD 兩種,Node.js 誕生早于 ES6,模塊系統(tǒng)使用的是類(lèi)似 CommonJS 的實(shí)現(xiàn),遵從幾個(gè)原則
一個(gè)文件是一個(gè)模塊,文件內(nèi)的變量作用域都在模塊內(nèi)
使用module.exports
對(duì)象導(dǎo)出模塊對(duì)外接口
使用require
引入其它模塊
circle.js
const { PI } = Math; module.exports = function area(r) { PI * r ** 2; };
上面代碼就實(shí)現(xiàn)了 Node.js 的一個(gè)模塊,模塊沒(méi)有依賴其它模塊,導(dǎo)出了方法area
計(jì)算圓的面積
test.js
const area = require('./circle.js'); console.log(`半徑為 4 的圓的面積是 ${area(4)}`);
模塊依賴了 circle.js,使用其對(duì)外暴露的 area 方法,計(jì)算圓的面積
模塊對(duì)外暴露接口使用 module.exports,常見(jiàn)的有兩種用法:為其添加屬性或賦值到新對(duì)象test.js
// 添加屬性 module.exports.prop1 = xxx; module.exports.funA = xxx; module.exports.funB = xxx; // 賦值到全新對(duì)象 module.exports = { prop1, funA, funB, };
兩種寫(xiě)法是等價(jià)的,使用時(shí)候沒(méi)區(qū)別
const mod = require('./test.js'); console.log(mod.prop1); console.log(mod.funA());
還有另外一種直接使用exports
對(duì)象的方法,但是只能對(duì)其添加屬性,不能賦值到新對(duì)象,后面會(huì)介紹原因
// 正確的寫(xiě)法:添加屬性 exports.prop1 = xxx; exports.funA = xxx; exports.funB = xxx; // 賦值到全新對(duì)象 module.exports = { prop1, funA, funB, };
require 用法比較簡(jiǎn)單,id 支持模塊名和文件路徑兩種類(lèi)型
const fs = require('fs'); const _ = require('lodash');
示例中的 fs、lodash 都是模塊名,fs 是 Node.js 內(nèi)置的核心模塊,lodash 是通過(guò) npm 安裝到node_modules
下的第三方模塊,如果出現(xiàn)重名,優(yōu)先使用系統(tǒng)內(nèi)置模塊
因?yàn)橐粋€(gè)項(xiàng)目?jī)?nèi)可能會(huì)包含多個(gè) node_modules 文件夾(Node.js 比較失敗的設(shè)計(jì)),第三方模塊查找過(guò)程會(huì)遵循就近原則逐層上溯(可以在程序中打印module.paths
查看具體查找路徑),直到根據(jù)NODE_PATH
環(huán)境變量查找到文件系統(tǒng)根目錄,具體過(guò)程可以參考官方文檔
此外,Node.js 還會(huì)搜索以下的全局目錄列表:
其中$HOME
是用戶的主目錄,$PREFIX
是 Node.js 里配置的node_prefix
。強(qiáng)烈建議將所有的依賴放在本地的 node_modules 目錄,這樣將會(huì)更快地加載,且更可靠
模塊還可以可以使用文件路徑加載,這是項(xiàng)目?jī)?nèi)自定義模塊的通用加載方式,路徑可以省略拓展名,會(huì)按照 .js、.json、.node 順序嘗試
'/'
為前綴的模塊是文件的絕對(duì)路徑,按照系統(tǒng)路徑查找模塊'./'
為前綴的模塊是相對(duì)于當(dāng)前調(diào)用 require 方法的文件,不受后續(xù)模塊在哪里被使用到影響模塊在第一次加載后會(huì)被緩存到Module._cache
,如果每次調(diào)用require('foo')
都解析到同一文件,則返回相同的對(duì)象,同時(shí)多次調(diào)用require(foo)
不會(huì)導(dǎo)致模塊的代碼被執(zhí)行多次。 Node.js 根據(jù)實(shí)際的文件名緩存模塊,因此從不同層級(jí)目錄引用相同模塊不會(huì)重復(fù)加載。
理解的模塊單次加載機(jī)制方便我們理解模塊循環(huán)依賴后的現(xiàn)象a.js
console.log('a 開(kāi)始'); exports.done = false; const b = require('./b.js'); console.log('在 a 中,b.done = %j', b.done); exports.done = true; console.log('a 結(jié)束');
b.js
console.log('b 開(kāi)始'); exports.done = false; const a = require('./a.js'); console.log('在 b 中,a.done = %j', a.done); exports.done = true; console.log('b 結(jié)束');
main.js
:
console.log('main 開(kāi)始'); const a = require('./a.js'); const b = require('./b.js'); console.log('在 main 中,a.done=%j,b.done=%j', a.done, b.done);
當(dāng) main.js 加載 a.js 時(shí),a.js 又加載 b.js,此時(shí),b.js 會(huì)嘗試去加載 a.js
為了防止無(wú)限的循環(huán)會(huì)返回一個(gè) a.js 的 exports 對(duì)象的未完成的副本 給 b.js 模塊,然后 b.js 完成加載,并將 exports 對(duì)象提供給 a.js 模塊
因此示例的輸出是
main 開(kāi)始 a 開(kāi)始 b 開(kāi)始 在 b 中,a.done = false b 結(jié)束 在 a 中,b.done = true a 結(jié)束 在 main 中,a.done=true,b.done=true
看不懂上面的過(guò)程也沒(méi)關(guān)系,日常工作根本用不到,即使看懂了也不要在項(xiàng)目中使用循環(huán)依賴!
Node.js 每個(gè)文件都是一個(gè)模塊,模塊內(nèi)的變量都是局部變量,不會(huì)污染全局變量,在執(zhí)行模塊代碼之前,Node.js 會(huì)使用一個(gè)如下的函數(shù)封裝器將模塊封裝
(function(exports, require, module, __filename, __dirname) { // 模塊的代碼實(shí)際上在這里 });
回頭看看最開(kāi)始的問(wèn)題,為什么 exports 對(duì)象不支持賦值為其它對(duì)象?把上面函數(shù)添加一句 exports 對(duì)象來(lái)源就很簡(jiǎn)單了
const exports = module.exports; (function(exports, require, module, __filename, __dirname) { // 模塊的代碼實(shí)際上在這里 });
其它模塊 require 到的肯定是模塊的 module.exports 對(duì)象,如果吧 exports 對(duì)象賦值給其它對(duì)象,就和 module.exports 對(duì)象斷開(kāi)了連接,自然就沒(méi)用了
隨著 ES6 使用越來(lái)越廣泛,Node.js 也支持了 ES6 Module,有幾種方法
使用 babel 構(gòu)建是在 v12 之前版本最簡(jiǎn)單、通用的方式,具體配置參考 @babel/preset-env(https://babeljs.io/docs/en/babel-preset-env)
.babelrc
{ "presets": [ ["@babel/preset-env", { "targets": { "node": "8.9.0", "esmodules": true } }] ] }
在 v12 后可以使用原生方式支持 ES Module
開(kāi)啟--experimental-modules
模塊名修改為.mjs
(強(qiáng)烈不推薦使用)或者 package.json 中設(shè)置"type": module
感謝各位的閱讀!關(guān)于Node.js 的模塊有哪些就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!