1. Node.js 模块化
1.1 CommonJS 标准
utils.js
javascript
/**
* 目标:基于 CommonJS 标准语法,封装属性和方法并导出
*/
const baseURL = "http://hmajax.itheima.net";
const getArraySum = (arr) => arr.reduce((sum, item) => (sum += item), 0);
module.exports = {
baseURL,
getArraySum,
};
index.js
javascript
/**
* 目标:基于 CommonJS 标准语法,导入工具属性和方法使用
*/
/*
模块化:每个文件都是独立的模块,需要标准语法导出和导入进行使用
CommonJS 标准 - 导出和导入模块
➢ 导出:module.exports = {}
➢ 导入:require('模块名或路径')
➢ 内置模块,直接写名字。例如:fs,path,http等
➢ 自定义模块,写模块文件路径。例如:./utils.js
*/
// 解构导入的数据
// const { baseURL, getArraySum } = require("./utils");
const { baseURL, getArraySum } = require("./utils.js");
console.log(baseURL); // http://hmajax.itheima.net
console.log(getArraySum([1, 5, 8])); // 14
1.2 ECMAScript 标准 - 默认导出和导入
utils.js
javascript
/**
* 目标:基于 ECMAScript 标准语法,封装属性和方法并"默认"导出
*/
const baseURL = "http://hmajax.itheima.net";
const getArraySum = (arr) => arr.reduce((sum, item) => (sum += item), 0);
export default {
baseURL,
getArraySum,
};
package.json
javascript
{
"type": "module"
}
index.js
javascript
/**
* 目标:基于 ECMAScript 标准语法,"默认"导入,工具属性和方法使用
*/
/*
1. ECMAScript 标准 - 默认导出和导入模块
➢ 导出:export default {}
➢ 导入:import 变量名 from '模块名或路径'
2. Node.js 切换模块标准为 ECMAScript
➢ 运行模块所在文件夹,新建 package.json 并设置{ "type" : "module" }
*/
import obj from "./utils.js";
console.log(obj.baseURL); // http://hmajax.itheima.net
console.log(obj.getArraySum([1, 4, 7])); // 12
1.3 ECMAScript 标准 - 命名导出和导入
utils.js
javascript
/**
* 目标:基于 ECMAScript 标准语法,封装属性和方法并"命名"导出
*/
export const baseURL = "http://hmajax.itheima.net";
export const getArraySum = (arr) => arr.reduce((sum, item) => (sum += item), 0);
package.json
javascript
{
"type": "module"
}
index.js
javascript
/**
* 目标:基于 ECMAScript 标准语法,"命名"导入,工具属性和方法使用
*/
/*
ECMAScript 标准,命名导出和导入的语法
➢ 导出:export 修饰定义的语句
➢ 导入:import { 同名变量 } from '模块名或路径'
按需加载,使用命名导出和导入
全部加载,使用默认导出和导入
*/
import { getArraySum, baseURL } from "./utils.js";
console.log(baseURL); // http://hmajax.itheima.net
console.log(getArraySum([1, 5, 8, 12, 234])); // 260
2. 软件包
javascript
/*
1. 什么是包?
➢ 将模块,代码,其他资料聚合成的文件夹
2. 包分为哪 2 类呢?
➢ 项目包:编写项目代码的文件夹
➢ 软件包:封装工具和方法供开发者使用
3. package.json 文件的作用?
➢ 记录软件包的名字,作者,入口文件等信息
4. 导入一个包文件夹的时候,导入的是哪个文件?
➢ 默认 index.js 文件,或者 main 属性指定的文件
*/
3. npm 软件包管理器
3.1 npm - 软件包管理器
javascript
/**
* 目标:使用 npm 下载 dayjs 软件包来格式化日期时间
* 1. (可选)初始化项目清单文件,命令:npm init -y
* 2. 下载软件包到当前项目,命令:npm i 软件包名称
* 3. 使用软件包
*/
/*
npm config set registry xxx 这个命令用于设置 npm(Node Package Manager)的注册表地址
默认情况下,npm 使用官方的 npm 注册表 (https://registry.npmjs.org),
但有时为了加快下载速度或访问某些特定的包,用户可能会选择使用镜像源。
1. 将 npm 的注册表设置为一个镜像源(在中国境内可能更快)
npm config set registry http://registry.npmmirror.com
2. 安装 dayjs 这个日期处理库; i - install
npm i dayjs
*/
/*
1. npm 软件包管理器作用?
➢ 下载软件包以及管理版本
2. 初始化项目清单文件 package.json 命令?
➢ npm init -y
3. 下载软件包的命令?
➢ npm i 软件包名字
4. 下载的包会存放在哪里?
➢ 当前项目下的 node_modules 中,并记录在 package.json 中
*/
const dayjs = require("dayjs");
const res = dayjs().format("YYYY-MM-DD");
console.log(res); // 2024-12-12
3.2 npm - 安装所有依赖
javascript
/**
* 目标:安装所有依赖软件包
* 场景:一般拿到别人的项目后,只有 package.json 缺少 node_modules 时需要做
* 语法:在当前项目终端下,输入命令:npm i
* 效果:会根据 package.json 记录的所有包和版本开始下载
*/
/*
1. 当项目中只有 package.json 没有 node_modules 怎么办?
➢ 当前项目下,执行 npm i 安装所有依赖软件包
2. 为什么 node_modules 不进行传递?
➢ 因为用 npm 下载比磁盘传递要快
*/
// 格式化日期
const dayjs = require("dayjs");
const nowDateStr = dayjs().format("YYYY-MM-DD");
console.log(nowDateStr); // 2024-12-12
// 求数组里最大值
const _ = require("lodash");
console.log(_.max([1, 2, 8, 3, 4, 5])); // 8
4. npm 全局软件包 nodemon
javascript
/**
* 目标:使用 nodemon 全局软件包,检测文件变化,自动重启程序
* 语法:
* 1. 安装 nodemon 全局软件包,命令:npm i nodemon -g
* 2. 使用 nodemon 来执行目标 js 文件
* 体验:启动后,修改代码,保存后观察终端效果
*/
/*
1. 本地软件包和全局软件包区别?
➢ 本地软件包,作用在当前项目,封装属性和方法
➢ 全局软件包,本机所有项目使用,封装命令和工具
2. nodemon 作用?
➢ 替代 node 命令,检测代码更改,自动重启程序
3. nodemon 怎么用?
➢ 先确保安装 npm i nodemon -g
➢ 使用 nodemon 执行目标 js 文件
*/
// 格式化日期
const dayjs = require("dayjs");
const nowDateStr = dayjs().format("YYYY-MM-DD");
console.log(nowDateStr);
// 求数组里最大值
const _ = require("lodash");
console.log(_.max([1, 10, 2, 3, 4, 55]));
5. Node.js 总结
javascript
/**
* 总结:
* Node.js模块:
* 概念:每个文件就是一个模块,独立作用域,按需加载,需使用特定语法导出导入
* CommonJS 标准语法:
* 导出:module.exports = {}
* 导入:require('模块名或路径')
* ECMAScript 标准语法:
* 默认导出:export default {}
* 默认导入:import 变量名 from '模块名或路径'
* 命名导出:export 修饰定义语句
* 命名导入:import { 同名变量 } from '模块名或路径'
*
* Node.js包:
* 概念:把模块文件,代码文件,其他资料聚合成一个文件夹
* 项目包:编写项目需求和业务逻辑的文件夹
* 软件包:封装工具/方法的文件夹(一般用 npm 管理)
* 本地软件包:封装属性/方法,在当前项目中使用,例如:dayjs,lodash
* 全局软件包:封装工具/命令,在本机中使用,例如:nodemon
*
* 常用命令:
* 执行 js 文件:node xxx
* 初始化 package.json: npm init -y
* 下载本地软件包:npm i 软件包名
* 下载全局软件包:npm i 软件包名 -g
* 删除软件包:npm uni 软件包名
*/
6. Express 搭建 Web 服务
javascript
/*
Express - 框架
使用 express 本地软件包,快速搭建 Web 服务(基于 http 模块)
功能:1. 提供数据接口 2. 提供网页资源等
*/
// 1. 下载 express 软件包
const express = require("express");
// 2. 导入并创建 Web 服务对象
const server = express();
// 3. 监听请求的方法和请求的资源路径
server.get("/", (req, res) => {
res.send("哦耶 express");
});
// 4. 监听任意请求的方法和请求的资源路径
server.all("*", (req, res) => {
res.status(404);
res.send("您访问的资源不存在");
});
// 5. 监听端口号,启动 Web 服务
server.listen(3000, () => {
console.log("启动成功成功");
});
7. 获取省份列表 - 接口开发
javascript
/**
* 目标:基于 express 软件包,开发提供省份列表的数据接口
* 要求:get 请求方法,/api/province 的请求路径
*/
const fs = require("fs");
const path = require("path");
const express = require("express");
const server = express();
// 监听 get 请求方法,
// 监听资源路径 /api/province,
// 读取 province.json 省份数据返回
server.get("/api/province", (req, res) => {
fs.readFile(path.join(__dirname, "/data/province.json"), (err, data) => {
if (err) {
console.log(err);
} else {
res.send(data.toString());
}
});
});
server.all("*", (req, res) => {
res.status(404);
res.send("你要访问的资源路径不存在");
});
server.listen(3000, () => {
console.log("Web 服务已启动");
});
8. 跨域以及解决方案
8.1 浏览器的同源策略
javascript
/**
* 目标:了解浏览器中的同源策略
* 同源策略:是一种安全策略,限制一个源的文档/脚本与另外一个源的资源交互
*
* 好处:保护网站的安全,减少被攻击的媒介
* 限制:浏览器限制 AJAX 只能访问同源的 URL 网址!
*
* 源:指的 URL 中的协议,域名,端口号
* 同源:网页加载所在的源,与 AJAX 请求的源完全相同即为同源
*/
8.2 跨域问题
javascript
/*
跨域访问:
网页所在源和 AJAX 请求的源(协议,域名,端口号)不完全相同,就发生跨域访问
*/
8.3 跨域问题 - 解决方案1 - CORS
javascript
/*
跨域问题 - 解决方案1 - CORS
目标:前后端分离的项目,前端和后端不在一个源,还要保证数据通信
解决:
采用 CORS (跨域资源共享),一种基于 HTTP 头的机制,
该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),
使得浏览器允许这些源访问加载自己的资源
步骤:
1. 下载 cors 本地软件包
2. 导入 cors 函数
3. 使用 server.use() 给 Web 服务添加插件功能
4. 把 cors 函数调用传入给 Web 服务,启动测试
1. 为什么要解决跨域问题?
➢ 因为前后端分离的项目,不在同一个源去开发项目
➢ 需要保证数据之间通信
2. 跨域问题如何解决?
➢ 让后端开启 CORS 跨域资源共享
➢ 在响应头设置 Access-Control-Allow-Origin: *
*/
// 2. 导入 cors 函数
const cors = require("cors");
// 3. 使用 server.use() 给 Web 服务添加插件功能
server.use(cors());
8.4 跨域问题 - 解决方案2 - 同源访问
javascript
/*
跨域问题 - 解决方案2 - 同源访问
目标:开发环境用 cors,上线部署关闭 cors,并采用同源访问方式
做法:让后端 Web 服务既可以提供数据接口,也可以返回网页资源
好处:安全,后端的接口不允许非同源来访问
1. CORS 只适用于什么阶段的项目?
➢ 本地开发阶段项目
2. 项目上线,如何解决跨域问题?
➢ 把前端项目和后端项目部署到同一个源下访问
*/
// 暴露指定的文件夹,让前端可以直接拼接路径和资源名字来访问
server.use(express.static(path.join(__dirname, "public")));