node(上)
Node.js
CommonJS
- CommonJS 是一种模块化规范,主要用于在服务器端(如 Node.js 环境)实现模块化编程。以下是关于 CommonJS 的详细介绍:
1. 背景
在 JavaScript 的早期,代码通常是全局共享的,没有模块化的概念。随着项目复杂度的增加,代码的可维护性和可复用性变得很差。CommonJS 规范应运而生,它旨在为 JavaScript 提供一种模块化机制,方便开发者组织代码、避免命名冲突,并提高代码的可维护性。
2. 核心概念
CommonJS 规范定义了模块的加载和导出机制,主要包括以下几个核心概念:
- 模块(Module):每个文件被视为一个独立的模块。模块内部的变量和函数默认不会被外部访问,除非显式导出。
require:用于加载模块。通过require函数可以引入其他模块的功能。module和exports:用于导出模块的功能。module是一个对象,exports是module的一个属性,通常用于导出模块的接口。
3. 模块的导出
在 CommonJS 中,可以通过 module.exports 或 exports 来导出模块的内容:
module.exports:可以直接导出一个对象、函数、类等。它是模块的最终导出内容。// math.js const add = (a, b) => a + b; const subtract = (a, b) => a - b; module.exports = { add, subtract };exports:exports是module.exports的引用,可以用来导出模块的部分内容。但需要注意,如果直接覆盖module.exports,exports的引用会失效。// utils.js exports.add = (a, b) => a + b; exports.subtract = (a, b) => a - b;
4. 模块的加载
通过 require 函数加载模块:
// app.js
const math = require('./math.js');
console.log(math.add(3, 5)); // 输出 8
console.log(math.subtract(10, 4)); // 输出 6
5. 模块缓存机制
CommonJS 模块加载时会进行缓存。当第一次加载模块时,模块的内容会被执行并缓存结果。后续再次加载时,直接返回缓存的结果,而不会重新执行模块代码。这可以提高性能,但需要注意,模块的状态是持久化的。
6. 适用场景
CommonJS 主要用于 Node.js 环境,因为它非常适合服务器端的模块化开发。Node.js 原生支持 CommonJS 规范,使得开发者可以方便地组织代码,构建大型项目。
7. 与其他模块化规范的比较
- 与 AMD(Asynchronous Module Definition)比较:AMD 是一种异步加载模块的规范,主要用于浏览器端,支持异步加载模块,适合复杂的前端项目。CommonJS 是同步加载模块,更适合服务器端。
- 与 ES6 模块(ESM)比较:ES6 模块是现代 JavaScript 的原生模块化规范,支持动态导入、静态分析等特性。CommonJS 是较早的规范,语法相对简单,但在现代项目中,ESM 的使用越来越广泛。
CommonJS 是 JavaScript 模块化发展的重要一步,虽然在现代前端开发中逐渐被 ES6 模块取代,但它在 Node.js 环境中仍然具有重要地位。
npm
npm(Node Package Manager)是 Node.js 生态系统中的核心工具,用于管理 JavaScript 项目中的依赖包。以下是关于 npm 的详细介绍:
npm 的功能和作用
- 包管理:
- 安装依赖包:通过简单的命令(如
npm install <package>)可以快速安装项目所需的第三方库。 - 更新和卸载包:使用
npm update <package>和npm uninstall <package>可以方便地更新或卸载包。 - 管理全局包:使用
npm install -g <package>可以将包安装到全局环境中。
- 安装依赖包:通过简单的命令(如
- 版本控制:
- npm 支持语义化版本控制(SemVer),允许开发者指定依赖包的特定版本或版本范围。
- 在
package.json中,可以使用符号(如^、~)来定义版本范围。 package-lock.json文件可以锁定依赖包的具体版本,确保不同开发环境的一致性。
- 依赖解析:
- npm 自动处理包之间的依赖关系,确保所有依赖都能正确安装。
- 脚本运行:
- 在
package.json的scripts字段中定义自定义脚本,如构建、测试、部署等任务。 - 使用
npm run <script-name>可以运行这些脚本。
- 在
- 包发布:
- 开发者可以将自己的代码打包并发布到 npm 官方仓库。
- 也可以搭建私有注册表,用于内部包的管理和分发。
- 生命周期钩子:
- npm 提供了多种生命周期钩子(如
preinstall、postinstall、prepublish等),允许在包的安装、测试、发布等过程中执行自定义脚本。
- npm 提供了多种生命周期钩子(如
npm 的使用
- 安装 npm:
- npm 通常与 Node.js 一起安装。安装 Node.js 后,npm 也会随之安装。
- 可以通过
npm -v命令检查 npm 是否安装成功。
- 初始化项目:
- 使用
npm init命令可以创建一个package.json文件,记录项目的元数据和依赖信息。
- 使用
- 常用命令:
- 安装依赖:
npm install或npm install <package>。 - 更新依赖:
npm update或npm update <package>。 - 卸载依赖:
npm uninstall <package>。 - 查看已安装的包:
npm list。 - 清除缓存:
npm cache clean --force。
- 安装依赖:
高级用法
- 私有包和作用域:
- 使用作用域(如
@myorg/mypackage)可以组织相关包,并创建私有包。 - 发布私有包需要付费账户或组织。
- 使用作用域(如
- 镜像源:
- 由于 npm 官方服务器在国外,国内用户可以使用淘宝镜像(如
cnpm)来加速包的下载。
- 由于 npm 官方服务器在国外,国内用户可以使用淘宝镜像(如
- 持续集成/持续部署(CI/CD):
- 在 CI/CD 环境中,使用
npm ci可以严格按照package-lock.json安装依赖。
- 在 CI/CD 环境中,使用
npm 是现代 JavaScript 开发中不可或缺的工具,它极大地提高了开发效率并简化了依赖管理。
yarn
Yarn 是一个现代的包管理工具,旨在提高 JavaScript 项目的依赖管理和安装速度。以下是 Yarn 的基本用法,包括初始化项目、安装依赖、更新依赖、运行脚本等常见操作。
1. 安装 Yarn
在安装 Yarn 之前,需要确保已经安装了 Node.js。可以通过以下命令安装 Yarn:
使用 npm 安装 Yarn:
bash复制
npm install --global yarn
验证 Yarn 是否安装成功:
bash复制
yarn --version
如果返回版本号,则表示 Yarn 已正确安装。
2. 初始化项目
在项目的根目录下运行以下命令,创建 package.json 文件:
bash复制
yarn init
按照提示输入项目信息(如名称、版本、描述、入口文件等)。也可以使用 -y 或 --yes 选项快速生成默认配置:
bash复制
yarn init -y
3. 安装依赖
(1)安装项目依赖
在项目根目录下运行以下命令,安装指定的包,并将其添加到 package.json 的 dependencies 中:
bash复制
yarn add <package-name>
例如:
bash复制
yarn add express
这会在项目中安装 express 包,并在 package.json 中添加如下内容:
JSON复制
"dependencies": {
"express": "^4.18.2"
}
(2)安装开发依赖
如果某些包仅在开发环境中使用(如测试工具、构建工具等),可以将其添加到 devDependencies:
bash复制
yarn add <package-name> --dev
或简写为:
bash复制
yarn add <package-name> -D
例如:
bash复制
yarn add jest -D
(3)安装全局包
某些工具(如 create-react-app)需要全局安装:
bash复制
yarn global add <package-name>
例如:
bash复制
yarn global add create-react-app
4. 更新依赖
更新项目中的某个依赖包:
bash复制
yarn upgrade <package-name>
更新所有依赖包:
bash复制
yarn upgrade
5. 卸载依赖
卸载项目中的某个依赖包:
bash复制
yarn remove <package-name>
6. 运行脚本
在 package.json 的 scripts 字段中定义脚本:
JSON复制
"scripts": {
"start": "node index.js",
"test": "jest"
}
运行脚本:
bash复制
yarn run <script-name>
例如:
bash复制
yarn run start
yarn run test
也可以省略 run,直接运行:
bash复制
yarn start
yarn test
7. 查看已安装的包
查看项目中已安装的包:
bash复制
yarn list
查看全局已安装的包:
bash复制
yarn global list
8. 清理缓存
Yarn 会缓存已安装的包,以加快后续安装速度。如果需要清理缓存,可以运行:
bash复制
yarn cache clean
9. 切换镜像源
由于 Yarn 默认使用的是官方源,可能会受到网络问题的影响。可以切换到国内镜像源以提高下载速度。
查询当前使用的镜像源:
bash复制
yarn config get registry
切换到国内镜像源(如淘宝镜像):
bash复制
yarn config set registry https://registry.npmmirror.com/
切换回官方源:
bash复制
yarn config set registry https://registry.yarnpkg.com/
10. 其他常用命令
查看包信息:
bash复制
yarn info <package-name>搜索包:
bash复制
yarn search <keyword>查看 Yarn 配置:
bash复制
yarn config list
11. 使用 yarn.lock 文件
Yarn 使用 yarn.lock 文件来锁定依赖版本,确保在不同机器上安装的依赖完全一致。在项目中,yarn.lock 文件会自动生成,不要手动修改它。如果需要重新生成 yarn.lock 文件,可以删除旧文件后运行:
bash复制
yarn install
12. 离线模式
Yarn 支持离线模式,可以在没有网络的情况下安装依赖。确保本地缓存中有相关包后,运行:
bash复制
yarn install --offline
通过以上命令和操作,你可以高效地使用 Yarn 来管理项目的依赖、运行脚本和发布包。Yarn 的设计目标是快速、可靠和安全,适合现代 JavaScript 项目的开发需求。
内置模块(http模块)
Node.js 的 http 模块是一个内置模块,用于创建 HTTP 服务器和客户端。它提供了底层的 HTTP 功能,允许开发者构建高性能的 HTTP 应用程序。以下是关于 Node.js 中 http 模块的详细介绍和使用方法。
1. 创建 HTTP 服务器
使用 http 模块可以轻松创建一个 HTTP 服务器。以下是一个简单的示例:
const http = require('http');
// 创建 HTTP 服务器
const server = http.createServer((req, res) => {
// 设置响应头
res.writeHead(200, { 'Content-Type': 'text/plain' });
// 发送响应内容
res.end('Hello, World!\n');
});
// 监听端口
const PORT = 3000;
server.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
代码解析
http.createServer():创建一个 HTTP 服务器实例。- 它接受一个回调函数,该回调函数会在每次请求到达时被调用。
- 回调函数的参数:
req:http.IncomingMessage对象,表示客户端的请求。res:http.ServerResponse对象,用于向客户端发送响应。
res.writeHead():设置响应头,包括状态码和响应头字段。res.end():结束响应,发送响应内容到客户端。server.listen():让服务器监听指定的端口。
2. 处理不同的 HTTP 请求
可以通过检查 req 对象的属性来处理不同的请求路径和方法。
const http = require('http');
const server = http.createServer((req, res) => {
const { method, url } = req;
if (method === 'GET' && url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>Welcome to the Home Page</h1>');
} else if (method === 'GET' && url === '/about') {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<h1>About Us</h1>');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
});
const PORT = 3000;
server.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
3. 处理 POST 请求
处理 POST 请求时,需要从请求体中读取数据。可以通过监听 data 和 end 事件来实现。
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/submit') {
let body = '';
// 监听 data 事件,读取数据
req.on('data', (chunk) => {
body += chunk.toString();
});
// 监听 end 事件,处理数据
req.on('end', () => {
console.log('Received POST data:', body);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`You sent: ${body}`);
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
});
const PORT = 3000;
server.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
4. 发送 HTTP 请求(客户端)
http 模块也可以用于发送 HTTP 请求。以下是一个发送 GET 请求的示例:
const http = require('http');
const options = {
hostname: 'example.com',
port: 80,
path: '/',
method: 'GET',
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
// 结束请求
req.end();
5. 使用 HTTP 模块的优势
- 轻量级:
http模块是 Node.js 的内置模块,无需额外安装。 - 高性能:基于 Node.js 的非阻塞 I/O 模型,可以处理高并发请求。
- 灵活性:提供了底层的 HTTP 功能,可以自定义请求和响应的处理逻辑。
6. 与其他框架的比较
虽然 http 模块功能强大,但在实际开发中,通常会使用更高级的框架(如 Express.js)来简化开发过程。Express.js 基于 http 模块,提供了路由、中间件、模板引擎等高级功能,适合构建复杂的 Web 应用程序。
示例:使用 Express.js 创建服务器
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
总结
Node.js 的 http 模块是一个强大的工具,适用于构建高性能的 HTTP 服务器和客户端。它提供了底层的 HTTP 功能,允许开发者自定义请求和响应的处理逻辑
内置模块(url模块)
Node.js 的 url 模块是一个非常重要的内置模块,用于处理和解析 URL。它提供了多种方法和属性,可以帮助开发者轻松地解析、构建和操作 URL。以下是 url 模块的主要功能和用法:
1. 解析 URL
url.parse() 方法可以将一个 URL 字符串解析为一个对象,包含 URL 的各个组成部分。
const url = require('url');
const urlString = 'http://example.com:8080/path/to/file?query=123#hash';
const parsedUrl = url.parse(urlString);
console.log(parsedUrl);
输出示例:
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'example.com:8080',
port: '8080',
hostname: 'example.com',
hash: '#hash',
search: '?query=123',
query: 'query=123',
pathname: '/path/to/file',
path: '/path/to/file?query=123',
href: 'http://example.com:8080/path/to/file?query=123#hash'
}
2. 构建 URL
url.format() 方法可以将一个 URL 对象或字符串重新格式化为一个完整的 URL 字符串。
const url = require('url');
const urlObject = {
protocol: 'http:',
hostname: 'example.com',
port: 8080,
pathname: '/path/to/file',
query: 'query=123',
hash: '#hash'
};
const formattedUrl = url.format(urlObject);
console.log(formattedUrl); // 输出: http://example.com:8080/path/to/file?query=123#hash
3. 解析查询字符串
url.parse() 方法解析 URL 后,会将查询字符串部分存储在 query 属性中。如果需要进一步解析查询字符串,可以使用 querystring 模块。
const url = require('url');
const querystring = require('querystring');
const urlString = 'http://example.com/path/to/file?query=123&name=Kimi#hash';
const parsedUrl = url.parse(urlString);
const query = querystring.parse(parsedUrl.query);
console.log(query); // 输出: { query: '123', name: 'Kimi' }
4. URL 模块的现代替代:URL 和 URLSearchParams
从 Node.js v10 开始,引入了与浏览器一致的 URL 和 URLSearchParams API,这些 API 更现代化且功能更强大。
const { URL, URLSearchParams } = require('url');
// 解析 URL
const urlString = 'http://example.com:8080/path/to/file?query=123#hash';
const myUrl = new URL(urlString);
console.log(myUrl.protocol); // http:
console.log(myUrl.hostname); // example.com
console.log(myUrl.port); // 8080
console.log(myUrl.pathname); // /path/to/file
console.log(myUrl.search); // ?query=123
console.log(myUrl.hash); // #hash
// 解析查询字符串
const searchParams = new URLSearchParams(myUrl.search);
console.log(searchParams.get('query')); // 123
// 构建 URL
const newUrl = new URL('/path/to/file', 'http://example.com');
newUrl.search = 'query=123';
newUrl.hash = '#hash';
console.log(newUrl.href); // http://example.com/path/to/file?query=123#hash
5. 使用场景
- 解析请求 URL:在 HTTP 服务器中,解析客户端请求的 URL,提取路径、查询参数等信息。
- 构建响应 URL:根据业务逻辑动态生成 URL,用于重定向或生成链接。
- 处理查询参数:方便地操作查询字符串,例如添加、删除或修改查询参数。
总结
Node.js 的 url 模块提供了丰富的功能,用于处理和解析 URL。虽然传统的 url.parse() 和 url.format() 方法仍然可用,但推荐使用现代的 URL 和 URLSearchParams API,因为它们更符合现代 JavaScript 的规范,并且功能更强大、更易于使用。
内置模块(querstring模块)
querystring 是 Node.js 的一个内置模块,用于处理查询字符串(URL 中的 ?key=value&... 部分)。它提供了两个主要功能:解析查询字符串和构建查询字符串。
1. 解析查询字符串
可以将查询字符串解析为一个对象。
const querystring = require('querystring');
const queryString = 'name=Kimi&age=25&city=Beijing';
const parsedQuery = querystring.parse(queryString);
console.log(parsedQuery);
// 输出:{ name: 'Kimi', age: '25', city: 'Beijing' }
2. 构建查询字符串
可以将一个对象转换为查询字符串。
const querystring = require('querystring');
const queryParams = { name: 'Kimi', age: 25, city: 'Beijing' };
const queryString = querystring.stringify(queryParams);
console.log(queryString);
// 输出:name=Kimi&age=25&city=Beijing
node 解决跨域问题
在 Node.js 中解决跨域问题(CORS)有多种方法,以下是几种常见的解决方案:
1. 使用 cors 中间件
cors 是一个专门用于解决跨域问题的 Node.js 中间件,非常简单易用。
安装
bash复制
npm install cors
使用示例
JavaScript复制
const express = require('express');
const cors = require('cors');
const app = express();
// 允许所有来源访问
app.use(cors());
// 或者指定特定来源
app.use(cors({
origin: 'http://example.com'
}));
app.get('/data', (req, res) => {
res.json({ message: 'This is CORS-enabled for only example.com.'