参考:https://lurongtao.gitee.io/felixbooks-gp19-node.js/

一、Node简介

1.1 Node是什么

Node.js®是基于 Chrome的V8 JavaScript 引擎构建的JavaScript运行环境、运行时(runtime)。

Node.js不是新语言,也不是一个框架或者一个库,而是一个软件。2009出现的。

Node.js是一个 JavaScript 运行环境 ,说白了,就是用来运行js的。

官网:https://nodejs.org/en/

中文官网:https://nodejs.org/zh-cn/

1.2. Node能做什么

Node 打破了过去 JavaScript 只能在浏览器中运行的局面。前后端编程环境统一,大大降低了前后端语言切换的代价。

  • Node.js 适合开发服务器端的中间层(BFF)
  • Node.js 适合用于开发前端方向的各种工具

以下是Node可以实现的工作:(仅作了解)

  • Web 服务器
  • 命令行工具
  • 网络爬虫
  • 桌面应用程序开发(Electron
  • app
  • 嵌入式
  • 游戏
  • ……

1.3. 安装Node

官网:https://nodejs.org/en/

中文官网:https://nodejs.org/zh-cn/

安装后,可打开终端如cmd,输入node -v 查看是否安装成功

二、Node.js 相关工具

2.1 nvm

我们知道,NodeJS有太多的版本了,切记,并不是新版本一出现,旧的版本就不去用了。

在不同的项目开发过程中,可能需要我们在电脑中同时存在多个不同版本的Node。
这时候就需要一个软件,来更好地管理这些不同版本地Node存在我们地电脑中,Nvm就是这样一个软件。

nvm (node.js version manager 的简写)翻译过来 nodejs 版本管理器。

2.1.1 安装Nvm

nvm下载链接 https://github.com/coreybutler/nvm-windows/releases

注意:如果电脑之前安装过nodejs,请先卸载nodejs后再进行安装。

检测nvm是不是安装成功了:

成功安装后,新开一个 cmd 窗口,输入 nvm -v 如果有信息,代表安装成功!

配置nvm:

复制下面两句话到nvm的安装目录的settings.txt的最后。
(目的是加快后面下载nodejs的速度)

  1. node_mirror: https://npm.taobao.org/mirrors/node/
  2. npm_mirror: https://npm.taobao.org/mirrors/npm/

2.1.2 nvm命令

  • nvm version: 查看 nvm 的版本
  • nvm list: 查看当前安装的 Node.js 所有版本 (常用)
  • nvm install 版本号 [架构]: 安装指定版本的 Node.js (常用)
  • nvm uninstall 版本号: 卸载指定版本的 Node.js
  • nvm use 版本号: 选择指定版本的 Node.js (常用)
  1. # 安装指定版本
  2. nvm install 10.15.0
  3. # 安装最新版本
  4. nvm install latest
  5. # 使用安装的这个版本10.15.0
  6. nvm use 10.15.0
  7. # 查看node版本
  8. node -v

2.2 npm

npm 全称为 Node Package Manager,是一个基于 Node.js 的包管理器,也是整个 Node.js 社区最流行、支持的第三方模块最多的包管理器。npm的初衷:JavaScript开发人员更容易分享和重用代码。

npm 全称为 Node Package Manager,是一个基于 Node.js 的包管理器,也是整个 Node.js 社区最流行、支持的第三方模块最多的包管理器。npm的初衷:JavaScript开发人员更容易分享和重用代码。

  1. nodejs = ECMAScript + 核心模块
  2. 自己遵循 commonjs 规范写出模块,如果写的是功能模块(日期处理datejs,数字处理numberjs)。如果可以把这些模块分享出来,以后谁要进行相关功能开发的时候,直接拿开发好的模块使用即可,没必要自己在开发。在互联网有一个网站专门收集这样的工具包。https://www.npmjs.cn/。
  3. 如果我们要使用这个网站里面的包,则我们需要使用一个功能,叫做 npm。

官网:https://www.npmjs.cn/

https://www.npmjs.com/

npm可以用来:

  • 允许用户获取第三方包并使用
  • 允许用户将自己编写的包或命令行程序进行发布分享

2.2.1 npm安装

npm不需要单独安装。在安装 Node 的时候,会连带一起安装npm

执行下面的命令可以用来查看本地安装的 npm 的版本号。

  1. npm -v

如果想升级 npm ,可以这样

  1. npm install npm --global(-g)
  1. 在nodejs安装的根目录下新建 node_cache 和 node_global 两个文件夹。
  2. 分别使用以下命令设置全局的安装包目录:
    npm config set prefix “D:\Program Files\nodejs\node_global”
    npm config set cache “D:\Program Files\nodejs\node_cache”
  3. 配置环境变量:
    打开计算机的环境变量,找到系统变量,新增一项 NODE_PATH,值为安装目录下的nodejs, D:\Program Files\nodejs\node_global\node_modules

2.2.2 npm常用命令

  1. npm help 查看所有命令
    npm help xxx 查看某条命令的详细帮助
  2. npm install (i) xxx 本地安装
    npm install (i) xxx -g 全局安装
  3. npm list (ls) -g 查看所有全局安装的模块信息,list 可以简写为 ls
    npm list (ls) —depth=0 xxx 查看某个安装的模块信息,第一层
  4. npm uninstall (uni) xxx 卸载模块
  5. npm update xxx 更新模块
  6. npm search xxx 搜索模块
  7. npm init 创建模块
  8. npm update 可以把当前目录下node_modules子目录里边的对应模块更新至最新版本
    npm update -g 全局更新
  9. npm root -g 查看全局包安装位置

npm 安装模块
npm init # npm 初始化当前目录
npm i # 安装所有依赖

  1. npm i express # 安装模块到默认dependencies
  2. npm i express -g # 会安装到配置的全局目录下
  3. npm i express -S # 安装包信息将加入到dependencies生产依赖
  4. npm i express -D # 安装包信息将加入到devDependencies开发依赖
  5. npm i jquery@1.8.3 # 安装jquery指定的1.8.3版本

npm 卸载模块

  1. npm uninstall express # 卸载模块,但不卸载模块留在package.json中的对应信息
  2. npm uninstall express -g # 卸载全局模块
  3. npm uninstall express --save # 卸载模块,同时卸载留在package.json中dependencies下的信息
  4. npm uninstall express --save-dev # 卸载模块,同时卸载留在package.json中devDependencies下的信息

npm 更新模块

  1. npm update jquery # 更新最新版本的jquery
  2. npm update jquery@2.1.0 # 更新到指定版本号的jquery
  3. npm install jquery@latest # 可以直接更新到最后一个新版本

npm 查看命令

  1. npm root # 查看项目中模块所在的目录
  2. npm root -g # 查看全局安装的模块所在目录
  3. npm list 或者 npm ls # 查看本地已安装模块的清单列表
  4. npm view jquery dependencies # 查看某个包对于各种包的依赖关系
  5. npm view jquery version # 查看jquery最新的版本号
  6. npm view jquery versions # 查看所有jquery历史版本号(很实用)
  7. npm view jquery # 查看最新的jquery版本的信息
  8. npm info jquery # 查看jquery的详细信息,等同于上面的npm view jquery
  9. npm list jquery npm ls jquery # 查看本地已安装的jquery的详细信息
  10. npm view jquery repository.url # 查看jquery包的来源地址

npm 其他命令

  1. npm cache clean --force # 清除npm的缓存
  2. npm prune # 清除项目中没有被使用的包
  3. npm outdated --long (-l) # 检查模块是否已经过时
  4. npm repo jquery # 会打开默认浏览器跳转到github中jquery的页面
  5. npm docs jquery # 会打开默认浏览器跳转到github中jquery的README.MD文件信息
  6. npm home jquery # 会打开默认浏览器跳转到github中jquery的主页

npm dedupe
命令用于删除重复的依赖项。它通过删除重复的包并在多个依赖包之间有效地共享公共依赖项来简化整体结构。它会产生一个扁平的和去重的树。
npm dedupenpm ddp
npm audit
检查项目依赖项是否存在漏洞。它可以看出有风险的 package、依赖库的依赖链、风险原因及其解决方案。
npm audit

  • 如果发现存在漏洞,我们可以使用 npm audit fix,它将自动安装所有易受攻击依赖包的修补版本(如果可用)。
    npm audit fix npm audit fix --force
  • 更好的做法是使用 synk,它是一个高级版的 npm audit,可自动修复,且支持 CI/CD 集成与多种语言。
    npx snyk

npm doctor
命令可以在我们的环境中运行多项检查。
npm doctor

2.2.3 package.json和包的安装

  1. # package.json初始化
  2. npm init -y
  3. # 安装包到生产环境(用户需要安装的),默认就是这个
  4. npm install jquery --save(-S)
  5. # 安装包到开发环境(用户可以不安装的)
  6. npm install lodash --save-dev(-D)
  7. # 查看包的所有版本
  8. npm view jquery versions
  9. # 安装包的指定版本
  10. npm install jquery@2.2.2
  11. # 卸载包
  12. npm uninstall jquery
  13. # 查看所有本地包的最新情况
  14. npm outdated
  15. # ~2.0.0表示patch, ^2.0.0表示minor * 表示xx最新版本
  16. # 更新包
  17. npm update
  18. # 清除缓存,--force 是强制执行
  19. npm cache clean --force
  20. # 查看全局包安装位置
  21. npm root -g

2.2.4 package.json

  1. {
  2. "name": "liwker-test", // 包名
  3. "version": "1.0.1", // 版本号
  4. "description": "", // 描述
  5. "main": "index.js", // 入口文件
  6. "scripts": { // 脚本
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "keywords": [],
  10. "author": "Liwker",
  11. "license": "ISC",
  12. "dependencies": {
  13. "lodash": "^4.17.21"
  14. }
  15. }

2.2.5 npm 包版本符号

  • ^ : 锁定major,第一个数
  • ~ : 锁定minor,第二个数
  • 空 : 锁定patch,第三个数(偶数为稳定,奇数为不稳定)
  • *: 最新版本
  1. "dependencies": {
  2. "jquery": "^3.6.0"
  3. }

2.2.6 上传自己的包

  1. 编写模块,保存为 index.js
    1. exports.sayHello = function(){
    2. return 'Hello World';
    3. }
  1. 注册npm仓库账号(https://www.npmjs.com/) ```bash npm adduser

// 不是第一次登录 npm login

  1. 3. 上传包
  2. ```bash
  3. npm pubish

可以失败的原因:

  1. 403 Forbidden
    一般是源的问题,淘宝源是不能登录的 ```bash

    查看npm源

    npm config get registry

切换npm源方法一

npm config set registry http://registry.npmjs.org

切换npm源方法二,需要安装nrm

nrm use npm

  1. 2. Err 400<br />我就踩了这个坑<br />一是在注册账号后需要邮箱的验证<br />二是package.json中的name值也就是包的名字必须是**全网唯一的**<br />三是包的名字**不能有大写字母**
  2. 上传好了后,可以在[https://www.npmjs.com/](https://www.npmjs.com/)搜到自己的包<br />就可以 npm install 自己的包
  3. 4. 卸载包
  4. ```bash
  5. # 查看当前项目引用了哪些包 :
  6. npm ls
  7. # 卸载包:
  8. npm unpublish --force

2.2.7 npm脚本

Node 开发离不开 npm,而脚本功能是 npm 最强大、最常用的功能之一。

1 什么是 npm 脚本?

npm 允许在 package.json 文件里面,使用 scripts 字段定义脚本命令。

  1. {
  2. // ...
  3. "scripts": {
  4. "build": "node build.js"
  5. }
  6. }

2 执行顺序

如果 npm 脚本里面需要执行多个任务,那么需要明确它们的执行顺序。

  1. "scripts": {
  2. "script1": "node script1.js",
  3. "script2": "node script2.js"
  4. }

如果是并行执行(即同时的并行执行),可以使用 & 符号。

  1. npm run script1 & npm run script2

如果是继发(串行)执行(即只有前一个任务成功,才执行下一个任务),可以使用 && 符号。

  1. npm run script1 && npm run script2

多脚也可以写在json里

  1. // 并行执行
  2. "scripts": {
  3. "start": "node script1.js & node script2.js"
  4. }
  5. // 串行执行
  6. "scripts": {
  7. "start": "node script1.js && node script2.js"
  8. }

3 简写形式

常用的 npm 脚本简写形式。

  1. npm start npm run start
  2. npm test npm run test

4 变量

npm 脚本有一个非常强大的功能,就是可以使用 npm 的内部变量。
首先,通过 npm_package_ 前缀,npm 脚本可以拿到 package.json 里面的字段。比如,下面是一个 package.json。

注意:一定要在 npm 脚本中运行(如:npm run view)才可以,直接在命令行中运行JS(如:node view.js)是拿不到值的

  1. {
  2. "name": "foo",
  3. "version": "1.2.5",
  4. "scripts": {
  5. "view": "node view.js"
  6. }
  7. }

那么,变量 npm_package_name 返回 foo,变量 npm_package_version 返回 1.2.5。

  1. // view.js
  2. console.log(process.env.npm_package_name); // foo
  3. console.log(process.env.npm_package_version); // 1.2.5

上面代码中,我们通过环境变量 process.env 对象,拿到 package.json 的字段值。如果是 Bash 脚本,可以用$npm_package_name 和 $npm_package_version 取到这两个值。

2.2.8 npm 安装 git 上发布的包

  1. # 这样适合安装公司内部的git服务器上的项目
  2. npm install git+https://git@github.com:***.git
  3. # 或者以ssh的方式
  4. npm install git+ssh://git@github.com:***.git

2.2.9 cross-env 使用

  1. cross-envs 是什么

运行跨平台设置和使用环境变量的脚本

  1. 出现原因

当您使用 NODE_ENV=production, 来设置环境变量时,大多数 Windows 命令提示将会阻塞(报错)。(异常是Windows上的Bash,它使用本机Bash。)换言之,Windows 不支持 NODE_ENV=production 的设置方式。

  1. 解决

cross-env 使得您可以使用单个命令,而不必担心为平台正确设置或使用环境变量。这个迷你的包(cross-env)能够提供一个设置环境变量的 scripts,让你能够以 Unix 方式设置环境变量,然后在 Windows 上也能兼容运行。

  1. 安装

npm install cross-env -D

  1. 使用
  1. {
  2. "scripts": {
  3. "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"
  4. }
  5. }

NODE_ENV环境变量将由 cross-env 设置 打印 process.env.NODE_ENV === ‘production’

2.3. nrm

NRM(npm registry manager) npm源管理

2.3.1 手工切换源

1 查看当前源

  1. npm config get registry

2 切换淘宝源

  1. npm config set registry https://registry.npm.taobao.org

2.3.2 NRM 管理源

NRM (npm registry manager)是npm的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速地在 npm 源间切换。

1 安装 nrm

在命令行执行命令,npm install -g nrm,全局安装nrm。

2 使用 nrm

执行命令 nrm ls 查看可选的源。 其中,带*的是当前使用的源,上面的输出表明当前源是官方源。

  1. 如果安装成功,执行不起,显示:path.js:39 throw new ERR_INVALID_ARG_TYPE(‘path‘, string‘, path)
  2. 解决问题:
  3. 1、运行,npm ls命令,找到npm的安装路径。
  4. 2、在资源管理器中,找到nrm的安装目录,一般是:C:\Users\Administrator\AppData\Roaming\npm\node_modules\nrm
  5. 3、在目录下找到cli.js文件。
  6. 4、用文本编辑器打开它。修改里面的一行代码:
  7. 原来代码是:const NRMRC = path.join(process.env.HOME, '.nrmrc');
  8. 修改为:const NRMRC = path.join(process.env.USERPROFILE, '.nrmrc');
  9. 5、重新运行,nrm ls成功。

3 切换 nrm

如果要切换到taobao源,执行命令 nrm use taobao

4 测试速度

你还可以通过 nrm test 测试相应源的响应时间。

  1. nrm test

2.4 npx

npx: npm package extention

npm 从5.2版开始,增加了 npx 命令。它有很多用处,本文介绍该命令的主要使用场景。

Node 自带 npm 模块,所以可以直接使用 npx 命令。万一不能用,就要手动安装一下。

  1. npm install -g npx

2.4.1 调用项目安装的模块

npx 想要解决的主要问题,就是调用项目内部安装的模块。比如,项目内部安装了Mocha。

  1. npm install -D mocha

一般来说,调用 Mocha ,只能在项目脚本和 package.json 的scripts字段里面,如果想在命令行下调用,必须像下面这样。

  1. # 项目的根目录下执行
  2. node-modules/.bin/mocha --version

npx 就是想解决这个问题,让项目内部安装的模块用起来更方便,只要像下面这样调用就行了。

  1. npx mocha --version

npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。

由于 npx 会检查环境变量$PATH,所以系统命令也可以调用。

  1. # 等同于 ls
  2. npx ls

注意,Bash 内置的命令不在$PATH里面,所以不能用。比如,cd是 Bash 命令,因此就不能用npx cd。

2.4.2 —no-install 参数和 —ignore-existing 参数

如果想让 npx 强制使用本地模块,不下载远程模块,可以使用--no-install参数。如果本地不存在该模块,就会报错。

  1. npx --no-install http-server

反过来,如果忽略本地的同名模块,强制安装使用远程模块,可以使用--ignore-existing参数。比如,本地已经安装了http-server,但还是想使用远程模块,就用这个参数。

  1. npx --ignore-existing http-server

2.5 noddmon

在使用node的一些比如http模块写web服务器,但是每次改写一点代码都需要重启服务器,开发不是很方便。nodemon可以监听代码的改动自动更新,不需要重启服务器程序就可以看效果。

文档:https://www.npmjs.com/package/nodemon

下载:

  1. npm install -g nodemon

2.6 相关文档

三、模块/包 与CommonJS

Node.js 有三类模块,即内置的模块、第三方的模块、自定义的模块。

3. 1 内置的模块

Node.js 内置模块又叫核心模块,Node.js安装完成可直接使用。如:

  1. const path = require('path')
  2. var extname = path.extname('index.html')
  3. console.log(extname)

3.2 第三方的Node.js模块

第三方的Node.js模块指的是为了实现某些功能,发布的npmjs.org上的模块,按照一定的开源协议供社群使用。如:

  1. npm install chalk
  2. const chalk = require('chalk')
  3. console.log(chalk.blue('Hello world!'))

3.3 自定义的Node.js模块

自定义的Node.js模块,也叫文件模块,是我们自己写的供自己使用的模块。同时,这类模块发布到npmjs.org上就成了开源的第三方模块。

自定义模块是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、速度相比核心模块稍微慢一些,但是用的非常多。

3.3.1 模块定义、接口暴露和引用接口

我们可以把公共的功能 抽离成为一个单独的 js 文件 作为一个模块,默认情况下面这个模块里面的方法或者属性,外面是没法访问的。如果要让外部可以访问模块里面的方法或者属性,就必须在模块里面通过 exports 或者 module.exports 暴露属性或者方法。

m1.js:

  1. const name = 'Liwker'
  2. const sayName = () => {
  3. console.log(name)
  4. }
  5. console.log('module 1')
  6. // 接口暴露方法一:
  7. module.exports = {
  8. say: sayName
  9. }
  10. // 接口暴露方法二:
  11. exports.say = sayName
  12. // exports是对 module.exports 的引用
  13. // 相当于 exports = module.exports
  14. // 所以下面这种是错误的!
  15. /*
  16. exports = {
  17. say: sayName
  18. }
  19. */

main.js:

  1. // 引用模块
  2. const m1 = require('./m1.')
  3. m1.say()

四、常用内置模块

三、 全局对象 global

JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可以在程序的任何地方访问,即全局变量。

在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。

后面看到所有的全局变量,例如 console,setTimeout 和 process 是 global 变量的成员。我们甚至可以向全局变量添加成员,使其在任何地方都可用。

  1. // 1. nodejs 里面声明的变量,并不会被挂载带 global 全局对象
  2. let b = 20;
  3. console.log(global.b); //undefined
  4. // 2. 可以向global添加成员,使其在任何地方都可用
  5. global.a = 10;
  6. console.log(a); //10
  7. // 3. 在nodejs执行js文件的过程中,里面也存在 this ,但是这个 this 和 global 并不是相等。
  8. console.log(global === this); //false
  9. // 实际上,在 nodejs 里面的this代表的当前这个 js模块(暂且认为 this 代表当前这个js文件)

process 对象

  1. console.log(process.argv);
  2. // 返回一个数组,前两个值是 node 命令所在位置,被执行 JS 文件的路径,若你执行命令时还有带有参数,依次会填充到此数组中也打印出来。(使用 nodejs 开发命令行的应用,需要获取 命令行的参数,才用得上)
  3. console.log(process.argv.slice(2));
  4. node process.js argv1 argv2
  5. // 打印命令里的后两个参数 [argv1, argv2]
  6. console.log(process.arch); // 打印系统位数 x64

5.6 yarn

Yarn 是于 2016 年 10 月 由 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,旨在取代 npm 这种包管理工具。

官网:
https://yarnpkg.com/en/docs

中文参考链接:
https://yarn.bootcss.com/

特点

  • 速度超快
    yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。
  • 超级安全
    在执行代码之前,yarn 会通过算法校验每个安装包的完整性。
  • 超级可靠
    使用详细、简洁的锁文件格式和明确的安装算法,yarn 能够保证在不同系统上无差异的工作。

安装:

管理员模式运行cmd :npm install -g yarn

常用命令

npm yarn
npm init -y yarn init -y
npm install 包名 [—save] yarn add 包名
npm uninstall react [—save] yarn remove [react]
npm install react —save-dev yarn add react —dev
npm update [—save] yarn upgrade
npm install -g @vue/cli yarn global add @vue/cli

yarn 全局安装后,命令不生效

背景:

  1. 执行 yarn global add @vue/cli 后,重启 bash......, vue 命令依然不生效
  2. 而 npm 全局安装(npm install -g @vue/cli)后,命令生效

解决办法:

1.执行如下命令,得出 yarn 全局安装的命令所处的安装目录

  1. yarn global bin

2.复制安装目录至电脑的环境变量中
S:Node.js入门 - 图1

修改yarn全局安装路径

  1. 改变 yarn 全局安装位置
  1. #1.改变 yarn 全局安装位置
  2. yarn config set global-folder "你的磁盘路径"
  3. #这里是我的路径
  4. yarn config set global-folder "D:\tools\Yarn\Data"
  1. 改变 yarn 缓存位置
  1. #2. 改变 yarn 缓存位置
  2. yarn config set cache-folder "你的磁盘路径"
  3. #这里是我的路径
  4. yarn config set cache-folder "D:\tools\Yarn\Cache"
  1. 改变yarn bin位置
    在我们使用全局安装包的时候,会在 “D:\tools\Yarn\Data” 下 生成 node_modules\.bin 目录
  1. #3.改变 yarn bin位置
  2. yarn config set prefix "你的磁盘路径"
  3. #这里是我的路径
  4. yarn config set prefix "D:\tools\Yarn"
  5. #安装全局包后,会在设置的路径下生成一个bin文件夹

我们需要将 D:\tools\Yarn\bin 整个目录 添加到系统环境变量中去,否则通过yarn 添加的全局包 在cmd 中是找不到的。

检查当前yarn 的 bin的 位置

  1. yarn global bin
  2. #如果按上面设置好了的就会是 "D:\tools\Yarn\bin"

检查当前 yarn 的 全局安装位置

  1. yarn global dir
  2. #如果按上面设置好了的就会是 "D:\tools\Yarn\Data"

四、模块 使用

4.1 模块规范定义

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

模块化的优势有以下几点:

  1. 防止命名冲突
  2. 代码复用
  3. 高维护性

一个js文件就是一个模块,模块的作用域是私有的,内部定义的变量或者函数,只在当前的文件(模块)可以使用

如果别人需要使用我们模块里面的东西,那么有两点要做(以CommonJS 的 Modules 规范: Node.js为例)

  1. 自己编写的模块,由于模块作用域是私有的,默认情况下,外部是没办法使用的;如果希望别人可以使用,则需要导出 exports 或者 module.exports。 导出的时候,以对象的方式进行导出
  2. 别人要使用某个模块,则需要先引入该模块,使用 require 引入,引入后需要使用一个变量来接收导入的对象。

对书写格式和交互规则的详细描述,就是模块定义规范(Module Definition Specification):

  • AMD 规范: Require.js
  • CMD 规范: Sea.js
  • CommonJS 的 Modules 规范: NodeJs
  • ES6 模块化规范 import … from …

4.2 NodeJs 模块化使用

导出数据方式一:

  1. exports.num = num;
  2. exports.sum = sum;
  3. exports.Animal = Animal;

导出数据方式二:

  1. // 通过module.exports 等于一个对象,来导出数据
  2. // 对象可采用es6简化对象的写法
  3. module.exports = {
  4. num,
  5. sum,
  6. Animal
  7. };

导入数据:

  1. // 注意1: 如果要使用某个模块里面的数据,则需要使用 require 关键字进行导入。
  2. // 注意2:在导入用户自己开发的模块的时候,需要加上路径(1. 相对路径(多) 2. 绝对路径) 注意: ./ 必须写上
  3. // 注意3:模块文件的扩展名(后缀名)可以写,也可以不写
  4. // 注意4:导出的模块一般需要使用一个变量来接收,一般把接收的量定义为常量
  5. // 注意5: 定义常量的名称和文件的名称保持一致(这个不是必须,大家都这么做)
  6. const m1 = require("./modules/m1.js");

完整代码:

  1. // 导出,m1.js中:
  2. let num = 10;
  3. function sum(a, b) {
  4. return a+b
  5. }
  6. class Animal{
  7. constructor(){
  8. this.age=0
  9. }
  10. }
  11. // 导出数据方式1:
  12. // exports.num = num;
  13. // exports.sum = sum;
  14. // exports.Animal = Animal;
  15. // 导出数据方式2:
  16. // 通过module.exports 等于一个对象,来导出数据
  17. // 对象可采用es6简化对象的写法
  18. module.exports = {
  19. num,
  20. sum,
  21. Animal
  22. };
  1. //导入,使用模块
  2. const m1 = require("./modules/m1.js");
  3. console.log(m1); //{ num: 10, sum: [Function: sum], Animal: [Function: Animal] }
  4. console.log(m1.sum(10, 20)); // 30
  5. const obj = new m1.Animal();
  6. console.log(obj.age); // 0

4.3 模块里面this的指向问题

exports 实际上是 module.exports 的引用

在 nodejs 里面的 this 代表当前的这个模块,也就是 exports 对象(在文件里,不是交互终端)

  1. console.log(exports); //{}
  2. console.log(module.exports); //{}
  3. console.log(exports === module.exports); //true exports实际上是module.exports的引用
  4. console.log('this', this); // this {}
  5. console.log(this === exports);// true
  6. // 在 nodejs 里面的 this 代表当前的这个模块,也就是 exports 对象 并且,交互模式下,没有exports这个对象
  7. console.log(global === this ); //false this不指向全局对象

4.4 nodejs常用内置模块

一般项目中模块分为3种:

  1. node.js 内置模块
  2. 自己书写的模块
  3. 第三方模块(使用一个专门的工具npm进行统一管理)

常用的内置模块如下:

  • fs :文件操作
  • http :网络操作
  • path :路径操作
  • querystring :查询参数解析
  • url :url 解析
  1. const fs = require("fs");
  2. const http = require('http');
  3. const path = require('path');
  4. const querystring = require('querystring');
  5. const url = require('url');

nodejs内置模块的文档网址:http://nodejs.cn/api/

4.5 path 内置模块

path 模块,处理与路径相关

  1. // 导入模块
  2. const path = require("path");
  3. console.log(__dirname); // 当前执行的文件绝对路径,不包含文件名
  4. console.log(__filename); // 当前执行的文件绝对路径,包含文件名和后缀名
  5. let extname = path.extname( __filename ); // 获取扩展名(后缀名)
  6. console.log(extname);
  7. let baseName = path.basename( __filename ); // 获取文件名(包含后缀名)
  8. console.log(baseName);
  9. let dirname = path.dirname(__filename); //获取目录(路径)
  10. console.log(dirname);
  11. let parse = path.parse(__filename); //获取路径字符串的对象
  12. console.log(parse);
  13. //路径的拼接操作 join
  14. // join 默认相对路径的拼接 ,以当前操作系统路径分割符进行拼接
  15. let fullPath1 = path.join('path.js');
  16. // fullPath1 = path.join(__dirname,'path.js'); //带目录
  17. // fullPath1 = path.join(__dirname,'a','path.js'); //带多级目录
  18. console.log(fullPath1);

4.6 Buffer 数据类型

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。但在处理像文件流时(文件读写操作),必须使用到二进制数据。因此在 Node.js 中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。说白了,Buffer 类似于一个整数数组。

创建buffer对象 :

  1. let buf1 = Buffer.from([97, 98, 99]); //根据一个数组创建 Buffer 对象
  2. console.log(buf1); //<Buffer 61 62 63> 以16进制存在buffer对象中
  3. console.log(buf1.toString()); // abc
  4. let buf2 = Buffer.from("nodejs"); //根据一个字符串创建 Buffer 对象
  5. console.log(buf2);
  6. console.log(buf2.toString()); // nodejs
  7. let buf3 = Buffer.alloc(10); // 创建了可以存放10个字符的buffer对象
  8. buf3.write("abc"); //按照ASCII表的值,转16进制,存在buffer中
  9. console.log(buf3);
  10. console.log(buf3.toString()); // abc
  11. // 总结: 以后看到 <Buffer ..... > 需要 toString() 才能看到里面的真实数据

4.7 fs 文件系统模块

Node.js 的 API 内置的有两个模块: path 和 fs ,我们使用 JavaScript 代码编写程序运行在 Node.js 环境中就可以操作文件

4.7.1 同步读取文件信息

同步读取:读取的时候,要等文件读取完毕后,才会执行后面的代码 (sync 同步)

  1. // 准备工作
  2. const fs = require("fs");
  3. const path = require("path");
  4. let pathName = path.join(__dirname, 'hello.txt');
  5. //同步读取文件
  6. const content = fs.readFileSync(pathName);
  7. // console.log(content);
  8. // 转换
  9. console.log(content.toString());
  10. const content = fs.readFileSync(pathName, "utf-8");
  11. console.log(content);

4.7.2 异步读取文件信息

不用等待文件读取完毕就会执行后面的代码。所谓异步,就是当前回调函数不用等执行完就可以执行后面的语句。

思考:如何读到后面的数据

答:在读取文件的时候,传递一个回调函数callback,当读取完毕后,回调函数执行,读取后面的数据

  1. const fs = require("fs");
  2. const path = require("path");
  3. let pathName = path.join(__dirname, "hello2.txt");
  4. // console.log(file);
  5. //参数1 要读取的文件
  6. //参数2 设置读取到内容的编码,设置后读到的内容为字符串,如果不传则读到的数据为 buffer
  7. //参数3 回调函数,读取完文件后执行的代码
  8. fs.readFile(pathName, "utf-8",(error, data)=>{
  9. // console.log(error);
  10. // console.log(data);
  11. if(error){
  12. console.log(error);
  13. return;
  14. }
  15. console.log(data);
  16. });

4.7.3 异步写入

  1. const fs = require("fs");
  2. const path = require("path");
  3. let pathName = path.join(__dirname, "hello.txt");
  4. fs.writeFile(pathName, "hello_write111", "utf-8",(error)=>{
  5. console.log("error");
  6. console.log("写完啦");
  7. });
  8. console.log("end");

4.7.4 几个常见方法

  1. const fs = require("fs");
  2. fs.renameSync(旧文件名, 新文件名); //修改文件名
  3. fs.readdirSync(__dirname); //读取当前路径下的文件名列表
  4. let str = "hello";
  5. str.endsWith("lo"); //true 是否以某字符串结尾
  6. str.startsWith("hh"); //false 是否以某字符串开头
  7. str.substring(2,4) //ll 左闭右开区间
  8. str.substring(2) //llo 从下标为2取到结束

4.7.5 小案例

需求:把当前文件夹的js文件的名字都添加前缀 [Liwker]

  1. const fs = require("fs");
  2. let nameList = fs.readdirSync(__dirname);
  3. nameList.forEach(currFileName => {
  4. if(currFileName.endsWith(".js")){
  5. fs.renameSync(currFileName, `[Liwker]${currFileName}`)
  6. }
  7. });

需求:把当前文件夹的名字都删除前缀 [Liwker]

  1. const fs = require("fs");
  2. let nameList = fs.readdirSync(__dirname);
  3. let str1 = "[Liwker]"
  4. nameList.forEach(currFileName => {
  5. if(currFileName.startsWith(str1)){
  6. fs.renameSync(currFileName, currFileName.substring(str1.length))
  7. }
  8. });

4.8 http 模块

4.8.1 http核心模块的使用

四个步骤:

  1. 导入http模块
  2. 定义服务器程序端口
  3. 创建服务器对象
  4. 调用服务器的监听方法,让服务器监听浏览器请求
  1. // 1、导入http模块
  2. const http = require("http");
  3. // 2、定义服务器程序端口
  4. const port = 8080;// 端口号:1-65535 (有些服务已经有一些默认端口 apache nginx 80 web 服务。 MySQL:3306 MongoDB:27017)
  5. // 注意:一个端口只能被一个服务进行使用,如果这个端口被某个服务使用,其他的服务不能在使用该端口的。这个时候出现端口冲突。如何解决?答:换个端口
  6. // 建议:1-1024 端口(有些系统服务会使用这个范围的端口),不建议程序员自己使用。一般都使用 1024 以后的端口。
  7. // 3、创建服务器对象
  8. const server = http.createServer((request, response)=>{
  9. response.write("hello nodejs"); // 书写响应体内容
  10. response.end() //发生响应到浏览器 当我们修改代码后,需要重新执行该文件,重启服务
  11. });
  12. // 4、调用服务器的监听方法,让服务器监听浏览器请求
  13. server.listen(port,(error)=>{
  14. console.log(error);
  15. console.log(`server is running at port ${port}`);
  16. });
  1. //如果需要解决中文乱码,需遵循http协议:
  2. response.setHeader("Content-type","text/html;charset=utf-8");

4.8.2 获取请求的一些信息

  1. const http = require("http");
  2. const url = require("url");
  3. const server = http.createServer((request, response)=>{
  4. //如果需要解决中文乱码,需遵循http协议:
  5. response.setHeader("Content-type","text/html;charset=utf-8");
  6. console.log("------------------------------");
  7. // Get
  8. let requestUrl = request.url; // 获取本次请求的资源路径
  9. console.log(requestUrl);
  10. let method = request.method; // 获取本次请求的方式
  11. console.log(method);
  12. let obj = url.parse( requestUrl, true); // true解析成对象,false解析成字符串
  13. console.log(obj.query); // 获取get请求的查询字符串
  14. // localhost:8080?name=nodejs&age=11 get请求
  15. // Post
  16. //当存在 post 提交数据 data 事件立马执行,postData就是提交过来的数据对象
  17. request.on('data',(postData) => { // 获取post请求的请求参数
  18. console.log(postData.toString());
  19. });
  20. response.write("hello nodejs"); // 书写响应体内容
  21. response.end(); //发生响应到浏览器 当我们修改代码后,需要重新执行该文件,重启服务
  22. });

六、ES6模块

6.1 nodejs12版本以下是 不支持ES6模块化规范的解决方案

在项目目录下新建src文件夹,src文件夹下新建m1.js模块和app.js模块:

m1.js模块中到处数据:

  1. export let name = "nodejs";
  2. export let age = 11;

app.js中导入模块:

  1. import {name,age} from "./m1.js"

此时运行app.js会报错!!! SyntaxError: Unexpected token {

注意:nodejs 不支持 es6 模块化规范
可以把这个代码转换一下,然后把 es6 规范转换为 commonjs 规范
学语法,兼容性如何不用管,可以交给第三方的转换工具(babel-cli 和 browserify)实现

解决:

1、在项目文件夹下生成生成 package.json 文件

  1. yarn init -y 或者 npm init -y

2、安装第三方工具:

在任意目录下执行,全局安装babel-cli 和 browserify:

如果yarn没有安装成功,就用npm

  1. yarn global add babel-cli browserify 或者 npm install babel-cli browserify -g

在自己项目目录下执行:

  1. yarn add babel-preset-es2015 或者 npm install babel-preset-es2015 --save-dev

3、在项目根目录新建 .babelrc 文件 :

  1. {
  2. "presets": [
  3. "es2015"
  4. ]
  5. }

4、在项目目录下书写完代码后,执行:

  1. babel src -d lib
  2. // src(源文件夹) lib(目标文件夹)

(如果出现babel 不是内部或者外部命令,请按照第三点最后的yarn 全局安装后,命令不生效的解决办法)

5、运行lib下的app.js即可 node lib\app.js

(记得,修改代码需要执行babel src -d lib命令后,再运行lib下的app.js)

6.2 ES6模块化规范语法

导出数据方式一:

  1. //导出数据方式一:
  2. export let name = "nodejs";
  3. export let age = 11;

导出数据方式二:

  1. let name = "nodejs";
  2. let age = 11;
  3. export {name, age}

针对导出数据的前两种方式的导入数据:

  1. import {name,age} from "./m1.js"

导出数据方式三:

  1. // 默认导出只能写一次
  2. export default {name, age}

导入并使用数据:

  1. import m3 from "./m3"
  2. console.log(m3.name);
  3. console.log(m3.age);

在es6中的默认导出的写法,允许和前面的导出方式一起写:

导出数据:

  1. let name = "nodejs";
  2. let age = 11;
  3. export let email = "nodejs@163.com";
  4. // 默认导出只能写一次
  5. export default {name, age}

导入并使用数据:

  1. import m3, {email} from "./m3"
  2. console.log(m3.name);
  3. console.log(m3.age);
  4. console.log(email);