一、 CommonJS 规范
1.1nodejs 与 commonjs 之间的关系:
1)nodejs是一种服务器语言。
a)开启服务的能力
b)文件读写的能力
服务器:就是一台安装了服务软件
2)commonjs是nodejs的规范。
1.2commonjs规范的意义:
由于nodejs是用javascript来写的,javascript遵守ECMAScript规范,而ECMAScript这个规范它(如果作为一门后台语言的规范)是不完整的,因为它内容仅仅只是规范了javascript的:词法、类型、表达式、方法、对象等基本要素。
如果使用ECMAScript来作为规范还有以下几个缺点:
1)没有模块系统(不方便扩展)
2)标准库较少,对于文件系统,I/O流等常见的需求没有标准的API
commonjs规范:
1)有开启服务器的能力
2)能够做一些服务器能做的事情:操作二进制,字符编码,io读写…
3)Nodejs模块化的规则:引用文件require 暴露接口:exports,module.exports 定义模块
二、核心模块
2.1核心模块 Path
作用:
basename(path) 获取传入路径的文件名
dirname(path) 获取传入路径目录
extname(path) 获取传入路径的扩展名
join()将两个或两个以上的路径拼接在一起
parse(path)将传入的路径转换为一个路径对象
format(pathObject)将一个路径对象转换为字符串
delimiter 得到操作系统的分隔符
isAbsolute(path) 判断一个路径是否是一个绝对路径
normalize(path) 将一个非标准路径转换成一个标准路径
relative(from path to path) form路径到to路径要的查找过程
sep 在win系统下得到‘\‘分隔符,在其它系统下面得到‘/‘分隔符
posix 所有的路径方法的一个集合
2.2核心模块 URL
作用:用于操作url
1.2.1 url的组成:协议名,用户名和密码,服务器IP地址,端口号,请求的路径,参数,哈希数
1.2.2 常用API:
url.prase(path)
url.format(pathObject)
2.3核心模块 querystring
作用:操作url中的参数
2.3.1 querystring常用的API:
querystring.parse() 将一个参数字符串转为对象
querystring.stringify()将一个对象转为字符串
querystring.escape(url) 将url中的汉字进行转码
querystring.unescape(url) 将url中被转码的汉字重新转为汉字
三、文件模块
3.1什么是文件模块:
nodejs在核心模块,模块的功能有限,我们根据自己的需求写出一个模块,这个模块在nodejs中统称为文件模块,又叫用户模块,第三方包
3.2 如何自己开发一个文件模块
过程:
一版本:
直接开发一个js文件,开发出需要的计算功能,使用另一个js文件去引用,但是如果将来再次加入其它的功能,又需要再加入另一个文件,开发对应的功能,再次用使用的js文件去引用,太麻烦了,为了能够让结构代码更加的清晰,我们将所有的文件约定好放在同一个文件夹node_modules中
注意点:
1)nodejs是定义模块不需要关键字define,其它跟js中的模块化一样
2)引用文件模块可以时路径中可以不加后缀
二版本:
用一个node_modules文件夹将所有文件模块放入其中(注意:这个node_module文件夹非常重要,将来开发过程中所有的文件模块都是放到这个文件下的)。但是如果将来我们开发的内容不仅仅是限于一个计算功能,可能还会有其它功能,比如说登录注册功能,那么一个node_modules下面放的文件就相当于有两种类型的文件了,为了将这两种类型的文件区分开。我们给每个类型的功能单独建立一个文件夹,来管理对应的模块,并且为每个在每个文件夹中设置一个对面的文件(像这样 的一个文件在nodejs我们将它称作包,一个包是多个js文件或者说js模块组成的,并且具有一个统一的出口文件,并且出口文件一般情况下名称定义为index.js)(图解)。
三版本:
写好包以后如果要使用还要直接去引包的出口文件,这样改造后的出口文件一般情况下路径很长,为了操作方便。我们不会再去引全路径,而是会直接引用的require上面放上包名以此来导入包,虽然路径没有写全,但是运行以后发现文件还是正常的,说明nodejs在执行require(‘包名‘)是有自己的过程的。
3.3 nodejs的引包过程
步骤一:当nodejs执行到require(‘包名‘)的时候会先将这个包名当作核心模块来识别
步骤二:但是发现这个包并不是核心模块时,会自动去node_modules文件中查找文件名为这个包名的文件夹
步骤二点五:如果找到这个包,且包中有一个叫做package.json的文件,nodejs会根据package.json中的main属性去找到对应的入口文件
步骤三:如果没有package.json文件就直接去包中找一个名称为index.js的模块,并加载出来
步骤四:如果都没有找到,就报错
3.4 package.js 文件
作用:给当前的包设置一些重要参数
生成package.js文件:关键指令npm init -y
在包文件夹下打开CMD,输入上面指令,会自动在这个目录下面生成一个package.json文件
文件内容:
{
"name": "js",
"version": "1.0.0",
"description": "",
"main": "abc.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
属性的作用:
name:设置当前包的名称(将来发布到npm上的名称)
下面是官方给出的一些建议:
名字里不要再包含"js"和"node",因为默认NPM包就是node.js程序,不过你可以通过engines字段来指定。
名字将会被作为url的一部分,所有要符合http url的一般命名规则,不能包含url非法字符,也不能以.和_开头。
名字也将作为require()命令的参数,所以应该尽量简明。
如果包要发布到NPM平台上的话,最好先检查下有没有重名, 并且字母只能全部小写。
version:设置当前包的版本,例:v2.0.0
name和version是package.json中最重要的两个字段,也是发布到NPM平台上的唯一标识,如果没有正确设置这两个字段,包就不能发布和被下载。
description:设置当前包的描述信息(方便将来其它用户在npm上能名搜索到已发布的包)
main:设置当前包的出口文件
script:这个设置可以使当前包调用NPM一些命令脚本,封装一些功能
keywords:设置当前包的关键字(方便将来其它用户在npm上能名搜索到已发布的包)
author:当前包的作者
license:设置当前包的许可证书版本(BSD-3-Clause,MIT,ISC)
这些许可证书规定了将来软件其它人得到以后是否可以做的一些操作:比如:使用,修改,转发, 以及使用项目的一部分出售。
注意:每一个包都必须要有一个json文件
3.5 包
什么是包:
就是将一组功能相似的文件模块统一放到一个文件夹下,并且为所有的文件模块设置一个统一的出口文件,这样的文件夹在nodejs中被称为包。
一个符合CommonJS规范的包应该是如下这种结构:
一个package.json文件应该存在于包顶级目录下(必须)
二进制文件应该包含在bin目录下(非必须)。
JavaScript代码应该包含在lib目录下(必须)。
文档应该在doc目录下(非必须)。
单元测试应该在test目录下(非必须)。
使用说明放在README.md文件,这个文件必须放在包的顶级目录(必须)
结构:
_包名
|
|__package.json
|
|__bin
| |
| |__二进制文件
| |
|__lib
| |
| |__JavaScript代码
|
|__doc
| |
| |__文档
|
|__text
| |
| |__单元测试
|
|__README.md
3.6 通过npm安装和上传包
1)上传:
步骤:
1)创建好一个标准结构的包(注意:一定要满足包的要求),并且在package.json文件中设置好一些参数。
2)去npmjs注册一个账号(:jhon_j.登录之后点击图像会弹出下拉框,选择profile,会打开记录发布包的历史记录)
3)在要发布的文件夹下打开CMD,执行发布指令:
a)npm adduser:根据引导,依次输入用户名,密码,以及注册邮箱就行了
如果看到:Logged in as jhon_j on https://registry.npmjs.org/.说明登录成功
b)npm publish:看到+ [email protected]指令说明已经上传成功
2)撤销:
3)安装:
a. 本地安装
指令: npm install 包的本地路径
作用:解决无法发布到互联网上的包通过这个指令在公司内部自己使用
b. 联网安装
指令: npm install 包名
i.本项目安装:
npm install 包名
ii.全局包安装:
npm install 包名 -g
小技巧:由于npm是国外网站,在安装的时候速度可能比较慢。解决办法一:下载一个nrm,通过nrm将npm的登录从国外移动到国内,使用nrm use cnpm指令 解决办法二:安装一个cnpm工具,直接通过cnpm来安装
一般哪些包要被全局安装,哪些包要项目安装在npm中的README.md中有介绍,全局包的安装本质上将文件放到了当前使用的nodejs的目录下面
总结:在整个nodejs环境中(不管是什么项目)你都希望用到这个包,就需要安装一个全局包,但是如果只有本项目用到,安装一个本项目包
3.7 npm其它的常用指令
npm adduser :会引导输入用户名,密码以及注册邮箱(如果登录成功会显示:Logged in as jhon_j on https://registry.npmjs.org/.)
npm publish:发布包
npm uppublish 包名@版本号:撤销已经发布的包
npm install <name>安装nodejs的依赖包
例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本,如npm install [email protected]
npm install <name> -g 将包安装到全局环境中
但是代码中,直接通过require()的方式是没有办法调用全局安装的包的。全局的安装是供命令行使用的,就好像全局安装了vmarket后,就可以在命令行中直接运行vm命令
npm install <name> --save 安装的同时,将信息写入package.json中
项目路径中如果有package.json文件时,直接使用npm install方法就可以根据dependencies配置安装所有的依赖包
这样代码提交到github时,就不用提交node_modules这个文件夹了。
npm init 会引导你创建一个package.json文件,包括名称、版本、作者这些信息等
npm remove <name>移除
npm update <name>更新
npm ls 列出当前安装的了所有包
npm root 查看当前包的安装路径
npm root -g 查看全局的包的安装路径
npm help 帮助,如果要单独查看install命令的帮助,可以使用的npm help install
3.8 require加载规则的总结
1)require无论是核心模块还是文件模块都优先从缓存加载(可以解决一个文件多次引用一个文件模块而反复加载的问题)
2)在window中加载一个文件模块要使用./或者../开头(如果不加后缀,nodejs会当作用核心模块或者是包来解析)
3)在mac和linux中以/加载是加载一个绝对路径的文件模块,而在window下/表示当前require函数所在文件所在的目录的盘符(比如:c盘,没有意义)
4)一个文件模块可以不写扩展名,require()会自动依次按照.js .node .json的顺序进行补齐后加载,如果三个扩展名都没有,则当做目录或者包来加载。如果目录或者包都没有,则报错。
所以如果不加后缀,将来如果一个文件返回的是json,那么它的加载性能会慢一点。
5)加载一个包
-依次按照module.paths数组中的路径,加载传入的包名,如果有,就加载出业;如果没有,报错
-包加载完毕以后,如果有package.json文件,就去找其中main属性对应的出口文件
-如果没有,就找默认文件index.js
3.9 调试nodejs
1)使用console.log()
使用麻烦,用了以后还要删除
2)nodejs的自带调试器
-node debug a.js
没有任何作用,一个玩具,将来有一天可以会变得强大的
3)使用visual stdio调试:
步骤:
a)安装vsCode,并且通过vscode打开要调试的文件所在的文件夹
b)点击F5,选择nodejs的打开方式,这时vsCode会打开一个lanuch.json,修改其中"program"属性,改为"${workspaceRoot}/文件名.js",
c)可以查看文件的五个全局对象以及添加监控文件中变量的值
4)使用webstorm调试