Node.js

Node.js简介

Node.js是一个javascript运行环境。它让javascript可以开发后端程序,实现几乎其他后端语言实现的所有功能,可以与PHP、Java、Python、.NET、Ruby等后端语言平起平坐。

Nodejs基于V8引擎,V8是Google发布的开源JavaScript引擎,本身就是用于Chrome浏览器的js解释部分。

  • 浏览器环境vs node环境

Node.js 可以解析JS代码(没有浏览器安全级别的限制)提供很多系统级别的API,如:

  • 文件的读写 (File System)

    const fs = require('fs')
    
    fs.readFile('./ajax.png', 'utf-8', (err, content) => {
      console.log(content)
    })
    
  • 进程的管理 (Process)

    function main(argv) {
      console.log(argv)
    }
    
    main(process.argv.slice(2))
    
    
  • 网络通信 (HTTP/HTTPS)

    const http = require("http")
    
    http.createServer((req,res) => {
      res.writeHead(200, {
        "content-type": "text/plain"
      })
      res.write("hello nodejs")
      res.end()
    }).listen(3000)
    
    

CommonJs规范

Commonjs

  • 在 commonjs 中每一个 js 文件都是一个单独的模块,我们可以称之为 module;
  • 该模块中,包含 CommonJS 规范的核心变量: exports、module.exports、require;
  • exports 和 module.exports 可以负责对模块中的内容进行导出;
  • require 函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容;

示例代码:
router.js 为要导出的模块,server.js 为要引用 router.js 的模块
router.js

// 可以直接给exports对象赋值导出
exports={
    forward: function(){...},
    back:  function(){...}
}
// 或者可以直接给exports添加属性
exports.forward=function(){...};
exports.back=function(){...};

server.js

// 使用require函数导入
const router = require("./router.js");
router.forward();
// 也可使用解构赋值,只导入这个模块的某一个方法来使用
const { forward } = require("./router.js");
forward();

关于模块化更多内容可查看 https://ridoblog.cn/archives/qian-duan-mo-kuai-hua

包管理器

01 npm的使用

npm init
npm install 包名 –g  (uninstall,update)
npm install 包名 --save-dev (uninstall,update)
npm list -g (不加-g,列举当前目录下的安装包)
npm info 包名(详细信息) npm info 包名 version(获取最新版本)
npm install md5@1(安装指定版本)
npm outdated(  检查包是否已经过时)


	"dependencies": {    "md5": "^2.1.0"  }  
  ^ 表示 如果 直接npm install 将会 安md5 2.*.*  	最新版本

	"dependencies": {    "md5": "~2.1.0"  }  
  ~ 表示 如果 直接npm install 将会 安装md5 2.1.*  最新版本

	"dependencies": {    "md5": "*"  }  
  * 表示 如果 直接npm install 将会 安装 md5  最新版本

02 全局安装 nrm

NRM (npm registry manager)是npm的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速地在 npm 源间切换。

手动切换方法: npm config set registry https://registry.npm.taobao.org

安装 nrm

在命令行执行命令,npm install -g nrm,全局安装nrm。

使用 nrm

执行命令 nrm ls 查看可选的源。 其中,带*的是当前使用的源,上面的输出表明当前源是官方源。

切换 nrm

如果要切换到taobao源,执行命令nrm use taobao。

测试速度

你还可以通过 nrm test 测试相应源的响应时间。

nrm test

03 yarn使用

npm install -g yarn

对比npm:
速度超快: yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。
超级安全: 在执行代码之前,yarn 会通过算法校验每个安装包的完整性。

// 开始新项目
	yarn init 
// 添加依赖包
	yarn add [package] 
	yarn add [package]@[version] 
	yarn add [package] --dev 
// 升级依赖包
	 yarn upgrade [package]@[version] 
// 移除依赖包
	 yarn remove [package]
// 安装项目的全部依赖
	 yarn install 

04 cnpm

cnpm是一个完整 npmjs.org 镜像,你可以用此代替官方版本,同步频率目前为 10分钟 一次,以保证尽量与官方服务同步。

  • 安装
npm install -g cnpm --registry=https://registry.npmmirror.com
  • 使用
cnpm install [name]

Node.js 内置模块

fs 文件系统模块

fs 模块是 Node.js 官方提供的,用来操作文件的模块,他提供了一系列方法和属性,满足用户对文件的操作需求。
例如:

  • fs.readFile()方法,用来读取指定文件中的内容
  • fs.writeFile()方法,用来向指定的文件中写入内容

使用前先引入

const fs = require("fs");

fs.readFile()

  1. fs.readFile()的语法格式
    使用 fs.readFile()方法,可以读取指定文件中的内容
fs.readFile(path, [options], callback); //[]表示参数为可选参数

path: 字符串,表示文件路径
options: 表示以什么编码格式来读取文件,例如 utf-8
callback: 文件读取完成后,通过回调函数来拿到读取的结果

  1. 实例代码:
    index.js
const fs = require("fs");

fs.readFile("demo.txt", "utf-8", (err, result) => {
  //  如果文件读取成功,err的值为null
  //  如果读取失败,err的值为一个错误对象
  if (err) {
    console.log("文件读取失败,错误信息:" + err.message);
  } else {
    console.log("文件读取成功,文件内容为:" + result);
  }
});

fs.writeFile()

  1. fs.writeFile()语法格式
fs.writeFile(path, data, [options], callback);

path:文件路径
data:要写入的内容
options: 写入文件的格式,默认 utf-8
callback: 文件写入完成后的回调函数

  1. 实例代码
const fs = require("fs");

fs.writeFile("demo.txt", "hello world", (err) => {
  if (err) {
    console.log("文件写入失败,错误信息:" + err.message);
  }
  console.log("文件写入成功");
});

fs.writeFile()会覆盖掉文件原有的内容,如果文件不存在,则会先创建文件,再写入内容。

fs.appendFile()

使用fs.writeFile()会覆盖掉原有的内容,如果想要追加内容,可以使用fs.appendFile()
语法格式与fs.writeFile()相同
示例代码:

fs.appendFile("demo.txt", "hello world", "utf-8", (err) => {
  if (err) {
    console.log(err.message);
  }
  console.log("success");
});

路径动态拼接问题

在使用 fs 模块操作文件时,如果提供的路径是以./或者…/开头的相对路径时,很容易出现路径动态拼接错误的问题。
原因: 代码在运行时,会执行 node 命令所处的目录,动态拼接出被操作文件的完整路径。
解决方案:在使用 fs 模块操作文件时,直接提供完整的路径(dirname 表示当前文件所处的目录),不要提供./或者…/开头的相对路径。

示例代码:

const fs = require("fs");

fs.writeFile(__dirname + "demo.txt", "hello world", (err) => {
  if (err) {
    console.log("文件写入失败,错误信息:" + err.message);
  }
  console.log("文件写入成功");
});

path 路径模块

path 模块时 Node.js 官方提供的,用来处理路径的模块。他提供了一系列的方法和属性,用来满足用户对路径的需求。
例如:

  • path.join()方法,将多个路径片段拼接成一个完整的字符串
  • path.basename()方法,用来从路径字符串中,将文件名解析出来

引入:

const path = require("path");

path.join()

使用 path.join()方法,可以把多个路径片段拼接为完整的路径字符串
语法格式:

path.join([...paths]);
  • …paths 路径片段的序列
  • 返回拼接后的路径

示例代码:

const path = require("path");

const pathstr = path.join("/a", "/b", "/c", "../", "/d");
console.log(pathstr); //输出a/b/d

const pathstr2 = path.join(__dirname, "demo.txt");
console.log(pathstr2); //输出文件绝对路径

注意:路径拼接尽量用 path.join()方法进行处理,不要使用+进行字符串的拼接。

path.basename()

使用 path.basename()方法,可以获取路径中的最后一部分,经常通过这个方法来获取路径中的文件名。
语法格式:

path.basename(path, [ext]);
  • path: string 类型,表示一个路径的字符串
  • ext: string 类型,表示文件拓展名
  • 返回值为 string 类型,表示路径中的最后一部分

示例代码:

const path = require("path");

let pathName = "a/b/c/d/index.html";
let fullname = path.basename(pathName);
console.log(fullname); // 打印index.html

let nameWithoutExt = path.basename(pathName, ".html");
console.log(nameWithoutExt); //打印 index

path.extname()

使用 path.extname()方法,可以获取路径中的拓展名部分
语法格式:

path.extname(path);
  • path string 类型,表示一个路径的字符串
  • 返回一个 string 类型的拓展名字符串

示例代码:

const path = require("path");
let pathName = "a/b/c/d/index.html";
let ext = path.extname(pathName);
console.log(ext); // 打印.html

http模块

http模块是Node.js官方提供的,用来创建web服务器的模块,通过http模块提供的http.createServe()方法,就能方便的把一台普通的电脑,变成一台Web服务器。
导入:

const http =require('http') 

服务器相关概念

客户端与服务器

在网络节点中,负责消费资源的电脑,叫做客户端,负责对外提供网络资源的电脑,叫做服务器。

IP地址

IP地址就是互联网每台计算机的唯一地址,因此ip地址具有唯一性,如果把个人电脑比作一台电话,那么ip地址就相当于电话号码,只有在知道对方ip地址的前提下,才能与对应的电脑之间进行数据通信。
IP地址的格式: 通常用"点分十进制"表示成(a.b.c.d)的形式,其中,a,b,c,d 都是0-255之间的十进制整数。例如:(127.0.0.1)代表本机的ip地址

注意:互联网中每台服务器都有自己的ip地址,可以在命令行中通过 ping 加域名的方式查看ip地址
例如

ping www.baidu.com
域名和域名服务器(DNS)

尽管ip地址能够唯一的标记网络上的计算机,但是ip地址是一长串数字,不直观且不方便记忆,于是人们又发明了另外一套字符型的地址方案,即所谓的域名(Domain Name)地址。
ip地址和域名是一一对应的关系,这份对应关系存放在域名服务器中。使用者只需通过好记的域名访问对应的域名服务器即可,对应的转换工作由DNS实现。DNS就是提供ip地址和域名之间的转换服务的服务器。
注意:

  1. 单纯使用ip地址,互联网中的电脑也能够正常工作,但有了域名的加持,能够让互联网的世界变得更加方便。
  2. 127.0.0.1对应的域名为localhost,都代表自己的这台电脑,在使用上没有任何区别。
端口号

在一台电脑中,可以运行成百上千个web服务,每个web服务都对应一个唯一的端口号,客户端发送过来的网络请求,通过端口号,可以被准确的交给对应的web服务进行处理。
注意:

  1. 每个端口号不能同时被多个web服务占用。
  2. 在实际应用中,URL中的80端口可以被省略

创建最基本的web服务器

创建web服务器的基本步骤

  1. 导入http模块
  2. 创建web服务器实例
  3. 为服务器实例绑定request事件,监听客户端的请求
  4. 启动服务器

示例代码:

// 1. 导入http模块
const http=require('http')
// 2. 调用http.createServe()方法,创建一个web服务器实例
const server=http.createServer()
// 为服务器实例绑定request事件
server.on('request',(req,res)=>{
//只要有客户端来请求我们自己的服务器,就会触发request事件,调用这个回调函数
console.log("someone visit our web server");
res.end("hello world");
})
 // 调用server.listen()方法,启动当前的web服务器实例
server.listen(4000,()=>{
    console.log("http server running at localhost:4000");
})

req请求对象

只要服务器接受到了客户端的请求,就会通过调用server.on()为服务器绑定的request事件处理函数。
如果想在事件处理函数中,访问与客户端相关的数据或属性,可以使用如下的方式

server.on('request',(req,res)=>{
const str =`your request url is ${req.url},and request method is ${req.method}`
console.log(str);
})

res响应对象

在服务器的request事件处理函数中,如果想要访问与服务器相关的数据或属性,可以使用如下的方式:

server.on("request", (req, res) => {
  const str = `your request url is ${req.url},and request method is ${req.method}`;
  // res.end()方法的作用
  // 向客户端发送指定的内容,并结束这次请求的处理过程
  res.end(str);
});

解决中文乱码问题

当调用 res.end()方法,向客户端发送中文内容的时候,会出现乱码问题,此时,需要手动设置内容的编码格式:

server.on("request", (req, res) => {
  const str = `您请求的url地址是: ${req.url},请求的method类型是 ${req.method}`;
//   调用res.setHeader()方法,设置Content-Type响应头,解决中文乱码问题
  res.setHeader('Content-Type','text/html; charset=utf-8')
  res.end(str);
});

根据不同的url响应不同html内容

思路:

  1. 获取请求的url地址
  2. 设置默认的响应内容为 404 Not found
  3. 判断用户请求的是否为/首页
  4. 判断用户请求的是否为/about关于页面
  5. 设置Content-Type响应头,防止中文乱码
  6. 使用res.end()把内容响应给客户端
    代码实现
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
  let content = `<h1>404 Not found</h1>`;
  let { url } = req;
  if (url === "/") {
    content = `<h1>首页</h1>`;
  } else if (url === "/about") {
    content = `<h1>关于页</h1>`;
  }
  res.setHeader('Content-Type','text/html; charset=utf-8')
  res.end(content);
});
server.listen("8080", () => {
  console.log("server running at 8080");
});

Q.E.D.


永远自由,永远热爱