文章目录
一、初识 Node.js
(一)JS 解析引擎
- 定义:
解析
并执行
JS 代码,给出运行结果
浏览器 | Chrome | Firefox | Safri | JSCore |
---|---|---|---|---|
JS 解析引擎 | IE | V8 | OdinMonkey | Chakra |
(二)JS 运行环境
- 定义:代码正常运行所需的必要环境
- 浏览器:V8引擎 + 内置 API(BOM、DOM、Canvas、ajax、JS内置对象) + 第三方库(jQuery、art-template)
- Node.js:V8引擎 + 内置 API(fs、path、http、JS内置对象、querystring) + 第三方库(express + mysql)
(三)Node.js
1、作用
框架 | Express | Electron | restify |
---|---|---|---|
功能 | 构建 Web 应用 | 构建跨平台桌面应用 | 构建 API 接口项目 |
2、命令
- 打开终端
win + e
- 切换目录
cd 目标目录
- 查看版本号
node -v
- 执行 JS 代码
node js文件路径
- 打开目标目录终端
shift + 文件位置鼠标右键 + powershell
- 快速定位上一次执行命令
↑ 键
- 快速补全路径
tab 键
- 快速清空当前输入命令
esc 键
- 清空终端
cls 键
二、fs 文件系统模块
(一)fs 模块
- 定义:Node.js 官方提供、用来
操作文件
的模块 - 导入:
const fs = require('fs')
(二)方法
1、fs.readFile()
- 用法:
读取
指定文件内容 - 语法:fs.readFile(path[, options], callback(err, dataStr))
path:文件路径的字符串
options:读取文件的编码格式,默认 utf8
callback: 文件读取完成后,通过回调函数拿到读取结果
- 注意
- 只能用来创建文件,不支持创建路径
- 重复调用写入同一个文件,新内容覆盖旧内容
2、fs.writeFile()
- 用法:向指定文件
写入
内容 - 语法:fs.writeFile(path, data[, options], callback(err, dataStr))
data:要写入的内容
3、路径动态拼接
- 原因:提供 ./ 或 …/ 开头的
相对路径
时,执行 node 命令所处目录,出现路径动态拼接错误
三、path 路径模块
(一)path 模块
- 用法:Node.js 官方提供、用来
处理路径
的模块 - 导入:
const path = require('path')
(二)方法
1、path.join()
- 用法:路径片段拼接完整路径
- 语法:path.join([paths…])
- path.join(‘/a’,‘/b/c’,‘
../
’,‘./d’,‘e’) // \a\b\d\e - path.join(__dirname, ‘/文件名’) // 当前文件所处目录\文件名
- path.join(‘/a’,‘/b/c’,‘
2、path.basename()
- 用法:从路径字符串末尾解析文件名
- 语法:path.basename(path[, ext])
- path.basename(‘/a/b/c/index.html’) // index.html
- path.basename(‘/a/b/c/index.html’, ‘.html’) // index
path:完整路径字符串
ext:文件扩展名
3、path.basename()
- 用法:获取路径扩展名
- 语法:path.extname(path)
- path.extname(‘/a/b/c/index.html’) // .html
四、http 模块
(一)http 模块
- 用法:Node.js 官方提供、用来
创建 web 服务器
的模块 - 导入:
const http = require('http')
(二)web 服务
- 后端:服务器安装了
web 服务器软件
,使之异于普通电脑。如 IIS、Apache 等第三方 web 服务器软件 - 前端:基于 Node.js 提供的 http 模块,
通过代码手写服务器软件
,从而对外提供 web 服务
(三)服务器相关概念
- IP 地址:互联网上
每台计算机的唯一地址
,通常以点分十进制
表示成a.b.c.d的形式,均为0-255间十进制整数 - 域名:为了避免 IP 地址不直观且不便于记忆的问题,使用
字符型地址
方案 - 域名服务器:DNS,IP 地址和域名的一一对应关系存放在域名服务器,提供
IP 地址和域名之间的转换
服务 - 端口号:一台电脑中运行众多的 web 服务,每个 web 服务都对应一个唯一的端口号。通过端口号,可以准确处理客户端发送过来的网络请求,提交给
对应 web 服务
进行处理- 每个端口号不能同时被多个 web 服务占用
- 实际应用中,URL 的
80端口可以被省略
(四)创建 web 服务器
1、创建基本 web 服务器
- 导入 http 模块
- 创建 web 服务器实例
- 为服务器实例绑定 request 事件,监听客户端请求
- 启动服务器
(1)req
- req:
请求对象
,包含与客户端相关的数据和属性- req.url:请求地址(端口号以后)
- req.method:请求方式
(2)res
- res:
响应对象
,包含与服务器相关的数据和属性- 解决中文乱码:手动设置内容编码格式,res.setHeader(‘Content-Type’, ‘text/html;charset=utf-8’)
- res.end():向客户端发送指定内容,并结束请求的处理过程
// 1、导入 http 模块
const http = require('http')
// 2、创建 web 服务器实例
const server = http.createServer()
// 3、调用 server.on() 方法,为服务器绑定 request 事件
server.on('request', (req, res) => {
const str = `你请求的地址为${req.url},请求的 method 为${req.method}`
// 3.1、解决中文乱码
res.setHeader('Content-Type','text/html;charset=utf-8')
// 3.2、向客户端发送指定内容,并结束请求
res.end(str)
})
// 4、调用 server.listen(端口号,回调) 方法,启动 web 服务器
server.listen(80, () => {
console.log('http running at http://127.0.0.1');
})
2、根据不同 url 响应不同 html
- 获取
请求的 url 地址
- 设置
默认响应内容
为 404 Not found - 判断用户
请求的页面类型
- 设置
Content-Type 响应头
,防止中文乱码 - 使用
res.end()
把内容响应给客户端
server.on('request',(req, res) => {
// 1、获取请求的 url 地址
const url = req.url
// 2、设置默认响应内容为 404 Not Found
let content = `<h1>404 Not Found</h1>`
// 3、判断用户请求页面类型
if(url === '/' || url === '/index.html'){
content = `<h1>首页</h1>`
}else if(url === '/about.html'){
content = `<h1>关于页面</h1>`
}
// 4、设置 Content-Type 响应头,防止中文乱码
res.setHeader('Content-Type', 'text/html; charset=utf-8')
// 5、内容响应给客户端
res.end(content)
})
3、实现 web 服务器
(1)核心思路
- 把文件的
实际存放路径
,作为每个资源的请求 url 地址
(2)实现步骤
- 导入需要模块
- 创建基本的 web 服务器
- 将资源的请求 url 地址映射为文件的存放路径
- 读取文件内容并响应给客户端
- 优化资源请求路径
// 1、导入模块,处理服务器、文件、路径问题
const http = require('http')
const fs = require('fs')
const path = require('path')
// 2、创建web服务器
const server = http.createServer()
// 3、添加web服务器的request事件
server.on('request', (req, res) => {
const url = req.url
// 3.1、路径直接拼接
// const fpath = path.join(__dirname, url)
// 3.2、优化资源请求路径
let fpath = ''
if(url === '/'){
fpath = path.join(__dirname, '/clock/index.html')
}else{
fpath = path.join(__dirname, '/clock', url)
}
// 4、根据映射来的文件路径读取文件
fs.readFile(fpath, 'utf-8', (err, dataStr) => {
if(err) return res.end('404 Not Found')
// 成功读取的内容响应给客户端
res.end(dataStr)
})
})
// 5、启动服务器
server.listen(80, ()=>{
console.log('server running at http://127.0.0.1');
})
五、Node 模块化
(一)模块化基本概念
- 模块化:遵守固定规则,将大文件拆成独立且相互依赖的多个小模块
- 优点
- 提高代码复用性
- 提升代码可维护性
- 实现按需加载
(二)Node.js 模块分类
1、三类模块
- 内置模块:Node.js
官方提供
的,如 fs、path、http - 自定义模块:
用户创建
的每个 .js 文件 - 第三方模块:
第三方开发
模块,下载后使用
2、加载模块
- 语法:require(‘名字/路径’)
- 区别:加载内置和第三方模块填写名字,加载自定义模块填写相对路径
- 注意:加载模块,会执行被加载模块中的代码
3、模块作用域
- 定义:类似函数作用域,自定义模块中的变量、方法等
只能在当前模块被访问
- 优点:防止全局变量污染
4、向外共享模块作用域中的成员
(1)module 对象
- 每个 .js 自定义模块中都有一个 module 对象,储存当前模块相关信息
Module {
id: '.',
path: 'C:\\Users\\Administrator\\Desktop\\files',
exports: {},
filename: 'C:\\Users\\Administrator\\Desktop\\files\\module.js',
loaded: false,
children: [],
paths: [
'C:\\Users\\Administrator\\Desktop\\files\\node_modules',
'C:\\Users\\Administrator\\Desktop\\node_modules',
'C:\\Users\\Administrator\\node_modules',
'C:\\Users\\node_modules',
'C:\\node_modules'
]
}
(2)module.exports 对象
- module.exports:用于自定义模块中对外共享模块内成员,外界用 require() 导入自定义模块时,得到的就是
module.exports 指定对象
- exports:简化版代码,
默认情况下 module.exports 和 exports 指向同一个对象
,最终共享结果以 module.exports 指向的对象为准 - 同一模块中,避免同时使用 module.exports 和 exports
5、模块化规范
- Node.js 遵循 CommonJS 模块化规范——模块特性和各模块之间如何相互依赖
- 每个模块内部,module 变量代表当前模块
- module 变量是一个对象,其 exports 属性是对外接口
- require() 方法用于加载模块,即加载该模块的 module.exports 属性
(三)npm 与包
1、包
- 定义:Node.js 中的
第三方模块
又称包 - 来源:第三方开发,免费且开源
- npm:全球最大包共享平台,点此下载
- 步骤
- 使用 npm 包管理工具,在项目安装对应包
- 使用 require() 导入包
- 参考官方 API 文档使用
npm install 包名 // 完整版
npm i 包名 // 简写版
npm i 包名@版本(点分十进制:大版本.功能大版本.Bug修复版本) // 指定版
npm i 包名 --save-dev // 仅项目开发阶段使用的包复杂版
npm i 包名 -D // 仅项目开发阶段使用的包简写版
2、包管理配置文件
(1)多人协作问题
- 第三方包体积过大,不方便团队成员共享项目源代码,需要在共享时剔除 node_modules
(2)包管理配置文件
项目根目录
中必有package.json
包管理配置文件,记录与项目有关的配置信息,方便剔除 node_modules 目录后,在团队成员共享项目源代码- 项目名称、版本号、描述
- 项目中使用的包
- 开发期间使用的包
- 开发和部署期间使用的包
① 快速创建 package.json
- 在执行命令时所处目录中,使用快捷命令
npm init -y
快速创建 package.json 包管理配置文件- 仅支持
英文目录
下运行,不支持空格 - 运行 npm install 后,npm 包管理工具自动把包的
名称
和版本号
记录到 package.json
- 仅支持
② 一次性安装所有包
- 拿到剔除 node_modules 的项目后,需要先把所有包下载到项目中才能正常运行
- 运行
npm install/i
命令,直接读取 package.json 中的 dependencies 节点,一次性下载
③ 卸载包
npm uninstall 包名
,自动将卸载的包从 package.json 中的 dependencies 节点移除
④ devDependencies
仅项目开发阶段使用
的包需要npm i 包名 -D
将包安装并记录到 devDependencies 节点开发和项目上线都使用
的包npm i 包名
将包安装并记录到 dependencies 节点
3、下包速度慢
- 原因:npm 下包默认使用国外服务器,网络数据传输经过漫长海底电缆
- 镜像:淘宝在国内搭建一个专门同步国外官方包的服务器,极大提高下包速度
// 查看当前下包镜像源
npm config get registry
// 将下包镜像源切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/
// 检查镜像源是否下载成功
npm config get registry
- nrm:快速查看和切换下包镜像源
// 安装 nrm 为全局工具
npm i nrm -g
// 查看所有镜像源
nrm ls
// 将下包镜像源切换为 taobao 镜像
nrm use taobao
4、包的分类
- 全局包:
npm i -g
,工具性质,参考官方说明文档使用 - 项目包:安装到项目 node_modules 目录的包
- 开发依赖包:记录到 DevDependencies 节点中的包,
仅开发期间使用
- 核心依赖包:记录到 dependencies 节点中的包,
开发和上线期间使用
- 开发依赖包:记录到 DevDependencies 节点中的包,
- i5thing_toc:将 md 文档转为 html 页面的工具
// 安装全局包
npm i -g i5ting_toc
// 调用包
i5ting_toc -f md文件路径 -o
5、创建并发布包
(1) 新建文件夹作为包的根目录
(2) 基础文件
- package.json:包管理配置文件
{
"name":"包名",
"version":"1.0.0", //版本号
"main":"index.js", // 入口文件
"description":"包简介",
"keywords":['关键词1', '关键词2', '关键词3',],
"license":"ISC" // 开源许可协议
}
- src:包功能文件
module.exports = {功能函数名} // 暴露给入口文件
- index.js:包入口文件
const exp = require('功能文件路径') //接收功能文件
module.export = {...exp} // 暴露给外部
- README.md:包使用说明
(3)发布
- 将终端切换到包的根目录,运行
npm publish
命令
(4)删除
- 运行
npm unpublish 包名 --force
命令- 仅支持删除72小时内发布的包
- 删除的包24小时内不允许重复发布
(四)模块加载机制
1、优先从缓存中加载
- 模块在第一次加载后会被缓存,多次调用 require() 不会导致模块代码重复执行,提升模块加载效率
2、模块加载机制
(1)内置模块加载优先级最高
- Node.js 官方发布模块同名优先加载
(2)自定义模块加载
- 必须指定以 ./ 或 …/ 开头的
路径标识符
,否则 node 会将其当做内置模块
或第三方模块
加载 - 导入自定义模块时如果忽略文件扩展名,node 会按序分别尝试加载以下文件
确切文件名
- 补全
.js
扩展名 - 补全
.json
扩展名 - 补全
.node
扩展名 - 加载失败,终端报错
(3)第三方模块加载
- 非内置模块、无路径开头时,Node.js 从当前模块的父目录开始,尝试从 node_modules 文件夹加载第三方模块
- 如果没有找到对应第三方模块,移动到上一层父目录加载,直至文件系统根目录
(4)目录作为模块
- 在被加载目录下查找 package.json 文件,寻找 main 属性作为 require() 加载入口
- 如果 package.json 文件不存在或 main 入口不存在/无法解析, node.js 加载目录下的 index.js
- 如果上述两步均失败,则 Node.js 在终端打印错误提示:Error:Cannot find module ‘xxx’