01:模块化和包管理器

一、web服务构成

  1. 服务器:
    • 也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。
    • 在网络环境下,根据服务器提供的服务类型不同,分为文件服务器,数据库服务器,应用程序服务器,WEB服务器等。
  2. web服务器环境:apache , ngnix , tomcat
  3. 服务器访问方式:localhost -> www.abc.com
  4. 数据库:mysql,sqlserver,mongoDB
    • 数据库:数字,字符
    • 磁盘(硬盘) 文件本身(图,视频,PDF)   文件服务器
  5. 后台管理程序:
    • nodejs,java……..

二、开发方式

  1. 大后端(前后端不分离):
    • 用户 -> 地址栏(http[s]请求) -> web服务器(收到) -> nodejs处理请求(返回静态、动态) -> 请求数据库服务(返回结果) -> nodejs(接收) -> node渲染页面 -> 浏览器(接收页面,完成最终渲染)
  2. 大前端(前后端分离):
    • 前端 -> http[s]请求 -> web服务器(收到) -> nodejs处理请求(返回静态、动态) -> 请求数据库服务(返回结果) -> nodejs(接收) -> 返回给前端(ajax)-> 前端处理数据(渲染) -> 浏览器(接收页面,完成最终渲染)

三、node基础

  1. 认识Node.js

Node.js是一个javascript运行环境。它让javascript可以开发后端程序,实现几乎其他后端语言实现的所有功能,可以与PHP、Java、Python、.NET、Ruby等后端语言平起平坐。

Nodejs是基于V8引擎,V8是Google发布的开源JavaScript引擎,本身就是用于Chrome浏览器的js解释部分,但是Node.js的作者Ryan Dahl,把V8引擎搬到了服务器上,用于做服务器的软件。

- 作用:用来实现后台管理程序
- 目的:数据服务,文件服务,web服务
- 类似:php,.net,java(jsp) ....
  1. 优势:
    • Nodejs语法完全是js语法,只要你懂js基础就可以学会Nodejs后端开发
    • NodeJs超强的高并发能力,实现高性能服务器
    • 开发周期短、开发成本低、学习成本低
  2. 使用 Node.js 需要了解多少 JavaScript

http://nodejs.cn/learn/how-much-javascript-do-you-need-to-know-to-use-nodejs

  1. 浏览器环境 和 Node.js环境

1653931239327-e97fad89-5165-4c3c-b7a8-40bb56c59761.png

Node.js 可以解析JS代码(没有浏览器安全级别的限制)提供很多系统级别的API,如:

- <font style="color:rgb(51, 51, 51);">文件的读写 (File System)</font>
- <font style="color:rgb(51, 51, 51);">进程的管理 (Process)</font>
- <font style="color:rgb(51, 51, 51);">网络通信 (HTTP/HTTPS)</font>
  1. 环境搭建:nodejs + web应用 + 数据库
    • 下载:http://nodejs.cn/download/
    • 安装:next安装法
    • 测试:
      • window:命令行工具
        • win+r -> 输入cmd,回车 -> 在命令行中输入:node -v,回车后查看node版本号
      • mac:终端
        • 输入输入:node -v,回车后查看node版本号
  2. 版本介绍:
    • Vx(主).x(子).x(修正)
    • 主:1/3的API发生巨变,使用方式变化了
    • 子:API没有删减,使用方式没变化,内部实现发生了变化
    • 修正版:什么都没变,处理一下bug
      • V6.8.x 稳定
      • V6.9.x 非稳定版
      • Vx.x.x-beta 测试
      • vx.x.x-rc 测试稳定``
      • vx.x.x-alpha 测试稳定
  3. Node.Js的执行
    1. 命令行形式直接执行,执行的是具体的代码
      1. 打开系统命令行工具(见下节命令行工具介绍)
      2. 在命令行工具中输入:node,回车,进入node编程状态
      3. 书写自己的代码,回车
      4. 退出node的编程状态:
        • ctrl+c,两次
      • 执行node代码非常方便,但是不适合长时间留存代码,不适合代码量较多的功能
      • 仅仅适合用来对一些API进行测试
    2. 文件形式执行,执行的是文件 *
      1. 编写node的文件:xxx.js
        • 注意扩展名也是js
      2. 打开系统命令行工具(见下节命令行工具介绍)
      3. 确保命令行工具没有在node编程状态
      4. 使用命令行工具的路径切换相关命令,进入要执行的文件所在的文件夹
        • 比如:要执行的文件在:D盘:资料->node学习->code->day06文件夹内
          • 最终需要使用命令行工具进入day06
          • cd d:资料/node学习/code/day06
        • 以执行 dirls命令,能查看到要执行的文件为准
      5. 使用:node 文件名,回车执行
      • 适合长时间留存代码,适合代码量较多的功能
      • 适合投入实际项目使用
  4. 系统命令行工具介绍
    • 打开方式
      • windows:命令行窗口
        1. 方法一:
          • 按:win+r,打开运行窗口 -> 输入:cmd -> 回车
        2. 方法二:
          • 开始菜单 -> 搜索:cmd -> 点击对应的命令行工具图标,打开
      • mac:终端
        • 在程序坞中,找到终端,点击打开
    • 路径切换 *
      • windows:
        • 打开上层文件夹:cd ../
        • 进入指定子文件夹:cd 指定文件夹名
          • cd 学习
          • cd d:资料/node学习/code/day06
        • 切换盘符:盘符:
          • d:c:
        • 查看当前文件夹内的子文件:dir
          • 帮助开发者查看接下来要去哪,或当前路径处于哪个位置
        • 清屏:cls
      • mac:
        • 打开上层文件夹:cd ../
        • 进入指定子文件夹:cd 指定文件夹名
          • cd 学习
          • cd 资料/node学习/code/day06
        • 查看当前文件夹内的子文件:ls
          • 帮助开发者查看接下来要去哪,或当前路径处于哪个位置
        • 清屏:clear

四、Node.js的模块化

1653932577656-7eeb17fa-5814-4f09-aea6-756cbf5fcfd8.png

  • Node.js的模块化标准采取的是CommonJS 规范。
  1. 模块化的目的
    • 主要为了JS在后端的表现制定
    • CommonJS 是个规范,Node.js / webpack 实现了这个规范
    • ECMA 是个规范,JavaScript 实现了这个规范
  2. 模块化方式
    • 服务器端JS:相同的代码需要多次执行 | CPU和内存资源是瓶颈 | 加载时从磁盘中加载
      • node模块: http,fs,querystring,url
      • 模块化方式:require('模块名')
    • 浏览器端js:代码需要从一个服务器端分发到多个客户端执行 | 带宽是瓶颈 | 通过网络加载
      • 模块化方式:CMDseajs.js;AMDrequire.js;ES6: exports/ import
  3. CommonJS模块化方式
    • require 引入模块、输入
      • require('模块名')
        • 不指定路径:先找系统模块 -> 再从项目环境找node_modules | bower_components (依赖模块)-> not found
        • 指定路径:指定路径 -> not found
      • require输入的是一个对象
    • exports 导出,批量输出,都是属性
      • exports.自定义属性 = 值
    • module 默认输出,只能输出一次,require输入的是任意接收
      • module.exports = { 自定义属性:值 }
  4. Node.js的模块分类
    1. 内置模块:官方提供,直接引入
      • 引入:const 变量 = require("模块名");
      • 使用:变量.xxx()
      • 内置模块:fsurlquerystringhttp
    2. 第三方模块:非官方,非当前开发者,需要先获取(下载)到第三方模块,才能引入
      • 下载:使用包管理器 npm下载第三方模块
      • 引入:const 变量 = require("模块名");
      • 使用:变量.xxx()
    3. 自定义模块:自己写的模块,先定义模块,再引入模块
      • 定义:exports.xxx = 功能或对象
      • 引入:const 变量 = require("路径+模块名");
      • 使用:变量.zzz()

五、包管理器 - npm

  1. 介绍:
    • 作用:安装模块(包),自动安装依赖,管理包(增,删,更新,项目所有包)
    • nodejs 环境自带 npm 包管理器
    • 切换淘宝镜像:npm config set registry http://registry.npmmirror.com
    • 类似的包管理器:yarn(https://www.yarnpkg.cn/),cnpm,bower,pnpm等
  2. 初始化npm环境(生成项目依赖描述文件:package.json)
    • npm init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"name": "myapp", // 项目名称,不要和依赖的包重名
"version": "0.0.1", // 版本
"description": "test and play", // 项目描述
"main": "index.js", // 入口文件
"dependencies": { // 项目依赖,上线也要用
"jquery": "^3.2.1",
"express": "^4.17.1"
},
"devDependencies": { // 开发依赖,上线就不用
"node-sass": "^2.0.0"
},
"scripts": { // 命令行
"test": "命令行",
},
"repository": { // 仓库信息
"type": "git",
},
"keywords": [ // 项目关键词
"test",'xx','oo'
],
"author": "admin", // 作者
"license": "ISC", // 认证
}
  1. 安装模块的环境位置
    1. 全局环境:
      • 可以独立运行,或,在package.json的scripts内配置命令后,使用npm run 命令名执行
      • 如:命令行工具:nrm,脚手架工具:vue-cli
      • 安装或卸载命令
        • npm install 包名 -g
          • install 可简写为 i
        • npm uninstall 包名 -g
          • uninstall 可简写为 uni
    2. 项目环境
      • 如果是命令行工具,只能在package.json的scripts内配置命令后,使用npm run 命令名执行
      • 其他第三方模块,在模块内直接使用require函数引入即可
      • 依赖环境
        • 项目依赖dependencies:运行时的依赖,发布后,即生产环境下还需要用的模块。
          • 安装命令:npm i 包名 --save 简写为:npm i 包名 -S
            • 如:jquery,express
        • 开发依赖devDependencies:开发时的依赖。只在开发过程中使用,发布后用不到。
          • 安装命令:npm i 包名 --save-dev简写为:npm i 包名 -D
            • 如:node-sass,webpack
  2. 其他常用npm命令
    • 列出所有已装包
      • npm list -g(不加-g,列举当前目录下的安装包)
    • 检查安装的包是否已经过时
      • npm outdated
    • 查看当前包概要信息
      • npm info 包名(详细信息)
      • npm info 包名 version(获取最新版本)
    • 安装package.json文件内已指定的所有包
      • npm install
      • package.json文件内的版本约束:
        • ^x.x.x      约束主版本,后续找最新
        • ~x.x.x      保持前两位不变,后续找最新
        • *           装最新
        • x.x.x       定死了一个版本
    • 安装指定版本的包:
      • npm install 包名@版本
  3. 包管理的下载源管理工具:nrm:
    • 安装:npm i nrm -g
    • 查看所有源:nrm ls
    • 测试所有源:nrm test
    • 切换源:nrm use 源名
  4. 自动刷新服务器插件:nodemon:
    • 下载:npm i nodemon -g
    • 使用:在命令行中:nodemon 文件名
    • 当使用nodemon执行的文件发生改变了,会自动重新执行该文件
  5. 模块下载中,如果比较卡顿(超过5分钟),或者下载报错:
    • ctrl + c -> npm uni 包名  -> npm cache clean --force(清除缓存) -> 换网 -> npm i 包名
  6. 发布模块(拓展):
    • 注册账号:npmjs.com
    • 创建包目录 -> npm init -y -> 创建入口index.js -> 编写,输出 -> 准备发布
    • 登录:npm login --registry ${username}
      • 输入邮箱
      • 输入密码
    • 发布:npm publish --registry ${username}
    • 删除:npm unpublish
    • 发布操作长时间没有做,邮箱需要确认,收取激活邮件
    • package-lock.json  文件用来固化依赖

六、node内置模块

1. http模块

  • 可以实现搭建服务器,请求数据等功能
  1. 引入模块:const http = require('http');
  2. 创建服务:
    • const server = http.createServer((request, response)=>{});  // 返回http对象
      • require:请求:浏览器 -> 服务器
        • req.url地址,提取地址栏数据
        • req.on('data|end');提取非地址栏数据,所有的http[s]都会触发data事件和end事件
      • response:响应:服务器 -> 浏览器
        • 响应头设置:res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});
        • res.write(字符/数据<string><buffer>);
        • res.end(); 结束响应
  3. 监听:
    • server.listen(端口,[地址],[回调函数]);
      • 端口:1-65535,1024以下系统占用,80
      • 地址(可选):
        • 虚拟域名:localhost或127.0.0.1
        • 真实域名:xx.duapp.com
      • 回调(可选):监听成功,执行回调函数
  4. 小提示:
    • 服务器代码更新后,需要重启服务器
      • 自动重启工具:nodemon
      • 可在命令行中通过npm全局安装该模块:npm install nodemon -g
      • 使用:nodemon 文件
    • 接口测试工具
      • postman

2. fs模块 - file system文件服务

  1. 引入模块:const fs = require('fs');
  2. 异步读文件:fs.readFile('路径',[配置],回调(err,data))
    • err:报错信息,null或者undefined,表示没有错误
    • data:二进制buffer流 ,可以通过data.toString("utf-8")转换格式
  3. 同步读文件:let data = fs.readFileSync('路径',[配置])
    • 免去回调地狱,但会阻塞其他程序执行,比较占用时间
    • 建议使用try-catch语句捕获同步语句的错误
  4. 异步写文件:fs.writeFile('路径','内容',回调(err))
    • err:保存信息,null或者undefined,表示没有错误
  5. 同步写文件:let data = fs.writeFileSync('路径','内容')
    • 免去回调地狱,但会阻塞其他程序执行,比较占用时间
  6. 删除文件:fs.unlink('路径',回调)
  7. 文件重命名:fs.rename('老文件名','新文件名',(err)=>{})
  8. 创建文件夹:fs.mkdir('路径', 回调)
  9. 删除文件夹:fs.rmdir('路径', 回调)
  10. 实现静态资源托管:
    • 什么是静态资源: css/html/js/图片/json/字体…
    • 前端资源请求:
      • href``src``locaction.href
    • 后端资源读取:
      fs.readFile(文件名,[编码],回调(err,data));

3. url模块 - 地址

  1. 作用:解析或转换url数据
  2. 引入:const url = require("url");
  3. 使用:
    • 字符转对象
      • const str = "http://localhost:8002/aaa?username=sdfsdf&content=234234#title4";
      • url.parse(str, true)
        • true 处理query数据,直接转成对象
      • obj参数
        • protocol: ‘http:’,  协议
        • slashes: true,  双斜杠
        • auth: null,  作者
        • host: ‘localhost:8002’,  主机 www.baidu.com
        • port: ‘8002’,  端口
        • hostname: ‘localhost’,  baidu
        • hash: ‘#title’,  哈希(锚)
        • search: ‘?username=sdfsdf&content=234234’,  数据
        • query: ‘username=sdfsdf&content=234234’,  数据
        • pathname: ‘/aaa’,  文件路径
        • path: ‘/aaa?username=sdfsdf&content=234234’,  文件路径
        • href: ‘http://localhost:8002/aaa?username=sdfsdf&content=234234#title
    • 对象转字符
      • url.format(obj)

4. querystring 模块 - 查询字段

  1. 作用:处理query数据
  2. 引入:const querystring = require("querystring");
  3. 字符转对象:
    • const str = "key=value&key2=value2";
    • querystring.parse(str)
  4. 对象转字符
    • const obj = {a:10, b:20}
    • querystring.stringify(obj)
  5. escape/unescape
    • 对数据中的中文或特殊符号进行转义,防止脚本注入攻击
    • const str = 'id=3&city=北京&url=https://www.baidu.com';
    • querystring.escape(str);
    • const str = 'id%3D3%26city%3D%E5%8C%97%E4%BA%AC%26url%3Dhttps%3A%2F%2Fwww.baidu.com';
    • querystring.unescape(str);

5. path模块 - 路径

  1. 作用:处理路径数据
  2. 引入:const path = require("path");
  3. 合并路径 - 使用特定于平台的分隔符作为分隔符将所有路径部分连接,生成规范路径
    • const str = path.join("aa", "qwe", "hello", "index.html");
    • MAC:aa/qwe/hello/index.html
    • Windows:aa\\qwe\\hello\\index.txt

6. 关于路径的全局变量

  1. 全局变量:__dirname
    • 用户获取当前文件所在文件夹的绝对路径
  2. 全局变量:__filename
    • 用户获取当前文件的绝对路径

7. 服务端发起get请求:http|https.get("url", 回调);

1
2
3
4
5
6
7
8
9
10
11
12
13
const https = require("https");

const url = "https://movie.douban.com/j/search_subjects?type=movie&tag=热门&page_limit=50&page_start=0";

https.get(url, res=>{
let data = "";
res.on('data', chunk=>{
data += chunk;
})
res.on('end', ()=>{
console.log(data);
})
})

8. 服务端发起post请求:http|https.request(ops, 回调);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const https = require("https");
const url = require("url");

const urlObj = url.parse("https://music.163.com/weapi/song/enhance/player/url/v1");

const options = {
hostname:urlObj.hostname,
port:443,
method:"POST",
path:urlObj.pathname,
headers:{
"Content-Type": "application/x-www-form-urlencoded"
}
};

const req = https.request(options, res=>{
let data = "";
res.on('data', chunk=>{
data += chunk;
})
res.on('end', ()=>{
console.log(data);
})
})

req.write("params=HBeWY9slvubV%2FsCFfS%2BUhfCTNEELGpEkyepAFVjDOXhiyngTesa1d9DqULe%2BG9EVcqZvNbDczEMZCCwv5G%2BCDFQUMrXNR%2BGwYg93iAybBw76XBRXiNmwSo088BTbOiwyD%2Fz5myLxHlCOrcrjzGZOFQ%3D%3D&encSecKey=82ea0a9c0217e745c8009280044eb9badf7cbb8d79c610015818721d0db9102c9a1d5c4fd062d331cd7aed0973ad3ddc80d29381de962d56e1df3584b6e65e6497aa8f3c133b2890cef54f3a29883219de94b82ffd30291c85e3d2353e4cea8bce3a8f643c9399ac4161dc72d7e9e83871ced1610fa5a1c2e6a25e00c0e9cc6c");
req.end();

七、路由

  • 什么是路由:就是根据不同的路径,响应不同的内容。一般情况下,在项目开始之前,都会对路由地址进行规划设定,然后在项目开发过程中,针对预先规划的路由地址进行处理和响应。
1
2
3
4
5
6
7
8
9
10
11
12
function dataHandle(req, res, data){
switch(data.type){
case "login":login(req, res, data);break;
case "register":register(req, res, data);break;
case "getData":getData(req, res, data);break;
case "getBanner":getBanner(req, res, data);break;
case "getGoods":getGoods(req, res, data);break;
case "getUser":getUser(req, res, data);break;
case "jsonp":jsonp(req, res, data);break;
default:error(req, res, data);
}
}