◆ 能够说出 pageage.json
文件中属性的含义
◆ 知道怎么解决包下载慢的问题
◆ 了解如何开发包
◆ 了解如何发布包
◆ 熟练模块的加载机制
◆ 熟练 express基本操作
npm
规定,在项目根目录中,必须提供一个叫做 package.json
的包管理配置文件,用来记录与项目有关的一些配置信息,例如:
package.json
配置文件的作用30.4M
28.8M
1.6M
在项目根目录中,创建一个叫做 **package.json
**的配置文件,即可用来记录项目中安装了哪些包。从而方便剔除 node_modules
目录之后,在团队成员之间共享项目的源代码
今后在项目开发中,一定要把 node_modules
文件夹,添加到 .gitignore
忽略文件中
package.json
npm
包管理工具提供了一个快捷命令,可以在执行命令时所处的目录中,快速创建 package.json
这个包管理配置文件
npm init
注意:
npm install
命令安装包的时候,npm
包管理工具会自动把包的名称和版本号,记录到 package.json
中package.json
文件中,有一个 dependencies
节点,专门用来记录您使用 npm install
命令安装了哪些包
// 安装一个包
npm i xxx
// 安装多个包
npm i xxx1 xxx2
npm install
命令(或 npm i
)一次性安装所有的依赖包可以运行 npm uninstall
命令,来卸载指定的包:
注意:npm uninstall
命令执行成功后,会把卸载的包,自动从 package.json
的 dependencies
中移除掉
devDependencies
节点的作用如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到 devDependencies
节点中
与之对应的,如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到 dependencies
节点中
您可以使用如下的命令,将包记录到 devDependencies
节点中
在使用 npm
下包的时候,默认从国外的 npm 服务器进行下载,此时,网络数据的传输需要经过漫长的海底光缆,因此下包速度会很慢
npm
镜像服务器的作用npm
的下包镜像源下包的镜像源,指的就是下包的服务器地址
nrm
切换下载包的服务器为了更方便的切换下包的镜像源,可以安装 nrm
这个小工具,利用 nrm
提供的终端命令,可以快速查看和切换下包的镜像源
那些被安装到项目的 node_modules
目录中的包,都是项目包
项目包又分为两类,分别是:
开发依赖包,被记录到 devDependencies
节点中的包,只在开发期间会用到
核心依赖包,被记录到 dependencies
节点中的包,在开发期间和项目上线之后都会用到
在执行 npm install
命令时,如果提供了 -g
参数,则会把包安装为全局包
全局包会被安装到 C:\Users\用户目录\AppData\Roaming\npm\node_modules
目录下
注意:
只有工具性质的包,才有全局安装的必要性。因为它们提供了好用的终端命令
判断某个包是否需要全局安装后才能使用,可以参考官方提供的使用说明即可
i5ting_toc
的安装和使用i5ting_toc
是一个可以把 md
文档转为 html
页面的小工具package.json
这个包管理配置文件package.json
中必须包含 name
,version
,main
这三个属性,分别代表包的名字、版本号、包的入口HTML
中的特殊字符HTML
中的特殊字符新建 itheima-tools
文件夹,作为包的根目录
在 itheima-tools
文件夹中,新建如下三个文件:
package.json
(包管理配置文件)index.js
(包的入口文件)README.md
(包的说明文档)package.json
配置文件{
"name": "flightloong-tools",
"version": "1.0.0",
"description": "提供格式化时间、HTMLEscape相关功能",
"main": "index.js",
"keywords": [
"itcast",
"itheima",
"dateFormat",
"escape"
],
"license": "ISC"
}
index.js
中定义格式化时间的方法// 包的入口文件 index.js
// 定义格式化时间的函数
function dateFormat (dateStr) {
const dt = new Date(dateStr)
const y = padZero(dt.getFullYear())
const m = padZero(dt.getMonth() + 1)
const d = padZero(dt.getDate())
const hh = padZero(dt.getHours())
const mm = padZero(dt.getMinutes())
const ss = padZero(dt.getSeconds())
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
// 定义一个补零的函数
function padZero (n) {
return n > 9 ? n : '0' + n
}
// 向外暴露需要的成员
module.exports = {
dateFormat
}
// 测试代码
const itheima = require('./flightloong-tools/index')
// 格式化时间的代码
const dtStr = itheima.dateFormat(new Date())
console.log(dtStr) // 2020-06-23 01:16:57
package.json
文件中 main
的作用在导入一个文件的时候,如果没有指定一个特定的文件,但是却能够得到某个包的返回内容,这是因为 Node
在使用 require
导入某个路径的时候,发现没有具体的文件,就会看这个路径下查看是否有 package.json
这个文件,如果有,则查看是否有 main
这个属性,如果有,则指定 main
属性对应的文件作为要执行的文件
index.js
中定义转义 HTML 的方法// index.js
// 定义转义 HTML 字符的函数
function htmlEscape(htmlstr) {
return htmlstr.replace(/<|>|"|&/g, match => {
switch (match) {
case '<':
return '&glt;'
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
// test.js
const itheima = require('./flightloong-tools/index')
// 转义 Html 字符串
const htmlStr = '这是h4标签123
'
const str = itheima.htmlEscape(htmlStr)
console.log(str)
index.js
中定义还原 HTML 的方法// 定义还原 HTML 字符的函数
function htmlUnEscape(str) {
return str.replace(/&glt;|>|"|&/g, (match) => {
switch (match) {
case '&glt;':
return '<'
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
// 还原 Html 字符串
const resetHtml = itheima.htmlUnEscape(str)
console.log(resetHtml)
src
-> dateFormat.js
中HTML
字符串的功能,拆分到 src
-> htmlEscape.js
中index.js
中,导入两个模块,得到需要向外共享的方法index.js
中,使用 module.exports
把对应的方法共享出去// dateFormat.js
// 定义格式化时间的函数
function dateFormat(dateStr) {
const dt = new Date(dateStr)
const y = padZero(dt.getFullYear())
const m = padZero(dt.getMonth() + 1)
const d = padZero(dt.getDate())
const hh = padZero(dt.getHours())
const mm = padZero(dt.getMinutes())
const ss = padZero(dt.getSeconds())
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
// 定义一个补零的函数
function padZero(n) {
return n > 9 ? n : '0' + n
}
module.exports = {
dateFormat
}
// htmlEscape.js
// 定义转义 HTML 字符的函数
function htmlEscape(htmlstr) {
return htmlstr.replace(/<|>|"|&/g, match => {
switch (match) {
case '<':
return '&glt;'
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
// 定义还原 HTML 字符的函数
function htmlUnEscape(str) {
return str.replace(/&glt;|>|"|&/g, (match) => {
switch (match) {
case '&glt;':
return '<'
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
module.exports = {
htmlEscape,
htmlUnEscape
}
// test.js
const itheima = require('./flightloong-tools/index')
// 格式化时间的代码
const dtStr = itheima.dateFormat(new Date())
console.log(dtStr)
// 转义 Html 字符串
const htmlStr = '这是h4标签123
'
const str = itheima.htmlEscape(htmlStr)
console.log(str)
// 还原 Html 字符串
const resetHtml = itheima.htmlUnEscape(str)
console.log(resetHtml)
README.md
文件,是包的使用说明文档。通过它,我们可以事先把包的使用说明,以 markdown
的格式写出来,方便用户参考README
文件中具体写什么内容,没有强制性的要求;只要能够清晰地把包的作用、用法、注意事项等描述清楚即可README.md
文档中,会包含以下 6 项内容### 安装
```
npm i flightloong-tools
```
### 导入
```js
const itheima = require('./flightloong-tools')
```
### 格式化时间
```js
// 调用 dateFormat 对时间进行格式化
const dtStr = itheima.dateFormat(new Date())
// 结果 2020-04-03 17:20:58
console.log(dtStr)
```
### 转义 HTML 中的特殊字符
```js
// 带转换的 HTML 字符串
const htmlStr = '这是h1标签123
'
// 调用 htmlEscape 方法进行转换
const str = itheima.htmlEscape(htmlStr)
// 转换的结果 <h1 title="abc">这是h1标签<span>123 </span></h1>
console.log(str)
```
### 还原 HTML 中的特殊字符
```js
// 待还原的 HTML 字符串
const str2 = itheima.htmlUnEscape(str)
// 输出的结果 这是h1标签123
console.log(str2)
```
### 开源协议
ISC
npm
账号sign up
按钮,进入注册用户界面Full Name
、Public Email
、Username
、Password
Create an Account
按钮,注册账号npm
账号npm
账号注册完成后,可以在终端中执行 npm login
命令,依次输入用户名、密码、邮箱后,即可登录成功npm login
命令之前,必须先把下包的服务器地址切换为 npm
的官方服务器。否则会导致发布包失败!npm
上将终端切换到包的根目录之后,运行 npm publish
命令,即可将包发布到 npm
上(注意:包名不能雷同)
npm unpublish 包名 --force
命令,即可从 npm
删除已发布的包npm unpublish
命令只能删除 72 小时以内发布的包npm unpublish
删除的包,在 24 小时内不允许重复发布npm
上发布没有意义的包!模块在第一次加载后会被缓存,这意味着多次调用 require()
方法不会导致模块的代码被多次执行
注意:不论内置模块、用户自定义模块、还是第三方模块,他们都会优先从缓存中加载,从而提高模块的加载效率
// 自定义模块.js
console.log('ok')
require('./自定义模块.js')
require('./自定义模块.js')
require('./自定义模块.js')
内置模块是由 Node.js
官方提供的模块,内置模块的加载优先级最高
例如: require('fs')
始终返回内置的 fs
模块,即使在 node_modules
目录下有名字相同的包也叫做 fs
const fs = require('fs') // 始终返回的是内置的 fs 模块
使用 require() 加载自定义模块时,必须指定以 ./
或者 ../
开头的路径标识符。在加载自定义模块时,如果没有指定 ./
或 ../
这样的路径标识符,则 node
会把它当作 内置模块
或 第三方模块
进行加载
在使用 require()
导入自定义模块时,如果省略了文件的拓展名,则 Node
会按照顺序分别尝试加载以下文件
.js
**扩展名进行加载.json
** 扩展名进行加载.node
扩展名进行加载如果传递给 require()
的模块标识符不是一个内置模块,也没有以 './'
或 '../'
开头,则 Node.js
会从当前模块的父目录开始,尝试从 /node_modules
文件夹中加载第三方模块
如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录
假设在 C:\Users\itheima\project\foo.js
文件里调用了 require('tools')
,则 Node.js
会按以下顺序查找
C:\Users\itheima\project\node_modules\tools
C:\Users\itheima\node_modules\tools
C:\Users\node_modules\tools
C:\node_modules\tools
当把目录作为模块标识符,传递给 require()
进行加载的时候,有三种加载方式:
package.json
的文件,并寻找 main
属性,作为 require()
加载的入口package.json
文件,或者 main
入口不存在或无法解析,则 Node.js
将会试图加载目录下的 index.js
文件Node.js
会在终端打印错误消息,报告模块的缺失:Error: Cannot find module xxx
Express
是基于 Node.js
平台,快速、开放、极简的 Web
开发框架,官方Express
的作用和 Node.js
内置的 http
模块类似,是专门用来创建 Web 服务器的Express
的本质:就是一个 npm
上的第三方包,提供了快速创建 Web 服务器的便捷方法Node.js
提供的原生 http
模块即可http
内置模块,为什么还有用 Express
)?http
内置模块用起来很复杂,开发效率低;Express
是基于内置的 http
模块进一步封装出来的,能够- 极大的提高开发效率http
内置模块与 Express
是什么关系?Web API
和 jQuery
的关系。后者是基于前者进一步封装出来的Web
网站服务器:专门对外提供 Web
网页资源的服务器。
API
接口服务器:专门对外提供 API
接口的服务器。
Express
,我们可以方便、快速的创建 Web
网站的服务器或 API
接口的服务器。在项目所处的目录中,运行如下的终端命令,即可将 express 安装到项目中使用
npm i express
创建基本的 Web 服务器
// 1.导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()
// 3. 调用 app.listen(端口号, 启动后的回调函数), 启动服务器
app.listen(3000, () => {
console.log('running……')
})
监听 GET
请求
监听 POST
请求
把内容响应给客户端
// 1.导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()
// 4. 监听客户端的 GET 和 Post 请求,并向客户端响应具体的内容
app.get('/user', (req, res) => {
// 调用 express 提供的 res.send() 方法,向客户端响应一个 JSON 对象
res.send({ name: 'zs', age: 20, gender: '男' })
})
app.post('/user', (req, res) => {
// 调用 express 提供的 res.send() 方法,向客户端响应一个文本字符串
res.send('请求成功')
})
// 3. 调用 app.listen(端口号, 启动后的回调函数), 启动服务器
app.listen(3000, () => {
console.log('running……')
})
req.query
对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数
const express = require('express')
const app = express()
app.get('/', (req, res) => {
// 通过 req.query 可以获取到客户端发送过来的,查询参数
// 注意:默认情况下, req.query 是一个空对象
console.log(req.query)
res.send(req.query)
})
app.listen(3000, () => {
console.log('running……')
})
req.params
对象,可以访问到 URL
中,通过 : 匹配到的动态参数/:id
– id 值不是固定的,可以自己定义,例如: /:ids
id
键,是自定义的变量值/:ids/:name
const express = require('express')
const app = express()
// 注意:这里的 :id 是一个动态的参数
app.get('/user/:id', (req, res) => {
// req.params 是动态匹配到的 URL 参数,默认也会是一个空对象
console.log(req.params)
res.send(req.params)
})
app.listen(3000, () => {
console.log('running……')
})
express.static()
express
提供了一个非常好用的函数,叫做 express.static()
,通过它,我们可以非常方便地创建一个静态资源服务器,public
目录下的图片、CSS
文件、JavaScript
文件对外开放访问了现在,你就可以访问 public 目录中的所有文件了:
访问图片资源:http://localhost:3000/images/bg.jpg
访问 css
资源:http://localhost:3000/css/style.css
访问 js
资源:http://localhost:3000/js/login.js
注意:Express
在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放静态文件的目录名不会出现在 URL
中
完整代码
const express = require('express')
const app = express()
// 在这里,调用 express.static() 方法,快速的对外提供静态资源
app.use(express.static('public'))
app.listen(3000, () => {
console.log('running……')
})
express.static()
函数,express.static()
函数会根据目录的添加顺序查找所需的文件完整代码
const express = require('express')
const app = express()
// 在这里,调用 express.static() 方法,快速的对外提供静态资源
app.use(express.static('public'))
app.use(express.static('static'))
app.listen(3000, () => {
console.log('running……')
})
可以通过带有 /public
前缀地址来访问 public 目录中的文件了:
http://localhost:3000/public/images/kitten.jpg
http://localhost:3000/public/css/style.css
http://localhost:3000/public/js/app.js
const express = require('express')
const app = express()
// 在这里,调用 express.static() 方法,快速的对外提供静态资源
app.use('/static', express.static('public'))
app.listen(3000, () => {
console.log('running……')
})
nodemon
nodemon
nodemon
在编写调试 Node.js
项目的时候,如果修改了项目的代码,则需要频繁的手动 close
掉,然后再重新启动,非常繁琐。现在,我们可以使用 nodemon 这个工具,它能够监听项目文件的变动,当代码被修改后,nodemon
会自动帮我们重启项目,极大方便了开发和调试
安装 nodemon
npm i nodemon -g
nodemon
实现后台项目的重启当基于 Node.js
编写了一个网站应用的时候,传统的方式,是运行 node app.js
命令,来启动项目
这样做的坏处是:代码被修改之后,需要手动重启项目
将 node
命令替换为 nodemon
命令,使用 nodemon app.js
来启动项目
这样做的好处是:代码被修改之后,会被 nodemon
监听到,从而实现自动重启项目的效果
// 使用 node 运行项目
node app.js
// 使用 nodemon 运行项目
nodemon index.js