1. 浏览器端的 AMD 和 CMD 模块化规范 【08-09年 流行】
注意:浏览器端不能使用 CommonJS规范;因为 CommonJS 下,模块是同步加载
的;
AMD/CMD可以理解为是commonjs在浏览器端的解决方案,AMD/CMD下,模块都是异步加载
的;
-
AMD模块化规范代表:RequireJS
主要特性1:对于依赖的模块,AMD 是提前执行;
js文件中依赖其他的js模块,这个模块不一定用到,但会提前执行
主要特性2:推崇依赖前置;
若你想用一个模块,需要先定义好怎么用 =》 需要先定义才能使用
-
CMD模块化规范代表:SeaJS
主要特性1:对于依赖的模块,CMD 是延迟执行;CMD 推崇 as lazy as possible.
尽可能晚的执行这个模块,这样尽可能提高js的执行效率。因为执行一定的模块,需要浪费一定的时间和性能 只有等真正用到的时候,采取去执行
主要特性2:推崇依赖就近;
若需要用到哪个模块,不需要先去定义再使用。 而是用到哪个模块,再去定义哪个模块
-
ES6的模块化(大趋势):es6是在
语言标准层面上
,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案
而AMD和CMD是在框架层面上,实现了模块功能,也就是说: 需要用AMD模块化规范,必须使用 RequireJS 框架,同理 需要用CMD模块化规范,必须使用 SeaJS 框架。 ************************************ ES6是在语言标准层面上,实现了模块功能。也就是说: 只要编程语言用的JavaScript,不需要使用任何框架, 就可以使用模块化导入其他模块、暴露自己的成员给其他成员使用 ************************************** 在CommonJS模块化规范中:它就具体规定了一个模块如何把自己内部的成员暴露给外部使用; 同时它也定义了外部在使用模块时应该遵循什么样的语法规范来进行使用 Node.js遵循了CommonJS规范:所以我们使用NodeJS编写代码的时候,无形中已经在使用了CommonJS规范
2. Node.js 中 模块
和 包
的概念
Node.js 由三部分组成:ECMAScript 核心 + 全局成员 + 模块成员
模块成员,根据一些区别,又可以分为三大类: 核心模块、第三方模块、用户自定义模块
2.1 核心模块
什么是核心模块
-
随着Node.js的安装包,一同安装到本地的模块,叫做核心模块;
例如:
fs
,path
等模块,都是由Node.js官方提供的核心模块;只要大家在计算机中,安装了Node这个应用程序,那么,我们的计算机中就已经安装了所有的 核心模块;
- 如何使用核心模块:
require('核心模块标识符')
2.2 第三方模块
什么是第三方模块:
-
一些非官方提供的模块,叫做第三方模块;
注意,第三方模块,并不在我们的计算机上;
如果大家需要使用某些第三方模块,必须去一个叫做
NPM
的网站上搜索并下载才能使用;
-
如何使用第三方模块:
先从 npm 官网上下载指定的第三方模块
使用
require('第三方模块的名称标识符')
来导入这个模块根据 第三方模块的 官方文档,尝试使用
2.3 用户自定义模块
-
什么是用户模块:
程序员在自己项目中写的 Javascript 文件,就叫做 用户自定义模块;
-
如何使用用户模块:
require('路径标识符')
3. 包的定义和使用
3.1 什么是包
英文名叫做 Packages
,包是在模块基础上更深一步的抽象;
程序员在自己项目中写的 Javascript 文件,都可以称为一个模块。
js文件中实现的功能,仅限于自己的项目使用,其他人员是无法用到这个模块的。
如果想让这个模块,让全世界的人都可以使用,就需要想办法把自己的模块封装为一个包。
将包上传到npm网站上供他们下载使用模块中的功能。
所以说:包就是功能的集合体、文件夹。
文件夹中封装了各种各样的文件,这些文件有一个统一的目的:对外提供具体的功能。
只要别人在 npm网站上搜索到这个包下载使用。就可以根据这个包提供的功能,实现它具体的业务逻辑
包的目的:方便分发和推广基于 CommonJS 规范实现的 应用程序 或 类库;
包可以看作是 模块、代码 和 其它资源 组合起来形成的 独立作用域;
包里所有的文件都是为包里所提供的功能而服务的
3.2 规范的包结构 【严格遵守前3项】
- 包都要以一个单独的目录而存在;
package.json
必须在包的顶层目录下;package.json
文件必须符合 JSON 格式,并且必须包含如下三个属性:name
,version
,main
- name: 包的名字
- version: 包的版本号
- main: 表示包的入口文件
- 二进制文件应该在bin目录下;
- javaScript代码应该在lib目录下;
- 文档应该在doc目录下;
- 单元测试应该在test目录下;
- Node.js对包要求并没有那么严格,只要顶层目录下有
package.json
,并符合基本规范即可;
3.3 包描述文件 package.json【了解】
- name:包的名称,必须是唯一
- version:符合语义化版本识别规范的版本字符串
- description:包的简要说明
- keywords:关键字数据,通常用于搜索
- maintainers:维护者数组,每个元素要包含name、email、web可选字段
- contributors:贡献者数组,格式与maintainers相同。包的坐着应该是贡献者数据的第一个元素
- bugs:提交bug的地址,可以是网址或者电子邮件地址
- licenses:许可证数组,每个元素要包含type和url字段
- repositories:仓库托管地址数组,每个元素要包含type、url和path字段
- dependencies:包的依赖,一个关联数组,由包名称和版本号组成。
- devDependencies:开发依赖项,表示一个包在开发期间用到的依赖项
3.4 定义 加减乘除的 calc 计算器包 【重点】
testCalc.js
/*
通过路径标识符导入 calc 包的,此时导入的就是package.json配置中main属性指定的文件路径
*/
const calc = require('./calc')
/*
在 导入 包的时候,require 的名字,必须是 包文件夹的名字;
而且,只要把包放到 node_modules 目录中,才能直接使用名称来引入这个包
*/
const calc = require('calc')
console.log(calc.add(1, 2))
console.log(calc.sub(5, 3))
node_modules
calc 包
package.json
{
"name":"calc",
"version":"0.0.1",
"main":"./lib/main.js"
}
README.md
#calc 包
## 安装
## 使用
lib 文件夹
main.js 暴露成员入口
//这个 main.js 是向外暴露成员的统一入口
//导入 四则运算的 模块
const add =require('./add.js');
const sub =require('./sub.js');
const mut =require('./mut.js');
const devide =require('./devide.js');
module.exports= {
add,
sub,
mut,
devide
}
add.js 加法
//加法模块
function add(x,y) {
return x+y
}
module.exports = add
devide.js 除法
//除法模块
function devide(x,y) {
return x / y
}
module.exports = devide
mut.js 乘法
//乘法模块
function mut(x,y) {
return x * y
}
module.exports = mut
sub.js 减法
//减法模块
function sub(x,y) {
return x-y
}
module.exports = sub
4. npm
4.1 npm 的两层含义
- NPM 是一个 第三方模块的托管网站,指的就是
https://www.npmjs.com/
; - NPM 是Node的包管理工具(全名叫做 Node package manager),在我们安装Node时候,就已经顺便也安装了 NPM 这个管理工具;
4.2 安装和卸载全局包(i5ting_toc)
将md文件转化为html文件 npm i i5ting_toc -g
定位到md文件所在目录,按shift + 鼠标右键 => 打开终端窗口: i5ting_toc -f .\md文件路径
- 什么是全局的包:安装到计算机全局环境中的包,叫做全局包;安装的全局包可以在当前电脑的任何目录下,直接通过命令行来访问;
- 如何安装全局包:运行
npm install 包名 -g
即可;其中-g
参数,表示 把包安装到全局目录中的意思; - 全局包的安装目录:
C:\Users\用户目录\AppData\Roaming\npm
- 什么样的包适合安装到全局:工具性质的包,适合安装到全局;
- 如何卸载全局包:要卸载某个全局的包,直接运行
npm uninstall 包名 -g
即可;其中uninstall
表示卸载的意思;
4.3 安装和卸载本地包
- 什么是本地的包:跟着项目安装的包,叫做本地包;本地包都会被安装到 node_modules 目录下;
- 注意:如果拿到一个空项目,必须在当前项目根目录中,先运行
npm init
或者npm init -y
命令,初始化一个package.json
的配置文件,否则包无法安装到本地项目中; - 如何安装本地包:运行
npm i 包名 --save
即可安装本地包;都安装到了当前项目的node_modules
目录下;如果大家用的是npm 5.x的版本,可以不指定
--save
命令,如果用的是 npm 3.x 的版本,则需要手动指定--save
; package-lock.json
文件中记录了曾经装过的包的下载地址,方便下次直接下载包,能够加快装包的速度,提升装包的体验;- 如何卸载本地包:使用
npm uninstall/remove 包名 -S/-D
即可卸载指定的本地包;
4.4 其它常用命令
-
--save
的缩写是-S
-
--save-dev
的缩写是-D
-
install
的缩写是i
-
注意:
dependencies
节点,表示项目上线部署
时候需要的依赖项;devDependencies
节点,表示项目在开发阶段
需要的依赖项,但是当项目要部署上线了,
devDependencies
节点中的包,就不再需要了! -
注意:当使用
npm i
快速装包的时候,npm会检查package.json
文件中,所有的依赖项,然后都为我们安装到项目中
-
--production
表示只安装dependencies
节点下记录的包,不安装devDependencies
节点下的包;当项目要上线了,才会使用
--production
命令
4.5 解决 npm 下载慢问题
- 默认,NPM在下载包的时候,连接的是国外的服务器,所以,有时候如果网速不是特别好,可能下载不下来包;此时,大家可以全局安装一个的工具,叫做
cnpm
- 如何安装
cnpm
:运行npm i cnpm -g
即可; - 如何使用
cnpm
:在装包的时候,只需要把npm
替换成cnpm
即可,例如:- 使用
npm
安装jquery
:运行npm i jquery -S
- 使用
cnpm
安装jquery
: 运行cnpm i jquery -S
- 使用
5. 使用 Node 构建 web 应用
-
PHP是后端的网站开发语言,PHP 开发出来的网站,可以通过 Apache 服务器托管运行起来;
-
疑问:Node中,可以使用 Javascript 编写后端网站,那么,有没有类似于 Apache 这样的服务器软件,来提供对应的网站服务呢?
回答:Node中没有这样的服务器软件,需要程序员手动搭配服务器
5.1 B/S 交互模型
什么是B/S:特指基于 浏览器(Browser) 和 服务器(Server) 这种交互形式;
- 什么是服务器:在网络节点中,专门对外提供资源服务的一台电脑;
- 什么是客户端:在网络节点中,专门用来消费服务的一台电脑;
- HTTP 协议的通信模型:
请求 - 处理 - 响应
的过程;- 请求:由客户端发起请求;
- 处理:由服务器端处理请求;
- 响应:服务器端把处理的结果,通过网络发送给客户端;
- 什么是静态资源:服务器端只需要读取并直接发送给客户端、不需要进一步处理的资源,叫做静态资源;
- 什么是动态资源:服务器端没有现成的资源,需要服务器端动态生成的资源,叫做动态资源;
5.2 实现一个类似于Apache的 静态资源服务器
使用
http
核心模块,创建最基本的web服务器
/**
* 创建最基本的web服务器,步奏:
* 1.导入 http 核心模块
* 2.调用 http.createServer() 方法,创建一个web 服务器对象
* 3.为 server 服务器 绑定 监听函数,通过 on 方法,绑定 request 事件,来监听 客户端的请求
* 4.server.listen 来启动服务器
*/
const http = require('http')
const fs = require('fs')
const path = require('path')
/**
* 2. 调用 http.createServer 方法,创建一个web 服务器对象
通过 第二步 创建的 server 服务器,并不能监听任何 客户端的请求;同时 它也没有被启动
*/
const server = http.createServer()
/**
* 3. 为 server 服务器 绑定 监听函数,通过 on 方法,绑定 request 事件,来监听 客户端的请求
* 可以通过 request 事件,来监听并处理客户端的请求;
* req 表示 客户端 相关的参数
* res 表示 和 服务器相关的参数 和 方法 res.end('hello world.')
*/
server.on('request', function (req, res) {
let url = req.url
/**
* 防止中文乱码
* text/plain 和 text/html 的区别:
* plain 表示普通的文本字符串;
* html 表示以 HTMl 标签的形式去解析服务器返回的内容
*/
res.writeHeader(200, {
'Content-Type': 'text/html; charset=utf-8'
})
// 判断请求的URL地址,返回对应的HTML页面内容
if (url === '/') url = '/views/index.html'
/**
* 使用 fs 模块,读取文件 通过 res.end 返回即可
*/
fs.readFile(path.join(__dirname, url), (err, buf) => {
if (err) return res.end('404. Not found.')
res.end(buf)
})
})
server.listen(3000, () => {
console.log('server running at http://127.0.0.1:3000')
})
5.3 在Node中结合模板引擎 实现动态资源服务器
view/1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>这是一个动态渲染的页面</h1>
<h6>通过 Node 服务器,结合 art-template 模板引擎渲染的动态页面</h6>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>
爱好:
{{each hobby}}
<span>{{$value}}</span>
{{/each}}
</p>
</body>
</html>
初始化项目
npm init -y npm install art-template
/**
* 创建最基本的web服务器,步奏:
* 1.导入 http 核心模块
* 2.调用 http.createServer() 方法,创建一个web 服务器对象
* 3.为 server 服务器 绑定 监听函数,通过 on 方法,绑定 request 事件,来监听 客户端的请求
* 4.server.listen 来启动服务器
*/
// 1. 导入 http 核心模块
const http = require('http')
// 导入 模板引擎
const template = require('art-template')
const path = require('path')
/**
* 2. 调用 http.createServer 方法,创建一个web 服务器对象
通过 第二步 创建的 server 服务器,并不能监听任何 客户端的请求;同时 它也没有被启动
*/
const server = http.createServer()
/**
* 3. 为 server 服务器 绑定 监听函数,通过 on 方法,绑定 request 事件,来监听 客户端的请求
* 可以通过 request 事件,来监听并处理客户端的请求;
* req 表示 客户端 相关的参数
* res 表示 和 服务器相关的参数 和 方法 res.end('hello world.')
*/
server.on('request', function (req, res) {
const url = req.url
if (url === '/') {
/**
* 基于模板名渲染模板 template(filename, data)
* 其中,第一个参数,是要渲染的HTML页面的路径; 第二个参数 是要渲染的 数据;
* template 方法的返回值,就是 渲染好的HTML内容,可以直接通过 res.end 发送给客户端
* 如果在渲染页面的时候,没有需要渲染的数据,则第二个参数,可以指定为一个 { } 空对象
*/
const htmlStr = template(path.join(__dirname, '/views/1.html'), { name: 'zs', age: 22, hobby: ['吃饭', '唱歌', '跳舞'] })
res.end(htmlStr)
}
})
server.listen(3000, function () {
console.log('server running at http://127.0.0.1:3000')
})