JavaScript Node.js 如何使用第三方模块
简介
在 Node.js(V8 引擎)中,第三方模块通过 npm(Node Package Manager) 来安装和管理。npm 是全球最大的软件注册表,包含数十万个开源包。
参考文档:
js-nodejs-api.md— Node.js 核心模块和 CommonJS/ES Modules 基础js-browser-modules.md— 浏览器中的第三方模块使用(CDN、ES Modules 等)
npm(Node Package Manager)
检查 npm 版本
npm --version
# 输出:如 9.0.0(与 Node.js 版本相关)
npm init — 初始化项目
# 交互式创建 package.json
npm init
# 使用默认值快速创建
npm init -y
npm install — 安装包
# 本地安装(项目依赖,记录在 package.json)
npm install lodash
npm install express
# 指定版本
npm install [email protected]
npm install [email protected]
# 作为开发依赖安装(只在开发时使用)
npm install --save-dev jest
npm install -D jest # 简写
# 从 Git 仓库安装
npm install git+https://github.com/user/repo.git
# 从本地目录安装
npm install ./my-local-package
npm uninstall — 卸载包
npm uninstall lodash
npm uninstall --save-dev jest # 卸载开发依赖
npm update — 更新包
# 更新所有包
npm update
# 更新指定包
npm update lodash
npm list — 查看已安装的包
# 查看项目依赖树
npm list
# 查看全局安装的包
npm list -g
# 只看顶层依赖
npm list --depth=0
npx — 临时执行包
# 无需全局安装,临时执行包的命令
npx create-react-app my-app
npx vite # 启动 Vite(无需安装)
# 执行后不会留在 node_modules 中(临时使用)
package.json 详解
运行 npm init -y 会生成 package.json 文件。
基本结构
{
"name": "my-project",
"version": "1.0.0",
"description": "A Node.js project",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "jest",
"build": "vite build"
},
"keywords": ["node", "express"],
"author": "Alice",
"license": "ISC",
"dependencies": {
"express": "^4.18.0",
"lodash": "^4.17.21"
},
"devDependencies": {
"jest": "^29.0.0"
},
"engines": {
"node": ">=18.0.0"
}
}
dependencies vs devDependencies
| 类型 | 说明 | 安装命令 | 使用场景 |
|---|---|---|---|
dependencies |
生产依赖,项目运行时需要 | npm install <pkg> |
Express、Lodash、Axios 等 |
devDependencies |
开发依赖,只在开发时使用 | npm install -D <pkg> |
Jest、Vite、ESLint 等 |
# 安装生产依赖(默认)
npm install express
# 安装开发依赖
npm install -D jest
# 只安装生产依赖(部署时)
npm install --production # 或 NODE_ENV=production npm install
scripts 脚本
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"build": "vite build",
"test": "jest",
"test:watch": "jest --watch",
"prestart": "echo '准备启动...'",
"poststart": "echo '已停止'",
"lint": "eslint src/"
}
}
npm start # 执行 start 脚本
npm run build # 执行 build 脚本(非 start/test 等默认脚本需加 run)
npm run lint # 执行 lint 脚本
npm test # npm test 是 npm run test 的简写
语义化版本(Semantic Versioning)
版本格式:主版本.次版本.修订号(如 4.18.0)
| 符号 | 含义 | 示例 | 说明 |
|---|---|---|---|
^ |
兼容版本 | ^4.18.0 |
允许更新次版本和修订号(4.x.x) |
~ |
近似版本 | ~4.18.0 |
只允许更新修订号(4.18.x) |
>= |
大于等于 | >=4.18.0 |
允许任何大于等于该版本的版本 |
* |
任意版本 | * |
总是使用最新版本 |
| 无前缀 | 精确版本 | 4.18.0 |
只使用指定版本 |
{
"dependencies": {
"express": "^4.18.0", // 可更新到 4.x.x,不更新到 5.0.0
"lodash": "~4.17.21", // 可更新到 4.17.x,不更新到 4.18.0
"axios": "1.6.0" // 精确版本,只使用 1.6.0
}
}
package-lock.json 的作用
package-lock.json 锁定依赖的精确版本,确保团队成员和部署环境安装完全相同的依赖版本。
# package-lock.json 会自动生成和更新
# 不要手动修改它
# 提交到版本控制系统(Git)
# 根据 package-lock.json 精确安装
npm ci # 比 npm install 更快,用于 CI/CD 环境
本地安装 vs 全局安装
本地安装(推荐)
# 本地安装(默认)
npm install express
# 包安装在 ./node_modules/ 目录
# 依赖记录在 package.json 的 dependencies 中
// 本地安装的包通过 require() 或 import 使用
const express = require('express');
// 或
import express from 'express';
全局安装
# 全局安装(-g 或 --global)
npm install -g nodemon
npm install -g pm2
# 全局安装的包可以作为命令行工具使用
nodemon index.js
pm2 start index.js
# 查看全局安装位置
npm root -g
# 输出:如 C:\Users\VanMek\AppData\Roaming\npm\node_modules
# 列出全局安装的包
npm list -g --depth=0
对比
| 特性 | 本地安装 | 全局安装 |
|---|---|---|
| 安装位置 | ./node_modules/ |
全局目录(如 ~/.npm-global/) |
| 记录在 | package.json |
不记录(除非手动) |
| 用途 | 项目依赖(代码中使用) | 命令行工具(如 nodemon、pm2) |
| 可移植性 | 高(package.json 可共享) | 低(其他机器可能没有) |
| 推荐场景 | 绝大多数情况 | 命令行工具 |
node_modules 目录
结构
project/
├── node_modules/
│ ├── express/
│ │ ├── lib/
│ │ ├── package.json
│ │ └── ...
│ ├── lodash/
│ └── ...
├── package.json
└── index.js
查找规则
当使用 require('express') 时,Node.js 按以下顺序查找:
- 如果是核心模块(如
fs、path),直接返回 - 查找当前目录的
node_modules/express - 如果没找到,查找上级目录的
node_modules/express - 继续向上查找,直到文件系统根目录
/project/a/b/c/
require('express') 查找顺序:
/project/a/b/c/node_modules/express
/project/a/b/node_modules/express
/project/a/node_modules/express
/project/node_modules/express
/node_modules/express ← 全局(如果配置)
注意:通常将
node_modules/添加到.gitignore,不提交到 Git。
CommonJS 方式引入第三方模块
基本语法
// 导入默认导出
const express = require('express');
const _ = require('lodash');
// 导入命名导出
const { debounce, throttle } = require('lodash');
// 导入子路径
const router = require('express').Router;
示例:使用 Lodash
npm install lodash
const _ = require('lodash');
// 防抖(debounce)
let debounced = _.debounce((msg) => {
console.log('防抖:', msg);
}, 500);
// 节流(throttle)
let throttled = _.throttle((msg) => {
console.log('节流:', msg);
}, 200);
// 数组操作
let arr = [1, 2, 2, 3, 3, 3];
console.log(_.uniq(arr)); // [1, 2, 3]
// 深拷贝
let obj = { a: { b: 1 } };
let cloned = _.cloneDeep(obj);
cloned.a.b = 2;
console.log(obj.a.b); // 1(未被影响)
示例:使用 Express
npm install express
const express = require('express');
const app = express();
// 中间件
app.use(express.json());
// 路由
app.get('/', (req, res) => {
res.send('Hello Express!');
});
app.get('/api/users', (req, res) => {
res.json([{ id: 1, name: 'Alice' }]);
});
app.post('/api/users', (req, res) => {
console.log('收到数据:', req.body);
res.status(201).json({ id: 2, ...req.body });
});
// 启动服务器
app.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});
ES Modules 方式引入第三方模块
配置方式
方式 1:在 package.json 中添加 "type": "module"
{
"name": "my-project",
"version": "1.0.0",
"type": "module"
}
方式 2:使用 .mjs 扩展名
// app.mjs
import express from 'express'; // 默认导入
import { debounce } from 'lodash-es'; // 命名导入(需要 lodash-es 包)
示例:ESM 中使用第三方包
npm install express
npm install lodash-es # Lodash 的 ESM 版本
// index.mjs 或 package.json 中 "type": "module"
import express from 'express';
import { debounce } from 'lodash-es';
const app = express();
app.get('/', (req, res) => {
res.send('Hello ESM!');
});
// 使用 lodash-es
const debounced = debounce((msg) => {
console.log(msg);
}, 500);
app.listen(3000);
CommonJS 与 ESM 互操作
// ESM 中导入 CommonJS 模块(通常可以)
import express from 'express'; // express 是 CommonJS 包,但可以导入
// CommonJS 中导入 ESM 模块(不能直接 require)
// const lodash = require('lodash-es'); // ❌ 错误!ESM 包不能用 require
// CommonJS 中可以使用动态 import(返回 Promise)
async function loadLodash() {
const lodash = await import('lodash-es');
console.log(lodash.debounce);
}
常用第三方库使用示例
Express — Web 框架
npm install express
npm install -D nodemon # 开发时自动重启
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
}
}
const express = require('express');
const app = express();
// 内置中间件
app.use(express.json()); // 解析 JSON 请求体
app.use(express.static('public')); // 静态文件服务
// 自定义中间件
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next(); // 调用 next() 继续处理
});
// 路由
app.get('/', (req, res) => {
res.send('首页');
});
app.get('/api/users/:id', (req, res) => {
res.json({ id: req.params.id, name: 'Alice' });
});
// 错误处理中间件(4 个参数)
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('服务器错误!');
});
app.listen(3000);
Axios — HTTP 客户端
npm install axios
const axios = require('axios');
// GET 请求
axios.get('https://api.example.com/users')
.then(res => console.log(res.data))
.catch(err => console.error(err));
// POST 请求
axios.post('https://api.example.com/users', {
name: 'Alice',
age: 25
})
.then(res => console.log('创建成功:', res.data))
.catch(err => console.error(err));
// 使用 async/await
async function fetchData() {
try {
let res = await axios.get('https://api.example.com/data');
console.log(res.data);
} catch (err) {
console.error('请求失败:', err.message);
}
}
// 设置默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer token';
Day.js — 轻量级日期库
npm install dayjs
const dayjs = require('dayjs');
// 解析和格式化
console.log(dayjs().format('YYYY-MM-DD HH:mm:ss')); // "2024-05-15 10:30:45"
// 日期运算
console.log(dayjs().add(1, 'day').format('YYYY-MM-DD')); // 明天
console.log(dayjs().subtract(1, 'week').format('YYYY-MM-DD')); // 上周
// 日期比较
let date1 = dayjs('2024-01-01');
let date2 = dayjs('2024-12-31');
console.log(date1.isBefore(date2)); // true
console.log(date1.isSame(date2, 'year')); // true(同年)
// 相对时间(需要插件)
// const relativeTime = require('dayjs/plugin/relativeTime');
// dayjs.extend(relativeTime);
// console.log(dayjs('2024-05-10').fromNow()); // "5 天前"
Jest — 测试框架
npm install -D jest
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch"
}
}
// math.js
function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }
module.exports = { add, subtract };
// math.test.js
const { add, subtract } = require('./math');
test('add 函数应该正确相加', () => {
expect(add(1, 2)).toBe(3);
expect(add(-1, 1)).toBe(0);
});
test('subtract 函数应该正确相减', () => {
expect(subtract(5, 3)).toBe(2);
expect(subtract(0, 0)).toBe(0);
});
npm test # 运行测试
Dotenv — 环境变量管理
npm install dotenv
// .env 文件
// DB_HOST=localhost
// DB_PORT=5432
// SECRET_KEY=my-secret-key
require('dotenv').config(); // 加载 .env 文件
console.log(process.env.DB_HOST); // "localhost"
console.log(process.env.DB_PORT); // "5432"(注意是字符串)
console.log(process.env.SECRET_KEY); // "my-secret-key"
// 也可以指定路径
require('dotenv').config({ path: './config/.env' });
CORS — 跨域处理
npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
// 启用 CORS(允许所有来源)
app.use(cors());
// 自定义 CORS 配置
app.use(cors({
origin: 'https://example.com', // 只允许该来源
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
// 单个路由启用 CORS
app.get('/api/data', cors(), (req, res) => {
res.json({ msg: 'hello' });
});
创建和发布自己的包
创建包
mkdir my-package
cd my-package
npm init -y
{
"name": "my-awesome-package",
"version": "1.0.0",
"description": "A awesome package",
"main": "index.js",
"keywords": ["utility", "helper"],
"author": "Alice <[email protected]>",
"license": "MIT"
}
// index.js
function myFunction() {
return 'Hello from my package!';
}
module.exports = { myFunction };
发布到 npm
# 1. 登录 npm(首次需要注册账号 https://www.npmjs.com/)
npm login
# 2. 发布
npm publish
# 3. 更新版本后重新发布
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
npm publish
.npmignore 文件
node_modules/
test/
.gitignore
*.log
.DS_Store
npm 脚本(scripts)
自定义脚本
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"build": "vite build",
"test": "jest",
"lint": "eslint src/",
"clean": "rm -rf dist/",
"predeploy": "npm run clean && npm run build",
"deploy": "gh-pages -d dist/"
}
}
生命周期脚本
{
"scripts": {
"prestart": "echo '准备启动...'",
"start": "node index.js",
"poststart": "echo '已停止'",
"prebuild": "rimraf dist",
"build": "vite build",
"postbuild": "echo '构建完成'"
}
}
跨平台脚本
npm install -D cross-env
{
"scripts": {
"dev": "cross-env NODE_ENV=development nodemon index.js",
"build": "cross-env NODE_ENV=production webpack"
}
}
综合示例
示例 1:Express + Lodash + Axios 构建 API
npm init -y
npm install express lodash axios cors
npm install -D nodemon
{
"name": "my-api",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "nodemon index.js",
"start": "node index.js"
},
"dependencies": {
"express": "^4.18.0",
"lodash-es": "^4.17.21",
"axios": "^1.6.0",
"cors": "^2.8.5"
}
}
import express from 'express';
import _ from 'lodash-es';
import axios from 'axios';
import cors from 'cors';
const app = express();
app.use(cors());
app.use(express.json());
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 }
];
// 获取所有用户
app.get('/api/users', (req, res) => {
res.json(users);
});
// 获取单个用户
app.get('/api/users/:id', (req, res) => {
let user = _.find(users, { id: parseInt(req.params.id) });
if (user) {
res.json(user);
} else {
res.status(404).json({ error: '用户未找到' });
}
});
// 代理请求外部 API
app.get('/api/external', async (req, res) => {
try {
let result = await axios.get('https://jsonplaceholder.typicode.com/users');
res.json(result.data);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000, () => {
console.log('API 服务器运行在 http://localhost:3000');
});
示例 2:使用 npm scripts 自动化任务
{
"scripts": {
"clean": "rimraf dist",
"copy:html": "cpx index.html dist/",
"copy:css": "cpx styles.css dist/",
"build": "npm run clean && npm run copy:html && npm run copy:css",
"serve": "http-server dist -p 8080",
"dev": "npm run build && npm run serve"
}
}
npm run dev # 构建并启动服务
示例 3:本地开发与生产环境配置(Dotenv)
npm install dotenv
# .env.development
NODE_ENV=development
API_URL=http://localhost:3000
# .env.production
NODE_ENV=production
API_URL=https://api.example.com
const express = require('express');
const app = express();
// 根据环境加载不同的 .env 文件
const env = process.env.NODE_ENV || 'development';
require('dotenv').config({ path: `.env.${env}` });
console.log('环境:', process.env.NODE_ENV);
console.log('API URL:', process.env.API_URL);
app.get('/', (req, res) => {
res.send(`环境: ${process.env.NODE_ENV}`);
});
app.listen(3000);
# 开发环境
npm run dev
# 生产环境
NODE_ENV=production npm start
总结:Node.js 第三方模块使用速查表
| 操作 | 命令 | 说明 |
|---|---|---|
| 初始化项目 | npm init -y |
创建 package.json |
| 本地安装 | npm install <pkg> |
安装到 node_modules/ |
| 开发依赖 | npm install -D <pkg> |
安装到 devDependencies |
| 全局安装 | npm install -g <pkg> |
作为命令行工具 |
| 卸载包 | npm uninstall <pkg> |
从 package.json 移除 |
| 更新包 | npm update <pkg> |
按语义化版本更新 |
| 查看依赖 | npm list --depth=0 |
查看顶层依赖 |
| 临时执行 | npx <pkg> |
无需安装,临时使用 |
| 运行脚本 | npm start |
执行 package.json 中的 scripts |
| 发布包 | npm publish |
发布到 npm 注册表 |
| 登录 npm | npm login |
登录 npm 账号 |
重要提示:本文档介绍的是 Node.js 特有的第三方模块管理(npm)。浏览器中的第三方模块使用请参考
js-browser-modules.md。