## 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
雖然Node.js是爲了高性能服務器而開發,但它並不是適用於全部領域。在當前的後端開發領域,它主要適用於如下場景:jquery
IO密集型業務webpack
自然的異步IO特性讓Node.js很是適合大量的IO請求、讀寫,它能夠快速的處理請求並返回數據。但Node.js不適合計算密集型(例如人工智能算法),這種操做一般交給C++來處理。git
分佈式應用程序員
因爲高效的IO操做,Node.js很是適合開發數據庫集羣。數據庫的訪問能夠是大量IO請求,只不過請求的處理須要進行密集的計算(數據庫引擎來完成)。阿里巴巴利用Node.js開發了NodeFoxes6
安裝完畢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
Node.js安裝完畢後,會隨同它一塊兒安裝了一個NPM工具,該工具做爲npm命令單獨使用。web
NPM是一個包管理工具,它可以輔助用戶遠程安裝其餘的依賴包
用途以下:算法
$ 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 安裝的依賴包默認存儲在項目目錄(須要具備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描述了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標籤會致使不少雜亂無章的代碼;使用某個庫卻沒相關庫的依賴;沒法追蹤到報錯的位置和錯誤。
Node.js首先採用了CommonJS規範,它是Node.js 目前使用最普遍的模塊規範,它是爲了解決JavaScript的做用域問題而定義的模塊,可使每一個模塊的自身命名空間執行
- 每一個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模塊是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)
它具備以下優點:
尤爲注意:頂層的this
指向undefined
,不該該在頂層代碼使用this
。
基本使用方式
文件a.js
define(function(){ var a=10 module.export=a })
文件b.js
var a=require('./a.js')//文件路徑,a.js的路徑 console.log(a)