1. Javascript 的单线程和异步
Javascript 的解析和执行一直是单线程的,但是宿主环境(浏览器或node)是多线程的;
异步任务是由宿主环境开启子线程完成,并通过事件驱动、回调函数、队列,把完成的任务, 交给主线程执行;
Javascript解析引擎,一直在做一个工作,就是从任务队列里提取任务,放到主线程里执行。
2. Node中的API为什么几乎都是异步操作
- 什么样的操作需要使用异步处理:要把 耗时的操作,放到异步中去执行;
- 异步执行任务的好处:能够提高 耗时的任务它的执行效率,提高 JS 解析引擎的工作效率;
3. 认识模块化
模块化就是一种约定,一定规范;
场景模拟:小强,小黄,小刚 共同基于 Node.js 开发项目!
- 为什么要有模块化:为了解决文件之间的依赖关系;
- 注意:模块化是一种开发思想;具体开发中需要定制符合实际需求的模块化规范!
- 大家可以把模块化规范,认为是一种明文的约定,大家都按照相同的约定写代码,减少了不必要的沟通成本,极大方便了各个模块之间的调用,方便别人,同时也方便自己;
4. 了解 CommonJS 规范
- 作用:是一套 Javascript 的模块化规范,规定了 模块的特性 和 各模块之间如何相互依赖;
- 用途:Node.js 中使用了 CommonJS 规范;
- 特点:同步加载模块;不适合在浏览器端使用;
- CommonJS规范都定义了哪些内容:wiki 对于 Modules 的描述
5. 模块作用域 和 全局作用域
在Node.js中有两个作用域,分别是 全局作用域 和 模块作用域;
- 全局作用域使用
global
来访问,类似于浏览器中的window
; - 每个 Javascript 文件,都是一个单独模块,每个模块都有自己独立的作用域,因此:模块中的成员,默认无法被其它模块访问。
使用 global 全局作用域在模块之间共享成员
- 如果在某个模块内部,想为 全局的 global 作用域挂载一些属性,需要显示的调用
global.***
来挂载; - 注意:在开发中,一般情况下,不推荐使用
global
全局作用域来共享成员,会存在全局变量污染问题;
模块作用域
-
module(模块标识)
module 属性是 Common JS 规范中定义的,它是一个对象,表示当前这个具体的 js 模块;
-
require(引用模块)
每一个实现了 CommonJS 规范的模块,必须定义一个 require() 函数,使用这个 require 函数,就能够 很方便的导入其它 模块中的成员,供自己使用;
-
exports(暴露模块成员)
每一个模块中,如果想要把自己的一些私有成员,暴露给别人使用,那么,必须实现一个 exports 对象,通过exports对象,可以方便的把模块内私有的成员,暴露给外界使用;
module.exports 和 exports 的关系
-
module.exports
和exports
默认引用了同一个空对象; -
module.exports
和exports
作用一致,都可以向外暴露成员; - 一个模块作用域中,向外暴露私有成员时,永远以
module.exports
为准;
6. 了解 - 浏览器端的 AMD 和 CMD 模块化规范
注意:浏览器端不能使用 CommonJS规范;因为 CommonJS 下,模块是同步加载的;
AMD/CMD可以理解为是commonjs在浏览器端的解决方案,AMD/CMD下,模块都是异步加载的;
- AMD模块化规范代表:RequireJS
- 主要特性1:对于依赖的模块,AMD 是提前执行;
- 主要特性2:推崇依赖前置;
- CMD模块化规范代表:SeaJS
- 主要特性1:对于依赖的模块,CMD 是延迟执行;CMD 推崇 as lazy as possible.
- 主要特性2:推崇依赖就近;
- ES6的模块化(大趋势):es6是在语言标准层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案;
7. Node.js 中 模块
和 包
的概念
回顾:Node.js 由三部分组成:ECMAScript 核心 + 全局成员 + 模块成员
模块成员的分类
模块成员,根据一些区别,又可以分为三大类: 核心模块、第三方模块、用户自定义模块
核心模块
-
什么是核心模块:
- 随着Node.js的安装包,一同安装到本地的模块,叫做核心模块;
- 例如:
fs
,path
等模块,都是由Node.js官方提供的核心模块; - 只要大家在计算机中,安装了Node这个应用程序,那么,我们的计算机中就已经安装了所有的 核心模块;
-
如何使用核心模块:
require('核心模块标识符')
第三方模块
-
什么是第三方模块:
- 一些非官方提供的模块,叫做第三方模块;
- 注意,第三方模块,并不在我们的计算机上;
- 如果大家需要使用某些第三方模块,必须去一个叫做
NPM
的网站上搜索并下载才能使用;
-
如何使用第三方模块:
- 先从 npm 官网上下载指定的第三方模块
- 使用
require('第三方模块的名称标识符')
来导入这个模块 - 根据 第三方模块的 官方文档,尝试使用
用户自定义模块
-
什么是用户模块:
- 程序员在自己项目中写的 Javascript 文件,就叫做 用户自定义模块;
-
如何使用用户模块:
require('路径标识符')
包的定义和使用
什么是包
- 英文名叫做
Packages
,包是在模块基础上更深一步的抽象; - 包的目的:方便分发和推广基于 CommonJS 规范实现的 应用程序 或 类库;
- 包可以看作是 模块、代码 和 其它资源 组合起来形成的 独立作用域;
规范的包结构
- 包都要以一个单独的目录而存在;
-
package.json
必须在包的顶层目录下; -
package.json
文件必须符合 JSON 格式,并且必须包含如下三个属性:name
,version
,main
- name: 包的名字
- version: 包的版本号
- main: 表示包的入口文件
- 二进制文件应该在bin目录下;
- javaScript代码应该在lib目录下;
- 文档应该在doc目录下;
- 单元测试应该在test目录下;
- Node.js对包要求并没有那么严格,只要顶层目录下有
package.json
,并符合基本规范即可;
包描述文件 package.json
name:包的名称,必须是唯一
description:包的简要说明
version:符合语义化版本识别规范的版本字符串
keywords:关键字数据,通常用于搜索
maintainers:维护者数组,每个元素要包含name、email、web可选字段
contributors:贡献者数组,格式与maintainers相同。包的坐着应该是贡献者数据的第一个元素
bugs:提交bug的地址,可以是网址或者电子邮件地址
licenses:许可证数组,每个元素要包含type和url字段
repositories:仓库托管地址数组,每个元素要包含type、url和path字段
dependencies:包的依赖,一个关联数组,由包名称和版本号组成。
devDependencies:开发依赖项,表示一个包在开发期间用到的依赖项
8. npm
npm 的两层含义
- NPM 是一个 第三方模块的托管网站,指的就是
https://www.npmjs.com/
; - NPM 是Node的包管理工具(全名叫做 Node package manager),在我们安装Node时候,就已经顺便也安装了 NPM 这个管理工具;
安装和卸载全局包(i5ting_toc)
- 什么是全局的包:安装到计算机全局环境中的包,叫做全局包;安装的全局包可以在当前电脑的任何目录下,直接通过命令行来访问;
-
如何安装全局包:运行
npm install 包名 -g
即可;其中-g
参数,表示 把包安装到全局目录中的意思; -
全局包的安装目录:
C:\Users\用户目录\AppData\Roaming\npm
- 什么样的包适合安装到全局:工具性质的包,适合安装到全局;
-
如何卸载全局包:要卸载某个全局的包,直接运行
npm uninstall 包名 -g
即可;其中uninstall
表示卸载的意思;
安装和卸载本地包
- 什么是本地的包:跟着项目安装的包,叫做本地包;本地包都会被安装到 node_modules 目录下;
-
注意:如果拿到一个空项目,必须在当前项目根目录中,先运行
npm init
或者npm init -y
命令,初始化一个package.json
的配置文件,否则包无法安装到本地项目中; -
如何安装本地包:运行
npm i 包名 --save
即可安装本地包;都安装到了当前项目的node_modules
目录下;- 如果大家用的是npm 5.x的版本,可以不指定
--save
命令,如果用的是 npm 3.x 的版本,则需要手动指定--save
;
- 如果大家用的是npm 5.x的版本,可以不指定
-
package-lock.json
文件中记录了曾经装过的包的下载地址,方便下次直接下载包,能够加快装包的速度,提升装包的体验; -
如何卸载本地包:使用
npm uninstall/remove 包名 -S/-D
即可卸载指定的本地包;
其它常用命令
-
--save
的缩写是-S
-
--save-dev
的缩写是-D
-
install
的缩写是i
- 注意:
dependencies
节点,表示项目上线部署时候需要的依赖项;devDependencies
节点,表示项目在开发阶段需要的依赖项,但是当项目要部署上线了,devDependencies
节点中的包,就不再需要了! - 注意:当使用
npm i
快速装包的时候,npm会检查package.json
文件中,所有的依赖项,然后都为我们安装到项目中 -
--production
表示只安装dependencies
节点下,记录的包,不安装devDependencies
节点下的包;当项目要上线了,才会使用--production
命令
解决 npm 下载慢问题
- 默认,NPM在下载包的时候,连接的是国外的服务器,所以,有时候如果网速不是特别好,可能下载不下来包;此时,大家可以全局安装一个的工具,叫做
cnpm
- 如何安装
cnpm
:运行npm install -g cnpm --registry=https://registry.npm.taobao.org
即可; - 如何使用
cnpm
:在装包的时候,只需要把npm
替换成cnpm
即可,例如:- 使用
npm
安装jquery
:运行npm i jquery -S
- 使用
cnpm
安装jquery
: 运行cnpm i jquery -S
- 使用
使用 Node 构建 web 应用
- PHP是后端的网站开发语言,PHP 开发出来的网站,可以通过 Apache 服务器托管运行起来;
- 疑问:Node中,可以使用 Javascript 编写后端网站,那么,有没有类似于 Apache 这样的服务器软件,来提供对应的网站服务呢?
B/S 交互模型
什么是B/S:特指基于 浏览器(Browser) 和 服务器(Server) 这种交互形式;
- 什么是服务器:在网络节点中,专门对外提供资源服务的一台电脑;
- 什么是客户端:在网络节点中,专门用来消费服务的一台电脑;
-
HTTP 协议的通信模型:
请求 - 处理 - 响应
的过程;- 请求:由客户端发起请求;
- 处理:由服务器端处理请求;
- 响应:服务器端把处理的结果,通过网络发送给客户端;
- 什么是静态资源:服务器端只需要读取并直接发送给客户端、不需要进一步处理的资源,叫做静态资源;
- 什么是动态资源:服务器端没有现成的资源,需要服务器端动态生成的资源,叫做动态资源;
实现一个类似于Apache的 静态资源服务器
使用
http
核心模块,创建最基本的web服务器
-
创建最基本的web服务器
-
创建服务器:使用
const server = http.createServer()
创建服务器; -
绑定监听事件:通过
server.on('request', function(req, res) { 请求的处理函数 })
绑定事件 并 指定 处理函数; -
启动服务器:通过
server.listen(端口, IP地址, 启动成功的回调函数)
来启动服务器;
-
创建服务器:使用
-
防止响应内容中文乱码问题
-
通过 设置响应报文头的
Content-Type
,来指定响应内容的编码类型,从而防止乱码:res.writeHeader(200, { 'Content-Type': 'text/plain; charset=utf-8' })
-
-
根据不同的URL返回不同的文本内容
- 使用
req.url
获取客户端请求的URL地址
- 使用
-
根据不同的URL返回不同的HTML页面
- 主要思路:使用
fs 模块
读取URL对应的HTML页面内容,并使用res.end()
响应给客户端即可;
- 主要思路:使用
处理并返回css样式表
处理并返回Javascript文件
优化
更多文章访问个人博客:http://www.lfanliu.top