## 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)