1. 程式人生 > >Node.js(day3)

Node.js(day3)

一、模組系統

1.什麼是模組

Node.js中常用的核心模組有:

  • http模組
  • fs檔案系統模組
  • url模組
  • path模組
  • os系統模組
    在使用Node.js中我們發現每個js之間是沒有聯絡的,都是單獨的一個作用域,這就是模組系統的設計。(相關概念請參考CommonJs規範
    簡言之,Node.js中的js不像普通的js具有全域性變數,而是以模組(檔案)為作用域,不會汙染其他檔案。而使用者書寫的js就是自定義模組,下載安裝的就是第三方模組,自帶的js就是核心模組。
    既然模組沒有了全域性作用域,那麼我們需要使用模組就需要進行載入和匯出通訊規則。
  • 載入:require()
  • 匯出:exports | module.exports

    2.exports和module.exports的區別

    首先兩者都是js檔案(模組)用於匯出變數的物件,如果你執行這樣的語句:
console.log(exports === module.exports);

你會發現結果為true。也就是說這兩個變數其實是指向同一個物件的引用。
底層原始碼類似這樣:

var module = {
    exports:{}
}
var exports = module.exports;

所以我們可以使用exports或module.exports來匯出變數。其實exports的作用就是簡化module.exports的書寫而已。
但是需要注意的是,不能對exports直接賦值,類似exports = function(...);這樣就切斷了var exports = module.exports;

這一關係。而底層最後執行的是return module.exports,所以使用exports時注意不能進行賦值操作即可。

3.require載入規則

直接說結論:

require載入本質上都是在載入檔案來實現模組功能

  • 載入自定義模組
    我們在載入自定義檔案時只需要寫明檔案路徑即可(基本都會使用相對路徑)。
    比如在我們需要在a.js中價值b.js。(假設在同一級目錄),我們只需要寫:
var bExports =  require('./b');//字尾可省略

另外,require有一個載入機制就是:優先從快取載入
比如現在同級目錄下還有一個c.js,且b.js和a.js中都有require('./c')這樣的語句。
結果就是:執行a.js --> 載入b.js -->載入c.js -->結束。
注意,這裡c.js並不會載入兩次

,這是require得優先從快取載入機制決定的,第一次載入c.js之後會將匯出的變數儲存到快取中,下次需要載入c.js時直接從快取中取出使用即可。這樣的機制提高了載入效率。

  • 載入核心模組
    對於核心模組的載入,我們可能沒有見到什麼js檔案,這其實是Node.js為了使用者方便使用直接為我們提供了模組對於的名稱,比如http就代表http模組,require('http')其實也是載入了檔案的,只是不是直接載入js檔案,而是編譯後的二進位制檔案。
  • 載入第三方模組
    首先要使用第三方模組必須使用npm下載安裝。
    比如載入art-template模組,我們只需要:
var template = require('art-template');

第三方模組最終也是加在執行js檔案,尋找需要載入檔案的步驟為(以require(art-template)):

  • 在執行的js檔案的同級檔案目錄下尋找node_modules資料夾(npm安裝的時候會自動建立)
  • 在node_modules下找到art-template目錄
  • 找到package.json檔案,讀取鍵為main 的值,一般為index.js
  • 載入找到的js檔案。
  • 以上情況為正常情況,也可能出現node_modules、art-template、package.json檔案、main值找不到的情況,如果是art-template能找到,後面的檔案找不到會預設執行index.js,如果index.js也不存在這是會向上一級查詢node_modules目錄,然後重複以上查詢規則,直到找到或查詢值磁碟根目錄,如果最終都沒有找到可以執行的檔案會報cannot find module 'art-template'的錯誤資訊。

二、包說明檔案

上面說到require()在載入第三方模組時會使用到package.json檔案,這個檔案就是包說明檔案。包說明檔案中包含了關於包(模組)的相關資訊,比如入口main、依賴dependencies等。
當我們使用npm install art-template安裝art-template模組時,發現生成的node_module檔案目錄下除了art-template還有許多其他模組,這是因為art-template模組本身也依賴了其他的一些模組,所以也需要安裝,以此類推依賴包的依賴包也需要安裝。
但是這樣會存在一個問題,當我們的專案很大,使用的模組也變多的時候,我們可能會忘記我們使用了哪些依賴包,所以我們希望在某個檔案下將依賴包的資訊記錄下來,這是package.json包說明檔案的另一個作用。
在安裝目錄下新建一個package.json檔案,內容為{}(必需),我們安裝模組時常用下面語句(--save)

npm install art-template --save

然後開啟package.json檔案,發現多了依賴資訊:

這樣,我們就能記錄專案的依賴包資訊。(高版本的npm無論有沒有--save都會產生一個package-lock.json檔案,裡面記錄的是本次下載安裝所有依賴包資訊)

我們不必每次都手動建立package.json檔案,而是使用npm init來建立。
然後會出現一步一步讓我們填寫關於本專案的基本資訊,可一路回車,使用預設設定。另:npm init --y可跳過設定,直接初始化完成。然後我們發現目錄下建立了一個package.json檔案,並寫入了相關資訊:

三、npm常用命令

  • 版本檢視
npm --version
npm -v
  • 更新npm
npm insatll npm --global
  • 安裝包
npm install
npm install 包名
npm intsall 包名 --save
  • 解除安裝包
npm uninstall
npm uninstall 包名
npm uninstall 包名 --save
  • 使用幫助
npm help
npm 命令 --help
  • 簡寫形式
--version 簡寫為 -v
install 簡寫為 i
uninstall 簡寫為 un
--save 簡寫為 -S
--help 簡寫為 -h
--global 簡寫為 -g

四、解決npm被牆的問題

某些npm包資源需屬於境外資源,可能被牆,這種時候可能出現安裝較慢或失敗的情況,為了解決這個問題可以安裝npm的國內映象:cnpm
cnpm是淘寶團隊對npm在國內的備份,官網地址:點這裡
安裝很簡單:

//必需安裝到全域性
npm insatll cnpm -g

然後使用cnpm進行包安裝即可,例如:

cnpm install art-template

五、初體驗:第三方模組Express
Express是高度整合的http模組,提高了我們直接使用http模組進行開發web伺服器的效率。
相關介紹及使用可參考官網Express

1.安裝

npm install express --save

2.helloWorld

var express = require('express');

//建立web服務
var app = express();
//建立伺服器視窗
app.listen(8000,function(){
    console.log('server running...');
});

//get請求事件
//當以get方式請求為'/'時觸發
app.get('/',function(req,res){
    res.send('hello express.你好express!');
});
//當以get方式請求為'/about'時觸發
app.get('/about',(req,res) => {
    res.send(`
        <!DOCTYPE html>
        <html>
        <head>
            <title>About me</title>
            <meta charset="utf-8">
        </head>
        <body>
            <h1>我是Express...</h1>
        </body>
        </html>
    `
    );
});

訪問情況:

我們發現express相比http簡化了一些,首先是api比較簡單,其次是對請求的url進行了處理,我們不用再使用request.url來注意判斷,,然後是訪問不到的路徑也進行了處理,最後就是Conten-Type也不需要我們手動設定了。當然express的優點不止這些,後續會逐漸用到。

3.express處理靜態資原始檔

在之前的http核心模組中我們如果要訪問某個目錄下的資原始檔,需要進行統一處理,然後再根據request.url來判斷並使用fs檔案系統模組來讀取檔案並輸出到頁面,但在express中,我們只需要對目錄進行簡單的靜態處理即可(首先建立一個public目錄,裡面放置一些資原始檔方便試驗),我們只需要在剛才的檔案中使用這個一個api即可:

//對目錄進行靜態資源處理,並使用
app.use('/public',express.static('./public'));

訪問結果:

相關說明

  • express僅用了一個api就完成了http中需要進行相關判斷的操作,且不需要手動建立fs模組來讀取檔案。
  • express.static('路徑')可以將路徑轉換為可通過url直接訪問的靜態資原始檔。
  • app.use('url訪問路徑',靜態資原始檔)是設定靜態資源訪問的路徑,如果不設定預設為/

更多有關Express的使用請參考下一篇文章