Node.js(二)

2021-03-02 Java筆記蝦

來源:風之之
www.cnblogs.com/fzz9/p/9916909.html

一、模塊系統1、什麼是模塊

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

http模塊

fs文件系統模塊

url模塊

path模塊

os系統模塊

在使用Node.js中我們發現每個js之間是沒有聯繫的,都是單獨的一個作用域,這就是模塊系統的設計。

簡言之,Node.js中的js不像普通的js具有全局變量,而是以模塊(文件)為作用域,不會汙染其他文件。而用戶書寫的js就是自定義模塊,下載安裝的就是第三方模塊,自帶的js就是核心模塊。

既然模塊沒有了全局作用域,那麼我們需要使用模塊就需要進行加載和導出通信規則。

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;這一關係。而底層最後執行的是returnmodule.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 

然後打開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 包名 

使用幫助

npm help
npm 命令 --help

簡寫形式


install 簡寫為 i
uninstall 簡寫為 un



四、解決npm被牆的問題

某些npm包資源需屬於境外資源,可能被牆,這種時候可能出現安裝較慢或失敗的情況,為了解決這個問題可以安裝npm的國內鏡像:cnpm

cnpm是淘寶團隊對npm在國內的備份,

安裝很簡單:

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

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

cnpm install art-template

五、初體驗:第三方模塊Express

Express是高度集成的http模塊,提高了我們直接使用http模塊進行開發web伺服器的效率。

1、安裝

npm install express 

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訪問路徑',靜態資源文件)是設置靜態資源訪問的路徑,如果不設置默認為/。

相關焦點

  • Node.js模塊化
    在 Node.js 環境中,默認就支持模塊系統,該模塊系統遵循 CommonJS 規範。在 Node,js 中一個 js 文件就是一個模塊模塊內部代碼對於外部來說都是不可見的,如需使用,可以通過兩種方式向外部暴露模塊成員導出在每一個模塊文件中,都會存在一個 module 對象,即模塊對象。
  • 一些小眾卻有用的 Node.js 包
    ,然後在命令行中執行 node index.js -x 3,會看到如下消息:Usage: index.js -x [num] -y [num]Options: -x [required] -y
  • 如何使用 npm 管理 NodeJS 包 | Linux 中國
    package name: (demo)version: (1.0.0)description: demo nodejs appentry point: (index.js)test command:git repository:keywords:author:license
  • 深入研究 Node.js 的回調隊列
    在本文中,我們將深入研究 Node.js 中的隊列:它們是什麼,它們如何工作(通過事件循環)以及它們的類型。Node.js 中的隊列是什麼?隊列是 Node.js 中用於組織異步操作的數據結構。這些操作以不同的形式存在,包括HTTP請求、讀取或寫入文件操作、流等。
  • Node.js幾種創建子進程方法
    execFilechild_process.execFile(file[, args][, options][, callback])const { execFile } = require('child_process')execFile('node
  • 理解 Node.js 中的 Worker Threads
    與之前提到的 Node.js 的構成,即一個進程 + 一個線程 + 一個事件循環 + 一個 JS 引擎 + 一個 Node.js 實例所不同,工作線程的方式採用的是一個進程 + 多個線程 + 每個線程一個時間循環 + 每個線程一個 JS 引擎 + 每個線程一個 Node.js 實例。
  • Node.js v17 來了,看看都有哪些新功能?
    如下例所示:// test.mjsimport * as readline from "node:readline/promises";import { stdin as input, stdout as output } from 'process';const rl = readline.createInterface
  • Node.js v17來了,Nodejs能崛起嗎?
    Node.js v17 版本已發布,在這個版本中提供了一些新的功能:基於 Promise 的其它核心模塊 API       錯誤堆棧尾部增加 Node.js 版本信息OpenSSL 3.0 支持v8 JavaScript 引擎更新至 9.5。
  • 【譯】Node.js的eventloop,timers和process.nextTick()
    事件循環是實現 Node.js 的非阻塞 I/O 操作的機制,在可能的時候將操作交給系統內核,儘管JavaScript 其實是單線程運行的。由於大多數系統內核是多線程的,它們可以在後臺同時執行多個操作。當其中的一個操作完成後,內核就會通知 Node.js,將合適的回調添加到輪詢隊列中,並等待時機執行。我們接下來將會在本文中進一步解釋。
  • Node.js模塊接口七大設計模式
    為了證明這點,我們在Node REPL中進行一些操作:$ node   > f1 = require('/Users/alon/Projects/export_this/function');  [Function]   > f2 = require('.
  • get、post 請求中常見 content-type 請求頭以及 nodeJs 解析請求參數
    演示代碼準備這裡我們基於 node Express 庫搭建一個簡單的伺服器,用來解析頁面發起的各種類型請求環境要求:安裝 nodeJs, 安裝 web 服務啟動工具 npm install -g serve目錄結構
  • Node 最新 Module 導入導出規範
    包由包含 package.json 的文件夾和所有子文件夾組成,直到下一個含另一個 package.json 的文件夾,或者 node_modules 文件夾。本頁為大家介紹如何書寫 package.json。頁面底部還有 Node.js 定義的 package.json 欄位供參考。二.
  • Node.js 中如何收集和解析命令行參數
    收集命令行參數  在 Node.js 中,可以通過 process.argv 屬性收集進程被啟動時傳入的命令行參數:  // ./example/demo.js  process.argv.slice(2);  // 命令行執行如下命令  node .
  • JS MODULE 大戰
    比如,nodejs 就不支持 import 和 export,明明 nodejs 支持其他的 ES6 語法,怎麼就對 import 和 export 如此不友好,筆者認為 nodejs是為了實現commonJS的規範,因此不能接受ES6的模塊擾亂nodejs的模塊規範。所以說 CommonJS 和 ES6 的模塊才是真正的規範。
  • Redis+Node.js實現一個能處理海量數據的異步任務隊列系統
    二、使用 NodeJS 操作 Redis異步任務隊列使用 Redis 來實現,因此我們需要部署一個單獨的 Redis 服務。在本地開發中為了快速完成 Redis 的安裝,我使用了 Docker 的辦法(默認機器已經安裝了 Docker)。
  • Python Django + 前端Vue.js快速搭建web項目
    命令:pip install django即可安裝最新版本的django        或者pip install django==1.11.13安裝指定版本Vue.js系:Node.js 8.11.2有關Vue的模塊(包括vue)可以使用node自帶的npm包管理器安裝。
  • vue.js-使用vue-cli3快速創建項目
    Vue.js 全家桶系列:包含了 vue-router、vuex、vue-resource,以及本文介紹的構建工具 vue-cli。這些是一個完整的 vue 項目的核心構成。path /usr/local/lib/node_modules/@vue/cli/node_modules/@babel/compat-datanpm ERR! errno -13npm ERR!
  • 分享4個Linux中Node.js的進程管理器
    Node.js進程管理器是一個有用的工具,可以確保Node.js進程或腳本連續(永久)運行,並使其能夠在系統引導時自動啟動。
  • Node.js 進階之 fs 文件模塊學習
    Node.js 中的 fs 模塊是文件操作的封裝,它提供了文件讀取、寫入、更名、刪除、遍歷目錄、連結等 POSIX 文件系統操作。與其它模塊不同的是,fs 模塊中所有的操作都提供了異步和同步的兩個版本,具有 sync 後綴的方法為同步方法,不具有 sync 後綴的方法為異步方法。
  • Electron和Node.js環境配置
    { "name": "ui-designer-demo", "version": "1.0.0", "description": "A minimal Electron application", "main": "main.js", "scripts": { "start": "electron ." }, "keywords