Node.js入門

一,瞭解Node.js

## 1.簡介:
基於事件驅動,能夠實現異步,非阻塞IO
因爲早期的網景公司和IE發佈的瀏覽器都採用了Javascript的腳本語言,使用至關普遍,直到Google公司發佈了基於Webkit內核的Chrome瀏覽器,而且從新編譯了Javascript的虛擬引擎,命名爲V8,使其運行的速度大幅度提高。
Node.js的發佈:Ryan Dahl的程序員根據需求開發一個高性能的服務器,因爲Google發佈的V8引擎性能很是好,而JavaScript生來就是基於事件,能夠輕鬆的實現回調數據而JavaScript的後端開發領域幾乎是空白的,因此Node.js被創做出來,Node是節點的意思,當時的做者但願它能夠構建大型分佈式可擴展可伸縮的平臺,每個線程、進程甚至服務器都做爲整個平臺的節點
## 2.Node.js的特色
#### 異步非阻塞IO
同步和異步:
同步指的是在請求資源或者查詢數據庫或者在進行大量運算時,須要等待操做完成才能進行下一步動做,同步的代碼都是按照串行順序完成的,中間某一個環節的錯誤有可能會致使整個程序的退出。
異步是相對同步而言,異步僅僅是對於上面提到的動做發送一個請求,但不須要等待請求完成,便可繼續進行後續的操做,而請求的結果執行是在回調函數中完成的。
在專業術語中,同步也叫串行;異步也叫並行。

Node.js中大多數操做都支持異步操做進行(同時也支持同步操做進行),不管是文件讀取仍是網絡請求亦或是數據庫訪問,都支持並行的異步IO操做。因爲異步非阻塞IO的特性,Node.js很是適合作高併發服務器。
#### 基於事件的回調
Node.js中仿照瀏覽器事件的原理針對大部分異步操做都採用了事件處理,在事件中監聽變化並把結果返回給回調函數。所以咱們代碼編寫的順序未必就是實際的執行順序,這有可能會形成代碼閱讀上的障礙。在學習Node.js的過程當中,注意:事件回調函數的第一個形參通常都指代error(即異步處理可能發生的錯誤),而且應該優先處理error。html

const fs = require('fs')
fs.readFile('hello.txt', (err) => {
    if (err) {
        // 這裏發生了錯誤
        console.error(err)
        return
    }
    // 若是沒有錯誤發生,err約定是null.
})

#### 單線程
由於瀏覽器內核運行JavaScript都是在單線程環境下執行的,所以Node.js繼承了JavaScript的單線程特性,可是目前已經擁有了實現多線程的方法:
經過Web Workers建立工做線程來實現多線程,並經過window.postMessage實現線程通訊。
經過child_process實現和Web Workers相似的方式,該特性只有Node.js提供。

#### 跨平臺
Node很是引入關注的特色還有具備跨平臺特性,兼容Window、Linux和Unix(Mac的OSX基於Unix),底層的架構是藉助libuv實現的跨平臺兼容,此外libuv不只用於Node.js,也成爲了許多跨平臺的基礎組件。node

3.Node.js的應用領域

雖然Node.js是爲了高性能服務器而開發,但它並不是適用於全部領域。在當前的後端開發領域,它主要適用於如下場景:jquery

  • IO密集型業務webpack

    自然的異步IO特性讓Node.js很是適合大量的IO請求、讀寫,它能夠快速的處理請求並返回數據。但Node.js不適合計算密集型(例如人工智能算法),這種操做一般交給C++來處理。git

  • 分佈式應用程序員

    因爲高效的IO操做,Node.js很是適合開發數據庫集羣。數據庫的訪問能夠是大量IO請求,只不過請求的處理須要進行密集的計算(數據庫引擎來完成)。阿里巴巴利用Node.js開發了NodeFoxes6

    4Node.js運行時

    安裝完畢Node.js以後,能夠在終端(Windows CMD命令行或者nix終端)輸入: node -v,查看node版本。出現版本號表示安裝成功
    輸入:node回車
    node會進入REPL環境(Read Eval Print Loop:交互式解釋器) ,相似 Window 系統的終端或 Unix/Linux shell,咱們能夠在終端中輸入命令,並接收系統的響應。
    REPL能夠執行:
    讀取用戶輸入或者JavaScript變量聲明
    執行JavaScript代碼
    多行表達式(如 for循環)會自動經過... 來換行
    打印結果
    執行完畢後:
    ctrl + c - 退出當前終端。
    ctrl + c 按下兩次 - 退出 Node REPL。
    github

    5.瞭解NPM

    Node.js安裝完畢後,會隨同它一塊兒安裝了一個NPM工具,該工具做爲npm命令單獨使用。web

NPM是一個包管理工具,它可以輔助用戶遠程安裝其餘的依賴包
用途以下:算法

  • 用戶能夠從NPM倉庫下載第三方包到本地使用。
  • 用戶能夠從NPM倉庫下載安裝第三方命令行工具到本地使用。
  • 容許用戶發佈本身的包或命令行工具到NPM倉庫中。
    Node.js默認是集成NPM的,只須要在終端輸入:npm -v便可打印版本號
$ npm -v
6.4.1

npm經常使用的命令:

1.  npm install [-args] [<@scope>/]<name>[@<version range>]
    安裝第三方依賴包,例如:npm install --global @babel/core@7.6.4
2.  npm uninstall  [-args] [<@scope>/]<name>[@<version range>]:
    卸載模塊,例如:npm uninstall jquery --save-optional,卸載可選階段的依賴裏的jquery
3.  npm update [-g] [<pkg>]
    更新模塊。
4.  npm outdated [[<@scope>/]<pkg>]
    檢查模塊是否已通過時。
5.  npm ls [[<@scope>/]<pkg> ...]
    查看安裝的模塊。
6.  npm init [-f|--force|-y|--yes]
    在項目中引導建立一個package.json文件。
    安裝包的信息可保存到項目的package.json文件中,以便後續的其它的項目開發或者他人合做使用。
7.  npm root [-g]
    查看包的安裝路徑
8.  管理npm的配置路徑有關的命令
npm config set <key> <value> [-g|--global]
npm config get <key>
npm config delete <key>
npm config list
npm config edit
npm get <key>
npm set <key> <value> [-g|--global]
9.  npm cache verify:清理緩存,若是安裝莫名報錯能夠考慮清空緩存。
 [清空Npm緩存]
nodejs 清空 npm 緩存
npm cache clean -f


10. npm start [-- args]:啓動某個腳本指令
    該命令寫在package.json文件scripts的start字段中:
    "scripts": {
        "start": "gulp -ws"
    }
    能夠自定義命令來配置一個服務器環境和安裝一系列的必要程序,如
    此時在cmd中輸入npm start命令至關於執行gulpfile.js文件自定義的watch和server命令。
11. npm stop  [-- args]:中止腳本。
12. npm restart: 重啓腳本。
13. npm publish: 發佈本身的模塊到倉庫。
14. npm version: 查看版本。
詳解npm install

npm install主要功能是在當前目錄下安裝所需的依賴,安裝的依賴包能夠經過引入庫的方式隨意的使用。正規格式以下:其中[]中是可選的<>中表示的是自定義名稱。

npm install 安裝的依賴包默認存儲在項目目錄(須要具備package.json)的node_modules目錄下。

引入依賴包時,會經過一級一級查找node_modules目錄,直到找到該包。
npm install [args] [<@scope>/]<name>[@<version range>]

npm install :須要保證當前目錄下存在package.json文件,基於package.json自動安裝所有依賴。
npm install [args] [<@scope>/]<name>[@<version range>]中的可選參數args:
--save 或 -S :安裝包信息將加到dependencies(生產階段的依賴),開發階段和部署階段都會使用它。
--save-dev 或 -D <package>:安裝包信息將加到devDependencies(開發階段的依賴),只有開發階段會使用它。
-O, –save-optional: 安裝包信息將加入到optionalDependencies(可選階段的依賴)。
-E, –save-exact: 精確安裝指定模塊版本。

npm安裝包的幾種依賴方式:

depedencies:指定應用依賴的外部包,這些依賴是應用正常發佈後正常執行所須要的,**但不包含測試時和本地打包時所使用的包**
devDependencies:**只用於開發環境的包**,不用於生產環境,這些包一般是單元測試或者打包工具等,例如gulp, grunt, webpack, moca, coffee等。
peerDependencies:同等依賴,用於指定本身寫的包兼容的宿主版本。
*試想一下,咱們編寫一個gulp的插件,而gulp卻有多個主版本,咱們只想兼容最新的版本,此時就能夠用同等依賴(peerDependencies)來指定:*
{
    "name": "gulp-my-plugin",
    "version": "0.0.1",
    "peerDependencies": {
        "gulp": "3.x"
    }
}
*當別人使用咱們的插件時,peerDependencies就會告訴明確告訴使用方,你須要安裝該插件哪一個宿主版本。
一般狀況下,咱們會在一個項目裏使用一個宿主(好比gulp)的不少插件,若是相互之間存在宿主不兼容,在執行npm install時,cli會拋出錯誤信息來告訴咱們,好比:*
npm ERR! peerinvalid The package gulp does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer gulp-cli-config@0.1.3 wants gulp@~3.1.9
npm ERR! peerinvalid Peer gulp-cli-users@0.1.4 wants gulp@~2.3.0
可是,假如運行命令npm install gulp-my-plugin –save-dev來安裝本身寫的包,會出現如下依賴圖譜:
├── gulp-my-plugin@0.0.1
└── gulp@3.9.1
optionalDependencies:可選依賴,若是有一些依賴包即便安裝失敗,項目仍然可以運行或者但願npm繼續運行,就可使用optionalDependencies。**另外optionalDependencies會覆蓋dependencies中的同名依賴包,因此不要在兩個地方都寫。**
bundledDependencies / bundleDependencies:打包依賴,bundledDependencies是一個包含依賴包名的數組對象,在發佈時會將這個對象中的包打包到最終的發佈包裏。**可是值得注意的是,這兩個包必須先在devDependencies或dependencies聲明過,不然打包會報錯。**
package.json文件介紹

package.json描述了npm模塊或者自定義項目的一些基本信息
若是自定義項目須要安裝第三方依賴或者本身發佈模塊到npm倉庫,都須要在項目的根目錄下面加入package.json文件,文件格式以下:

{
  // 做者
  "author": {
    "name": "Aseem Kishore",
    "email": "aseem.kishore@gmail.com"
  },
  // 命令行文件路徑
  "bin": {
    "json5": "lib/cli.js"
  },
  // 構建依賴
  "dependencies": {
    "minimist": "^1.2.0"
  },
  // 簡介,用於npm 搜索
  "description": "JSON for humans.",
  // 開發依賴
  "devDependencies": {
    // 版本號介紹
    // version 必須徹底和version一致
    // >version 必須比version大
    // >=version 同上
    // <version 同上
    // <=version 同上
    // ~version 大約同樣,見semver(7)
    // 1.2.x 1.2.0, 1.2.1, 等,但不包括1.3.0
    "core-js": "^2.6.5",
    "eslint": "^5.15.3",
    "eslint-config-standard": "^12.0.0",
    "eslint-plugin-import": "^2.16.0",
    "eslint-plugin-node": "^8.0.1",
    "eslint-plugin-promise": "^4.0.1",
    "eslint-plugin-standard": "^4.0.0",
    "regenerate": "^1.4.0",
    "rollup": "^0.64.1",
    "rollup-plugin-buble": "^0.19.6",
    "rollup-plugin-commonjs": "^9.2.1",
    "rollup-plugin-node-resolve": "^3.4.0",
    "rollup-plugin-terser": "^1.0.1",
    "sinon": "^6.3.5",
    "tap": "^12.6.0",
    "unicode-10.0.0": "^0.7.5"
  },
  // 項目官網
  "homepage": "http://json5.org/",
  // 關鍵字,用於npm 搜索
  "keywords": [
    "json",
    "json5",
    "es5",
    "es2015",
    "ecmascript"
  ],
  // 許可證
  "license": "MIT",
  // 程序入口,import導入默認就加載這個入口
  "main": "lib/index.js",
  "module": "dist/index.mjs",
  // 包名,npm install 就依賴於這個
  "name": "json5",
  // 源碼地址
  "repository": {
    "type": "git",
    "url": "git+https://github.com/json5/json5.git"
  },
  // 可用於npm start的命令。
  "scripts": {
    "build": "rollup -c",
    "build-package": "node build/package.js",
    "build-unicode": "node build/unicode.js",
    "coverage": "tap --coverage-report html test",
    "lint": "eslint --fix .",
    "prepublishOnly": "npm run production",
    "preversion": "npm run production",
    "production": "npm run lint && npm test && npm run build",
    "test": "tap -Rspec --100 test",
    "version": "npm run build-package && git add package.json5"
  },
  // 版本號
  "version": "2.1.1"
}

使用npm以前最好設置下npm的倉庫鏡像,以便提升訪問速度:
npm config set registry [https://registry.npm.taobao.org](https://registry.npm.taobao.org)
下面命令驗證配置是否成功:
npm config get registry
推薦:全局安裝yarn
yarn是Facebook官方發佈的能夠取代npm的的工具,使用命令的方式和npm相似(可選參數不一樣),可以顯著提升安裝依賴的速度,同時還能和npm兼容。
yarn [global][-D] add <pkg>:安裝依賴包。

模塊化

Node.js全部的API都是基於模塊發佈和使用的

模塊化的由來

在JavaScript的初期引用模塊化是經過script標籤來實現的,可是產生了不少的問題:全局的變量污染,沒法找到源頭;過多的script標籤會致使不少雜亂無章的代碼;使用某個庫卻沒相關庫的依賴;沒法追蹤到報錯的位置和錯誤。

CommonJS規範

Node.js首先採用了CommonJS規範,它是Node.js 目前使用最普遍的模塊規範,它是爲了解決JavaScript的做用域問題而定義的模塊,可使每一個模塊的自身命名空間執行

CommonJS使用規則

- 每一個js文件就是一個模塊,模塊有本身的做用域。在一個文件裏面定義的變量、函數、類,都是私有的,對其餘文件不可見。每一個模塊內部,module變量(默認擁有)表明當前模塊。這個變量是一個對象,它的exports屬性(即module.exports)是對外的接口。加載某個模塊,實際上是加載該模塊的module.exports屬性。

- 模塊必須經過 module.exports 導出對外的變量或接口。

引用

文件a.js

var a=10
module.exports=a

文件b.js

var a=require('./a.js')   ---此處爲路徑,a.js的路徑
console.log(a)

注意
commonjs加載是同步的,所以沒法按需加載

ES6中的模塊化

ES6模塊是ECMA組織從語言層面提出的標準模塊化API,將來徹底能夠取代CommonJS和其餘的模塊化系統。
基本使用方式
文件a.js

var a=10
export default a
export const name='小明'

文件b.js

import a,{name}from'./a.js'//路徑,a.js路徑
console.log(a)
console.log(name)

它具備以下優點:

  • 基於編譯時加載,可讓模塊在編譯階段就能進行靜態語法分析,從而提早預警語法錯誤或者作類型校驗。
    注意
    ES6模塊默認在嚴格模式下執行,即默認在模塊頭部加入:"use strict"。

尤爲注意:頂層的this指向undefined,不該該在頂層代碼使用this

AMD模塊

基本使用方式
文件a.js

define(function(){
var a=10
module.export=a
})

文件b.js

var a=require('./a.js')//文件路徑,a.js的路徑
console.log(a)
相關文章
相關標籤/搜索