Node.js学习分享(上)
Node.js
- fs文件系统模块
- fs.readFile()
- fs.writeFile()
- path路径模块
- 路径拼接
- path.join()
- 获取路径中的文件名
- path.basename()的语法格式
- 获取路径中的文件扩展名
- path.extname()的语法格式
- http模块
- 服务器相关概念
- IP地址
- 域名和域名服务器
- 端口号
- 创建最基本的web服务器
- 创建web服务器的基本步骤
- request请求对象
- 解决中文乱码问题
- 根据不同的URL响应不同的html内容
- 模块化
- Node.js中的模块化
- 加载模块
- 向外共享模块作用域的成员
- module对象
- module.exports对象
- exports对象
- npm与包
- 初次装包后多了哪些文件?
- 包的语义化版本规范
- 包管理配置文件
- 如何记录项目中安装了哪些包?
- 快速创建package.json
- 一次性安装所有的包
- 卸载包
- 初始化自己的包
- 发布包
- 模块的加载机制
- 优先从缓存中加载模块
- 内置模块的加载机制
- 第三方模块的加载机制
fs文件系统模块
- fs模块是Node.js官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作要求
- fs.readFile()方法,用来读取指定文件中的内容
- fs.writeFile()方法,用来向指定的文件中写入内容
- 使用fs模块前需要导入fs模块
const fs = require('fs')
fs.readFile()
- 语法格式:
fs.readFile(path[,options], callback) - 参数说明:
- path:必选参数,字符串,表示文件的路径
- options:可选参数,表示以什么编码格式来读取文件
- callback:必选参数,文件读取完成后,通过回调函数拿到读取的结果
如果读取失败:
err的值为错误对象
data的值为undefined
fs.writeFile()
- 语法格式:
fs.writeFile(path, data[,options], callback) - 参数说明:
- path:必选参数,字符串,表示文件的路径
- data:必选参数,表示要写入的内容
- options:可选参数,表示以什么编码格式来写入文件,默认是utf8
- callback:必选参数,文件写入完成后的回调函数
- 需要注意的点:
- 该方法只能用来创建文件不能用来创建文件夹(路径)
- 重复调用该函数,新写入的内容会覆盖掉原来的内容
路径动态拼接问题
- 在使用fs模块操作文件时,如果提供的操作路径是以./或者…/开头的相对路径时,很容易出现路径动态拼接错误的问题
- 原因:代码在运行的时候,会以执行node命令时所处的目录,动态拼接出被操作文件的完整路径
- 解决方案:
- 使用绝对路径代替相对路径(移植性差)
- __dirname:表示当前文件所处的目录(推荐)
path路径模块
- 用来处理路径的模块
- 同样,使用前需要导入
const path = require('path')
路径拼接
path.join()
- 使用path.join()方法,可以把多个路径片段拼接为完整的路径字符串
- 语法格式:
path.join([…paths]) - 参数解读:
- …paths:路径片段的序列
- 返回值:
const path = require('path')
// ../会抵消前面的路径
const pathStr = path.join('/a','/b/c','../','./d','e')
console.log(pathStr);
// /a/b/d/e
获取路径中的文件名
path.basename()的语法格式
- 使用path.basename()方法,可以获取路径中的最后一部分,经常通过泽哥方法来获取路径中的文件名
- 语法格式:
path.basename(path[,ext]) - 参数解读:
- Path :必选参数,表示一个路径的字符串
- Ext :可选参数,表示文件扩展名
- 返回::表示路径中的最后一部分
- 应用实例:
const path = require('path')
const fpath = '/a/b/c/index.html'
const fullName = path.basename(fpath)
console.log(fullName); //index.html
const nameWithoutExt = path.basename(fpath,'.html')
console.log(nameWithoutExt); //index
获取路径中的文件扩展名
path.extname()的语法格式
- 使用path.extname()方法,可以获得路径中的扩展名部分
- 语法格式:
path.extname(path) - 参数解读:
- Path :必选参数,表示一个路径的字符串
- 返回 :返回得到的扩展名字符串
const path = require('path')
const fpath = '/a/b/c/index.html'
//获取文件扩展名
const extname = path.extname(fpath)
console.log(extname); //.html
http模块
- 使用前同样需要导入
const http = require('http')
服务器相关概念
IP地址
- IP地址就是互联网上每台计算机的唯一地址,因此IP地址具有唯一性,只有在知道对方IP地址的前提下,才能与对应的电脑之间进行数据通信
域名和域名服务器
- IP地址和域名是一一对应的关系,这份对应关系存放在一种叫做域名服务器(DNS)的电脑中,使用者只需通过好记的域名访问对应的服务器即可,对应的转换工作由域名服务器实现。因此,域名服务器就是提供IP地址和域名之间的转换服务的服务器
端口号
- 在一台电脑中,可以运行成百上千个web服务,每个web服务都对应着一个唯一的端口号。客户端发送过来的网络请求,通过端口号,可以被准确的交给对应的web服务进行处理
注意:
- 每个端口号不能同时被多个web服务占用
- 在实际应用中,URL中的80端口可以省略
创建最基本的web服务器
创建web服务器的基本步骤
- 导入http模块
- 创建web服务器实例
const server = http.createServer() - 为服务器实例绑定request事件,监听客户端的请求
//绑定request事件
server.on('request',(request,response)=>{
console.log('someone visit our web server');
})
- 启动服务器
//启动服务器
server.listen('8080',()=>{
console.log('server running at http://127.0.0.1:8080');
})
request请求对象
- request是请求对象,它包含了与客户端相关的数据和属性
- request.url:是客户端请求的URL地址
- request.method:是客户端的method的请求类型
response响应对象 - res.end()方法:向客户端发送指定的内容,并结束这次请求的处理过程
const http = require('http')
const server = http.createServer()
server.on('request',(req,res)=>{
const url = req.url;
const method = req.method
const str = `your request url = ${url},and your request method = ${method}`
console.log(str);
res.end(str)
})
server.listen('8080',()=>{
console.log('http server running at http://127.0.0.1:8080');
})
解决中文乱码问题
- 当调用res.end()方法向客户端发送中文内容的时候,会出现乱码问题,此时,需要手动设置内容的编码格式
const http = require('http')
const server = http.createServer()
server.on('request',(req,res)=>{
const str2 = '让我们红尘作伴'
//设置Content-Type响应头,来解决中文乱码问题
res.setHeader('Content-Type','text/html; charset=utf-8')
console.log(str2);
res.end(str2)
})
server.listen('8080',()=>{
console.log('http server running at http://127.0.0.1:8080');
})
根据不同的URL响应不同的html内容
核心实现步骤:
- 获取请求的URL地址
- 设置默认的响应内容为 404 Not Found
- 判断用户的请求是否为/或者index.html首页
- 判断用户请求的是否为/about.html关于页面
- 设置Content-Type 响应头,防止中文乱码
- 使用res.end()将内容响应到客户端
const http = require('http')
const server = http.createServer()
server.on('request',(req,res)=>{
const url = req.url
let content = '<h1>404 Not Found</h1>'
if(url==='/' || url ==='/index.html'){
content = '<h1>首页</h1>'
}else if(url==='/about.html'){
content = '<h1>关于页面</h1>'
}
res.setHeader('Content-Type','text/html; charset=utf-8')
res.end(content)
})
server.listen('80',()=>{
console.log('http server running at http://127.0.0.1');
})
模块化
Node.js中的模块化
加载模块
- 使用强大的require()方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用
注意:使用require()方法加载模块时,会执行被加载模块中的代码
向外共享模块作用域的成员
module对象
- 在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息。
{
id: '.',
path: '/Users/miraculous/Desktop/前端/Node.js',
exports: {},
filename: '/Users/miraculous/Desktop/前端/Node.js/13-module对象.js',
loaded: false,
children: [],
paths: [
'/Users/miraculous/Desktop/前端/Node.js/node_modules',
'/Users/miraculous/Desktop/前端/node_modules',
'/Users/miraculous/Desktop/node_modules',
'/Users/miraculous/node_modules',
'/Users/node_modules',
'/node_modules'
],
[Symbol(kIsMainSymbol)]: true,
[Symbol(kIsCachedByESMLoader)]: false,
[Symbol(kIsExecuting)]: true
}
//以上为打印的module信息
module.exports对象
- 在自定义模块中,可以使用module.exports对象,将模块内的成员共享出去,供外界使用
- 外界用require()方法导入的自定义模块,得到的就是module.exports所指向的对象
const username = 'zhengbo'
const add = (x,y)=>{
return x + y
}
module.exports = {
username,
add
}
//以上为下面的导入模块
const obj = require('./14-module.exports向外共享对象')
console.log(obj);
注意:使用require()方法导入模块时,导入的结果,永远以module.exports指向的对象为准
exports对象
- 为了简化向外共享成员的代码,Node提供了exports对象,默认情况下,exports和module.exports指向同一个对象。最终共享的结果。还是以module.exports指向的对象为准
对比module.exports和exports - 直接对exports赋值不会改变module.exports的值,而module.exports的值才是通过require获取的内容
- module.exports:用于直接导出模块的默认值,可以是任何类型
- exports:用于导出模块的属性或方法,只能用于对象的属性赋值,不能直接赋值
注意:尽量不要在同一个模块中同时使用module.exports和exports,避免混淆
Node.js中的模块化规范
- Node.js遵循了CommonJS的规范,CommonJS规定了模块的特性和各模块之间如何相互依赖
CommonJS规定:
- 每个模块内部,module变量代表当前模块
- module变量是一个对象,它的exports属性(module.exports)是对外的接口
- 加载某个模块,其实是加载该模块的module.exports属性,require()方法用于加载模块
npm与包
- Node.js中的第三方模块又叫做包
初次装包后多了哪些文件?
- node_modules:用来存放所有已安装到项目的包。require()导入第三方包,就是从这个目录中查找并加载包
- package-lock.json:用来记录node_modules目录下的每一个包的下载信息,例如:包的名字、版本号、下载地址等
注意:不要手动修改上面两个文件中的任何代码
包的语义化版本规范
- 包的版本号是以“点分十进制”形式进行定义的,总共有三位数字,例如:2.24.0
- 第一位数字:大版本
- 第二位数字:功能版本
- 第三位数字:BUG修复版本
- 版本号提升规则:只要前面的版本号增长了,则后面的版本号归零
包管理配置文件
如何记录项目中安装了哪些包?
- 在项目根目录中,创建一个叫做package.json的配置文件,即可用来记录项目中安装了哪些包。从而方便剔除node_modules目录之后,在团队成员之间共享项目的源代码
注意:一定要把node_moduled文件夹添加到.gitignore忽略文件中
快速创建package.json
- 在执行命令所处的目录中,快速新建package.json文件
npm init -y
注意:上面的命令只能在英文的目录下成功运行,不能出现中文或者空格
一次性安装所有的包
- 应用场景:当我们拿到了一个剔除了node_modules文件的项目之后,需要先把所有的包下载到项目中,这样项目才可以运行起来
- 运行
npm install
或者npm i
一次性安装所有的依赖包 - 工作原理:执行上述命令时,npm包管理工具会先读取package.json中的dependencies节点,然后将它们一次性下载到项目中
卸载包
- 使用
npm uninstall
命令,来卸载指定的包
-npm uninstall + 指定包名
注意:上述命令执行成功后,会把卸载的包从dependicies中自动移除
Devdependencies - 如果某些包只在项目开发阶段会用到,在项目上线后并不会用到,建议将这些包devdependicies中
npm install + 包名 -D
初始化自己的包
- 创建一个文件夹
- 并在该文件夹中创建package.json、index.js、README.md
//package.json中的配置
{
"name": "itheima-study-nodejs", //包的名字
"version": "1.0.0",
"main": "index.js", //包的入口文件
"description": "提供了格式化时间、HTMLEscape相关功能", //对包的描述
"keywords": ["itheima","study"], //搜索包时的关键字
"license":"ISC"
}
发布包
- 在npmjs官网注册账号
- 在终端登录账号
注意:在运行npm login命令之前,必须先把下包的服务器地址切换为npm的官方服务器,否则会导致npm发包失败 - 将终端切换到包的根目录后,运行npm publish命令,即可将包发布到npm上(包名不能雷同)
删除已发布的包
- 运行
npm unpublish 包名 --force
命令,即可从npm删除已发布的包 - 注意:
- 该命令只能删除72小时之内发布的包
- 该命令删除的包,在24小时之内不允许重复发布
模块的加载机制
优先从缓存中加载模块
- 模块在第一次加载后会被缓存,这也意味着多次调用require()方法不会导致模块中的代码重复执行
内置模块的加载机制
- 内置模块的加载优先级最高!
自定义模块的加载机制 - 在导入自定义模块时,如果省略了文件的扩展名,则Node.js会按下面的顺序分别尝试加载文件
- 按照确切的文件名进行加载
- 补全.js扩展名进行加载
- 补全.json扩展名进行加载
- 补全.node扩展名进行加载
- 加载失败,终端报错
第三方模块的加载机制
- 现在
node_modules
中进行查找,如果没有则会往上一级目录去找,直到根目录为止