Node 开发概述

1. Node开发概述

1.1 为什么要学习服务器端开发基础

  • 能够和后端程序员更加紧密的配合
  • 网站业务逻辑前置,学习前端技术需要后端技术支持(Ajax)
  • 扩宽知识视野,能够站在更高的角度审视整个项目

1.2 服务器端开发要做的事情

  • 实现网站的业务逻辑 比如登录
  • 数据的增删改查 比如电商平台的购物车

1.3 为什么选择Node

  • 使用JavaScript语法开发后端应用
  • 一些公司要求前端工程师掌握Node开发
  • 生态系统活跃,有大量开源库可以使用
  • 前端开发工具大多基于Node开发

1.4 Node是什么

Node是一个基于Chrome V8引擎的JavaScript代码运行环境

Chrome V8引擎: JavaScript代码执行引擎。

1.5 Node.js 组成

  • JavaScript由三部分组成,ECMAScript DOM BOM 其中ECMAScript是核心 DOM BOM是浏览器这个运行环境为JavaScript这个语言提供的api
  • nodejs是由ECMAScript及node环境提供的一些附加api组成

1.6 Node.js 模块化开发

JavaScript开发的弊端:文件依赖和命名冲突

所以需要模块化,需要的开放出去 不需要的封装掉

软件中的模块化开发:一个功能就是一个模块,多个模块可以组成完整应用,抽离一个模块不会影响其他功能的运行。

比如:

app.js

user.js post.js goods.js

addUser.js deleteUser.js findGood.js addGood.js

node.js 规定一个js文件就是一个模块,模块内部定义的变量和函数默认情况下载外部无法得到

exports对象进行成员导出,使用require方法导入其他模块

exports.version = version;
exports.sayhi = sayhi;

// b.js
let a = require('./b.js');
console.log(a.version);
module.exports.version = version;

底层理解 exports 和 module.exports 都是对象,指向同一地址空间,如果不同的话,以module.export为准

1.7 系统模块fs 文件操作

const fs = require('fs');

读取文件内容:

fs.readFile('文件路径/文件名称'[,'文件编码'],callback);
fs.readFile('../css/main.css','utf-8',(err,doc) => {
    // 如果文件读取发生错误,参数err的值为错误对象,否则err为null
    // doc参数为文件内容
    if(err ==null){
        
    }
})

node 中所有的回调函数第一个参数都是error。错误优先的回调函数

写入文件:

fs.writeFile('文件路径/文件名称','数据',callback)

例如项目中写入错误日志。

const content = '';
fs.writeFile('../index.html',content,err => {
    if(err != null){
        console.log(err);
        return;
    }
    console.log('文件写入成功');
})

系统模块 path 路径操作:

为什么要进行路径拼接??

  • 不同操作系统的路径分隔符不统一
  • Windows是 \ /
  • Linux是/
  • Linux系统通常被用作网站的服务器

比如 图片上传功能 存在服务器的某一个硬盘文件夹

路径拼接语法:

path.join('路径','路径',...)

相对路径 vs 绝对路径:

  • 大多数情况下使用绝对路径,写相对路径不安全
  • 因为执行的时候一般是当前工作目录,所以相对路径不安全
  • 使用__dirname(两个下划线)获取当前目录所在绝对路径。
  • require时相对路径是相对当前目录,所以require可以使用相对路径

1.8 第三方模块

包,第三方模块,多个文件组成并在一个文件夹中

存在形式

  • js文件,提高项目具体功能API接口
  • 命令行工具存在

获取第三方模块:

npmjs.com 第三方模块的存储和分发仓库

npm (node package manager): node 第三方模块管理工具

  • npm install
  • npm uninstall

本地安装和全局安装

  • 命令行工具:全局安装
  • 库文件:本地安装

1.9 第三方模块 nodemon

在nodejs中每次修改文件都要在命令行中重新执行该文件,非常繁琐

  1. npm install nodemon -g 下载 全局安装
  2. 在命令行工具中使用nodemon命令代替node执行
  3. 用 ctr+C退出

1.10 第三方模块 nrm

nrm (npm registry manager): npm下载地址切换工具

  1. npm install nrm -g
  2. 查询 nrm ls
  3. 切换 nrm use 下载地址名称

1.11 第三方模块 Gulp

基于node平台开发的前端构建工具

将机械化操作编写成任务,想要执行机械化操作时执行一个命令行命令任务就能自动执行了

用机器代替手工,提高开发效率

  1. npm install gulp 下载gulp库文件
  2. 在项目根目录下建立 gulpfile.js
  3. 重构项目的文件夹结构 src目录放源代码 dist目录放构建后文件
  4. 在gulpfile.js中编写任务
  5. 命令行工具中执行任务

1.12 package.json文件

package.json的作用:

项目描述文件,记录了当前项目信息,例如项目名称、版本、作者,github地址,当前项目依赖了哪些第三方模块等。使用npm init -y命令生成(y是全部默认值 (yes))

{
  "name": "test",
  "version": "1.0.0",
  "description": "test main是项目主入口文件 scripts是命令的别名 ISC是开发源代码协议",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"nodemon app.js"
  },
  "keywords": [],
  "author": "Jiaqi Guo",
  "license": "ISC"
}

在终端写npm run build可以执行nodemon app.js命令

项目依赖——线上线下都需要

开发依赖——开发阶段需要依赖,线上运营阶段不需要依赖的第三方包 使用npm install xxx --save -dev将包添加在package.json文件中的DevDependencies字段中, 比如 gulp

npm install 下载所有的依赖

npm install --production 服务器环境 下载项目依赖

package-lock.json

记录模块之间的依赖关系

1.13 Node.js 中模块的加载机制

模块查找规则:

require('./find.js');
require('./find');
  1. require方法根据模块路径查找模块,如果是完整路径,直接引入模块
  2. 如果模块后缀省略,先找同名js文件再找同名js文件夹
  3. 如果找到了同名文件夹,找文件夹中的index.js
  4. 如果文件夹中没有index.js 就找当前文件夹package.js中找main选项的入口文件
  5. 如果入口文件不存在或者没有则报错,模块没有被找到。

模块没有路径也没有后缀

  1. 系统模块
  2. 去node_modules文件夹中
  3. 首先看是否有改名字的js文件
  4. 文件夹
  5. 如果是文件夹看是否有index.js
  6. 如果没有index.js看文件夹中package.json的main选项确定模块入口文件
  7. 否则找不到报错

2.Node运行环境搭建

2.1 Node.js运行环境安装

官网:https://nodejs.org/en/
中文网:http://nodejs.cn/

关于版本:

LTS = Long Term Support 长期支持版 稳定版

Current 拥有最新特性 实验版

运行中输入:powershell  打开命令行工具

再输入:node -v  可以查看安装版本

2.2 Node环境安装失败的解决办法

1.错误代号2502、2503

失败原因:系统帐户权限不足。

解决办法:
1)以管理员身份运行 powershell 命令行工具
2)输入运行安装包命令 msiexec /package node安装包位置。比如:msiexec /package E:\tools\node-v12.16.2-x64.msi

2.执行命令报错

失败原因:Node安装目录写入环境变量失败

解决办法:将Node安装目录添加到环境变量中

2.3 PATH 环境变量

存储系统中的目录,在命令行中执行命令的时候,系统会自动去这些目录中查找命令的位置。

3 Node.js 快速入门

3.1 Node.js 的组成

JavaScript 由三部分组成,ECMAScript、DOM、BOM。

Node.js 是由 ECMAScript 及 Node 环境提供的一些附加 API 组成的,包括文件、网络、路径等等一些更加强大的 API。

3.2 Node.js 基础语法

所有 ECMAScript 语法在 Node 环境中都可以使用。

运行js文件:在文件当前目录下,输入:

node xxx.js

3.3 Node.js 全局对象 global

在浏览器中全局对象是 window,在 Node 中全局对象是 global。

Node 中全局对象下有以下方法,可以在任何地方是有,global 可以省略:

console.log() 在控制台输出
setTimeout() 设置超时定时器
clearTimeout() 清除超时定时器
setInterval() 设置间歇定时器
clearInterval() 清除间歇定时器

例子:新建 global.js 文件:

global.console.log('我是global对象下面的console.log方法输出的内容');

global.setTimeout(function () {
  console.log('123');
}, 2000)

在命令行工具中,输入:

node global.js

结果是:先输出“我是global对象下面的console.log方法输出的内容”,然后2秒后输出“123”。

修改下代码,把 global 去掉:

console.log('我是global对象下面的console.log方法输出的内容');

setTimeout(function () {
  console.log('123');
}, 2000)

在命令行工具输入:

node global.js

结果和上面是一样的,说明 global 是全局对象。

4 Node.js模块化开发

4.1 JavaScript 开发弊端

JavaScript 在使用时存在两大问题:文件依赖和命名冲突。

4.2 软件中的模块化开发

一个功能就是一个模块,多个模块可以组成完整营养,抽离一个模块不会影响其他功能的运行。

4.3 Node.js 中模块化开发规范

Node.js 规定一个 JavaScript 文件就是一个模块,模块内部定义的变量和函数,默认情况下在外部无法得到。
模块内部可以使用 exports 对象进行成员导出,使用 require 方法导入其他模块。

4.4 模块成员导出

例子:

// a.js
// 在模块内部定义变量
let version = 1.2;
// 在模块内部定义方法
const sayHi = name => `您好,${name}`;
// 向模块外部导出数据
exports.version = version;
exports.sayHi = sayHi;

4.5 模块成员的导入

例子:

// b.js
// 在 b.js 模块中导入模块 a
let a = require('./a.js')
// 输出 a 模块中的 version 变量
console.log(a.version);
// 调用 a 模块中的 sayHi 方法并输出其返回值
console.log(a.sayHi('世界'));

此时在当面目录下的命令行中,输入:node ./b.js

会在控制台打印出:1.2  和  您好,世界

注意:导入模块时后缀可以省略。

比如:在 b.js中 可以写作

let a = require('./a')

4.6 模块成员导出的另一种方式:

module.exports.version = version;
module.exports.sayHi = sayHi;

exports 是 module.exports 的别名(地址引用关系),导出对象最终以 module.exports 为准。

4.7 模块导出两种方式的联系与区别: 

当 exports 对象和 module.exports 对象,指向的不是同一个对象时,以 module.exports 为准。

5 系统模块

5.1 什么是系统模块

Node 运行环境提供的 API ,因为这些 API 都是以模块化的方式进行开发的,所以我们又称 Node 运行环境提供的 API 为系统模块。

5.2 系统模块fs 文件操作

f: file, s: system,  fs: 文件操作系统

const fs = require('fs');

读取文件内容:

fs.readFile('文件路径/文件名称'[,'文件编码'],callback);

读取文件语法示例:

// 读取上一级 css 目录下的 base.css
fs.readFile('../css/base.css','utf-8', (err, doc) => {
  // 如果文件读取法师错误,参数 err 的值为错误对象,否则 err 的值为 null
  // doc 参数为文件内容
  if (err == null) {
    // 在控制台中输入文件内容
    console.log(doc);
  }
});

例子:新建 readFile.js 文件:

// 1.通过模块的名字 fs 对模块进行引用
const fs = require('fs');

// 2.通过模块内部的 readFile 方法,读取文件内容
fs.readFile('./a.js','utf8', (err, doc) => {
  // 如果文件读取法师错误,参数 err 的值为错误对象,否则 err 的值为 null
  // doc 参数为文件内容
  if (err == null) {
     在控制台中输入文件内容
     console.log(doc);
  }
});

在当前目录下的命令行输入:node readFile.js

可以读取出 a.js 的文件内容

 

写入文件内容:

fs.writeFile('文件路径/文件名', '数据', callback);

写入文件语法示例:

const context = '<h3>正在使用fs.writeFile写入文件内容</h3>''
fs.writeFIle('../index.html', context, err => {
  if (err != null) {
    console.log(err);
    return;
  }
  console.log('文件写入成功');
});

例子:新建 writeFile 文件:

const fs = require('fs');

fs.writeFile('./demo.txt', '<h3>Hello world</h3>', err => {
  if (err != null) {
    console.log(err);
    return;
  }
  console.log('文件写入成功');
})

注意:如果目录下没有 demo.txt 文件,系统会自动创建该文件;如果目录下有 demo.txt 文件,那么会覆盖替换原文件里面的内容。

此时,在当前目录下的命令行输入:node writeFile.js

命令行工具会显示“文件写入成功”,然后会看到目录下生产一个 demo.txt 文件,里面的内容是“<h3>Hello world</h3>”。

5.3 系统模块 path 路径操作

为什么要进行路径拼接:

不同操作系统的路径分隔符不统一,比如:/public/upload/avatar

Windows 上是:\ 或 /
linux 上是:/

5.4 路径拼接语法:

path.join('路径', '路径', 

路径拼接语法示例:

// 导入 path 模块
const path = require('path');
// 路径拼接
let finialPath = path.join('itcast', 'a', 'b', 'c.css');
// 输出结果 itcast\a\b\c.css
console.log(finialPath);

例子:新建 path.js 文件

// public/upload/avatar

// 导入 path 模块
const path = require('path');
// 路径拼接
let finialPath = path.join('public', 'upload', 'avatar');
// 输出结果 itcast\a\b\c.css
console.log(finialPath);

此时,在当前目录下的命令行输入:node path.js

命令行工具会把拼接好的路径打印出来。 public\upload\avatar

5.5 相对路径 VS 绝对路径

大多数情况下使用绝对路径,因为相对路径有时候相对的是命令行工具的当前工作目录

在读取文件或者设置文件路径时都会选择绝对路径

使用 __dirname 获取当前文件所在的绝对路径

例子:新创建 path-xj.js 文件:

const fs = require('fs');
const path = require('path');

console.log(__dirname); // 获取当前文件所在的绝对路径
console.log(path.join(__dirname, 'helloa.js'));

fs.readFile(path.join(__dirname, 'helloa.js'), 'utf8', (err, doc) => {
  console.log(err);
  console.log(doc);
});

在命令行工具中,往上退一级目录。

然后输入:node .\desktop\path-xj.js

可以看到命令行工具中显示:

 

6 第三方模块 

6.1  什么是第三方模块

别人写好的,具有特定功能的、我们能直接使用的模块,即第三方模块。由于第三方模块通常都是由多个文件组成,并且被防止在一个文件夹中,所以又名包。

第三方模块有两种存在形式:

1)以 js 文件的形式存在,提供实现项目具体功能的 API 接口。

2)以命令行工具形式存在,辅助项目开发。

6.2 获取第三方模块

npmjs.com:第三方模块的存储和分发仓库

npm(node package manager):node 的第三方模块管理工具,包管理工具。

下载:npm install 模块名称

卸载:npm uninstall package 模块名称

全局安装与本地安装:

1)命令行工具:全局安装
2)库文件:本地安装

6.3 第三方模块 nodemon

nodemon 是一个命令行工具,用以辅助项目开发。可以监控文件的修改。

在 Node.js 中,每次修改文件都要在命令行工具中重新执行该文件,非常繁琐。

使用步骤:

1)使用 npm install nodemon -g 下载

2)在命令行工具中使用 nodemon 命令替代 node 命令执行文件

6.4 第三方模块 nrm

nrm(npm registry manager):npm 下载地址切换工具

使用步骤:

1)使用 npm install nrm -g 下载

2)查询可用下载地址列表: nrm ls

3)切换 npm 下载地址:nrm use 下载地址名称

安装完成后,在命令行工具,输入:

nrm ls

结果:

*代表的是 npm 当前默认下载地址。

切换淘宝的下载地址,在命令行输入:

nrm use taobao

然后再输入: 

nrm ls

可以看到*切换到了 taobao 前面,表示 taobao 地址是当然默认地址了。

6.5 第三方模块 Gulp

基于 node 平台开发的前端构建工具,主要用来设定程序自动处理静态资源的工作。简单的说,gulp就是用来打包项目的。

将机械化操作编写成任务,想要执行机械化操作时执行一个命令行命令任务就能自动执行了。

用机器代替手工,提高开发效率。

官网:https://gulpjs.com/

中文官网:https://www.gulpjs.com.cn/docs/

Gulp 介绍及插件的使用

7 package.json 文件 

7.1 node_modules 文件夹的问题

1、文件夹以及文件过多过碎,当我们将项目整体拷贝给别人的时候,传输速度会很慢很慢。

2、复杂的模块依赖关系需要被记录,确保模块的版本和当前保持一致,否则会导致当前项目运行报错。

7.2 package.json 文件的作用

项目描述文件,记录了当前项目信息,例如项目名称、版本、作者、github地址、当前项目依赖了那些第三方模块等。使用 npm init -y 命令生成。

例子:

1.先新建 description 文件夹,并在命令行工具中切换到 description 目录下

输入:(-y 表示 都用默认值)

npm init -y

效果图:

 

会发现 description 目录下,生成了 package.json 文件。

2.在命令行工具输入:(可以同时安装多个插件,以空格隔开)

npm install formidable mime

然后可以看到 package.json 文件,多了一个 dependencies 选项:

 

dependencies 就是项目所依赖的第三方模块。

3.当我们把项目传递给别人时,不会传递 node_modules 文件夹。这里我们假设传递,把 node_modules 文件夹删除掉

别人要做的就是,在命令行工具进入当前项目目录,输入:

npm install

npm 会自动到项目的根目录下找 package.json 文件,然后这个文件中找到 dependencies 选项,再根据这个选项下载第三方模块。

7.3 项目依赖

在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖。

npm install 包名 命令下载的文件会默认被添加到 package.json 文件的 dependencies 字段中

{
  "dependencies": {
    "jquery": "^3.3.1"
  }
}

7.4 开发依赖

在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖。

使用 npm install 包名 --save-dev 命令将包添加到 package.json 文件的 dependencies 字段中

{
  "devDependencies": {
    "gulp": "^3.9.1"
  }
}

例如:

npm install gulp --save-dev

package.json 文件中多了一个开发依赖devDependencies:

 

将项目依赖和开发依赖区分的好处是:可以在不同的运行环境,下载不同的依赖。

比如说在线下开发环境,可以在命令行工具输入:npm install 下载所有依赖,

如果是在线上的运营环境(服务器环境),则可以输入: npm install --production 只会下载 dependencies 选项的依赖。

scripts 选项:

在 package.json 文件中,scripts 选择添加 build:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "nodemon app.js"
  },

在项目根目录下新建 app.js 文件:

console.log('app.js 文件被执行了');

正常情况下,我们在命令行工具执行,输入:

nodemon app.js

使用别名执行,输入:

npm run build

使用别名语法:

npm run 别名

7.5 package-lock.json 文件的作用

package-lock.json 文件中包含:模块与模块之间的依赖关系,模块的版本,模块的下载地址

8 Node.js 中的模块加载机制

8.1 模块查找规则-当模块拥有路径但没有后缀时

require('./find.js');
require('./find');

1、require 方法根据模块路径查找模块,如果是完整路径,直接引入模块。

2、如果模块的后缀省略,先找同名JS文件,再找同名JS文件夹

3、如果找到了同名文件夹,找文件夹中的 index.js

4、如果文件夹中没有 index.js ,就会去当前文件夹中的 package.json 文件中查找 main 选项中的入口文件

5、如果找指定的入口文件补存在或者没有指定入口文件,就会报错,模块没有被找到。

例子:

新建项目 modulefindRules ,并创建 require.js 文件:

require('./find.js')

和 find.js 文件

console.log('modulefindRules 文件夹下的 find.js 被引用了');

在当然项目的命令行工具中输入:

node require.js

效果图:

 

 修改 require.js 文件:

// require('./find.js')
require('./find');

重新执行:

node require.js

发现结果和刚才是一样的,同样打印出了“modulefindRules 文件夹下的 find.js 被引用了”。

修改 find.js 文件名为 find1.js。

新建 find 文件夹,并创建 index.js 文件:

console.log('find 文件夹下的 index.js 被执行了');

这时在命令行工具输入:

node require.js

打印的结果就是“find 文件夹下的 index.js 被执行了”。

在命令行工具中进入 find 目录,然后输入:

npm init -y

发现在 find 文件夹下,多了一个 package.json 文件,打开该文件,并把入口文件修改为:

"main": "main.js",

在 find 文件夹下,新建 main.js 文件:

console.log('find 文件夹下的 main.js 被执行了');

在命令行工具中返回到项目根目录,重新输入:

node require.js

发现打印的结果是:“find 文件夹下的 main.js 被执行了”。

8.2 模块查找规则-当模块没有路径且没有后缀时

require('find');

1、Node.js 会假设它是系统模块

2、Node.js 会去 node_modules 文件夹中

3、首先看是否有该名字的 JS 文件

4、再看是否 有该名字的文件夹

5、如果是文件夹看里面是否有 index.js

6、如果没有 index.js,查看该文件夹中的 package.json 中的 main 选项确认模块入口文件

7、否则找不到报错

例子:

在根目录下新建 node_modules 文件夹,并创建 find.js 文件:

console.log('node_modules 文件夹下的 find.js 被执行了');

回到命令行工具中,输入:

node require.js

发现结果打印出“node_modules 文件夹下的 find.js 被执行了”。

把 node_modules 目录下的 find.js 文件改名为:finde.js,并新建 find 文件夹,创建 index.js 文件:

console.log('node_modules 文件夹中的 find 文件夹下的 index.js 被执行了');

再回到命令行中输入:

node require.js

此时的打印结果是:“node_modules 文件夹中的 find 文件夹下的 index.js 被执行了”。

修改 node_modules 文件夹中 find 文件夹下的 index.js 文件改名为:index2.js。

并在命令行工具中,进入 modulefindRules\node_modules\find 目录,输入:

npm init -y

然后在 modulefindRules\node_modules\find 目录下,多了一个 package.json 文件,修改入口文件为:

"main": "b.js",

在 modulefindRules\node_modules\find 目录下,新建 b.js 文件:

console.log('b.js 文件被执行了');

回到命令行工具的项目根目录下,输入:

node require.js

此时结果打印为:“b.js 文件被执行了”。

 

posted on 2020-06-12 17:01  JoeYoung  阅读(1643)  评论(0编辑  收藏  举报