1 Node.js是什么?
Node.js 是一个 Javascript 运行环境(runtime)。
实际上它是对 Google V8 引擎进行了封装,V8 引擎执行 JavaScript 的速度非常快,性能非常好;而 Node.js 对一些特殊用例进行了优化,提供了替代的 API,使得 V8 在非浏览器环境下运行得更好,用于方便地搭建响应速度快、易于扩展的网络应用。
Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。
其官方站点:Node.js
2 发展史
- 2009年2月,Ryan Dahl在博客上宣布准备基于 V8 创建一个轻量级的 Web 服务器并提供一套库。
- 2009年5月,Ryan Dahl在 GitHub 上发布了最初版本的部分 Node.js 包,随后几个月里,有人开始使用 Node.js 开发应用。
- 2009年11月和2010年4月,两届 JSConf 大会都安排了 Node.js 的讲座。
- 2010年年底,Node.js 获得云计算服务商 Joyent 资助,创始人Ryan Dahl加入Joyent全职负责 Node.js 的发展。
- 2011年7月,Node.js 在微软的支持下发布 Windows 版本
3 特性
V8 引擎本身使用了一些最新的编译技术,这使得用 JavaScript 这类脚本语言编写出来的代码运行速度获得了极大提升,又节省了开发成本。
对性能的苛求是 Node 的一个关键因素,JavaScript 是一个事件驱动语言,Node 利用了这个优点,编写出可扩展性高的服务器。
Node 采用了一个称为“事件循环(event loop)”的架构,使得编写可扩展性高的服务器变得既容易又安全;提高服务器性能的技巧有多种多样,Node 选择了一种既能提高性能,又能减低开发复杂度的架构,这是一个非常重要的特性。
并发编程通常很复杂且遍地是雷,而 Node 绕过了这些,但仍能提供很好的性能。
Node 采用一系列“非阻塞”库来支持事件循环的方式,本质上就是为文件系统、数据库之类的资源提供接口。
向文件系统发送一个请求时,无需等待硬盘(寻址并检索文件),硬盘准备好的时候非阻塞接口会通知 Node。
该模型以可扩展的方式简化了对慢资源的访问, 直观,易懂。尤其是对于熟悉 onmouseover、onclick 等 DOM 事件的用户,更有一种似曾相识的感觉。
虽然让 JavaScript 运行于服务器端不是 Node 的独特之处,但却是其一强大功能,成为事实上的平台。
在 Node 项目启动的很短时间内,社区就已经贡献了大量的扩展库(模块),其中很多是连接数据库或是其他软件的驱动,但还有很多是凭他们的实力制作出来的非常有用的软件。
最后,不得不提到的是 Node 社区:虽然 Node 项目对比其他服务器项目还是非常年轻,但很少看到对一个项目如此狂热的社区;不管是新手,还是专家,大家都围绕着项目,使用并贡献自己的能力,致力于打造一个探索、支持、分享、听取建议的乐土。
- Node.js 的优点
作为一个新兴的后台语言,Node.js 有很多吸引人的地方:
- RESTful API
- 单线程:Node.js 可以在不新增额外线程的情况下,依然可以对任务进行并行处理 —— Node.js 是单线程的;它通过事件轮询(event loop)来实现并行操作,对此,我们应该要充分利用这一点 —— 尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。
- 非阻塞 I/O
- V8 虚拟机
- 事件驱动
4 模块
Node.js 使用 Module(模块)去划分不同的功能,以简化应用的开发。
模块有点像 C++ 语言中的类库,每一个 Node.js 的类库都包含了十分丰富的各类函数,比如 http 模块就包含了和 http 功能相关的很多函数,可以帮助开发者很容易地对比如 http、tcp/udp 等进行操作,还可以很容易的创建 http 和 tcp/udp 的服务器。
要在程序中使用模块是十分方便的,一般是如下步骤:
首先安装模块,比如通过 NPM 或者 yarn 这类包管理工具来找到并安装对应模块,当然这里举例的 http 模块是 Node.js 内建的,所以无需单独安装;不过如果是非内建模块,这样安装:
npm install <Module name>
接着,在安装了模块之后,我们就需要在开发项目当中引入该模块了。这个时候,Node.js 会在我们应用中搜索是否存在 node_modules 的目录,并且搜索这个目录中是否存在模块;如果找不到这个目录,则会到全局模块缓存中去寻找,同时用户可以通过相对或者绝对路径,指定模块的位置,比如:
const myModule = require('./myModule.js');
模块中包含了很多功能代码片断,在模块中的代码大部分都是私有的,意思是在模块中定义的函数方法和变量,都只能在同一个模块中被调用。
当然,可以将某些方法和变量暴露到模块外,这个时候可以使用 exports 去实现。
5 安装
5.1 Linux
(1)直接使用已编译好的包
Node 官网已经把 Linux 下载版本更改为已编译好的版本了,我们可以直接下载解压后使用:
wget https://nodejs.org/dist/v12.18.4/node-v12.18.4-linux-x64.tar.xz # 下载
tar xf node-v12.18.4-linux-x64.tar.xz # 解压
cd node-v12.18.4-linux-x64/ # 进入解压目录
./bin/node -v # 执行node命令 查看版本
v12.18.4
解压文件的 bin 目录底下包含了 node、npm 等命令,我们可以使用 ln 命令来设置软连接:
ln -s /usr/software/nodejs/bin/npm /usr/local/bin/
ln -s /usr/software/nodejs/bin/node /usr/local/bin/
(2)Ubuntu 源码安装 Node.js
以下部分将介绍在 Ubuntu Linux 下使用源码安装 Node.js;其他的 Linux 系统,如 Centos 等类似如下安装步骤。
在 Github 上获取 Node.js 源码:
sudo git clone https://github.com/nodejs/node.git
Cloning into 'node'...
修改目录权限:
sudo chmod -R 755 node
使用 ./configure 创建编译文件,并编译安装:
cd node
sudo ./configure
sudo make
sudo make install
查看 node 版本:
node --version
v12.18.4
(3)Ubuntu apt-get命令安装
命令格式如下:
sudo apt-get install nodejs
sudo apt-get install npm
(4)CentOS 下源码安装 Node.js
- 下载源码,我们需要在https://nodejs.org/en/download/下载最新的 Node.js 版本,这里以 v12.18.4 为例:
cd /usr/local/src/
wget http://nodejs.org/dist/v12.18.4/node-v12.18.4.tar.gz
- 解压源码:
tar zxvf node-v12.18.4.tar.gz
- 编译安装:
cd node-v12.18.4
./configure --prefix=/usr/local/node/12.18.4
make
make install
- 配置 NODE_HOME,进入 profile 编辑环境变量:
vim /etc/profile
- 设置 Node 环境变量,在 export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL 一行的上面添加如下内容:
#set for nodejs
export NODE_HOME=/usr/local/node/12.18.4
export PATH=$NODE_HOME/bin:$PATH
:wq 保存并退出,编译 /etc/profile 使配置生效:
source /etc/profile
验证是否安装配置成功:
node -v
输出 v12.18.4 表示配置成功。
npm 模块安装路径:
/usr/local/node/12.18.4/lib/node_modules/
注:Node.js 官网提供了编译好的 Linux 二进制包,也可以下载下来直接应用。
5.2 Mac OS 上安装
我们可以通过以下两种方式在 Mac OS 上来安装 node:
- 1、在官方下载网站下载 pkg 安装包,直接点击安装即可。
- 2、使用 brew 命令来安装:
brew install node
5.3 Windows 上安装
同样有两种方式,因为相当简单就不介绍了:
- Windows 安装包(.msi)
- Windows 二进制文件(.exe)安装
6 示例程序
如果我们使用 PHP 来编写后端的代码时,需要 Apache 或者 Nginx 的 HTTP 服务器,并配上 mod_php5 模块和 php-cgi。
从这个角度看,整个“接收 HTTP 请求并提供 Web 页面”的需求就不需要 PHP 来处理。
不过对 Node.js 来说,概念完全不一样了;使用 Node.js 时,我们不仅仅 在实现一个应用,同时还实现了整个 HTTP 服务器,事实上,我们的 Web 应用以及对应的 Web 服务器基本上是一样的。
在我们创建 Node.js 第一个 "Hello, World!" 应用前,让我们先了解下 Node.js 应用是由哪几部分组成的:
- 引入 required 模块:我们可以使用 require 指令来载入 Node.js 模块。
- 创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
- 接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。
6.1 引入 required 模块
我们使用 require 指令来载入 http 模块,并将实例化的 HTTP 赋值给变量 http,实例如下:
const http = require("http");
6.2 创建服务器
接下来我们使用 http.createServer() 方法创建服务器,并使用 listen 方法绑定 8888 端口(当然可以是别的端口), 函数通过 request, response 参数来接收和响应数据。
实例如下,在项目的根目录下创建一个叫 server.js 的文件,并写入以下代码:
const http = require('http');
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello Worldn');
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
以上代码我们完成了一个可以工作的 HTTP 服务器。
6.3 运行
接下来,打开浏览器访问 http://127.0.0.1:8888/,就会看到一个写着“Hello World”的网页:
上述代码当中:
- 第一行请求(require)Node.js 自带的 http 模块,并且把它赋值给 http 常量(防止意外修改)。
- 接下来我们调用 http 模块提供的函数: createServer ;这个函数会返回 一个对象,这个对象有一个叫做 listen 的方法,这个方法有一个数值参数, 指定这个 HTTP 服务器监听的端口号。
- 当服务器启动后,response.end 的参数就会作为网页内容显示在页面上。