今天我们聚焦 Node.js 进阶必备技能 ------ 模块化(含 CommonJS+ES6 两种规范)、包管理、Express 框架和跨域解决方案。这是从 "零散代码" 到 "规范项目" 的关键跨越,新手也能快速上手!
一、模块化:Node.js 的代码组织核心(CommonJS+ES6 双规范)
模块化的核心目的是拆分代码、解决命名冲突、提高复用性。Node.js 默认支持 CommonJS 规范(传统方案),同时也兼容 ES6 模块化(现代前端 / Node.js 14.13 + 支持),两种规范都要掌握!
1. 传统方案:CommonJS 规范(Node.js 默认)
Node.js 原生支持的模块化规范,核心是require()导入、module.exports/exports导出,适合 Node.js 后端项目。
(1)核心语法
- 导出模块:单个导出 / 批量导出
javascript
// 模块文件:utils.js
// 方式1:批量导出(推荐,清晰直观)
const add = (a, b) => a + b;
const sub = (a, b) => a - b;
module.exports = { add, sub }; // 导出一个对象
// 方式2:单个导出(也可给exports赋值)
// exports.add = add;
// exports.sub = sub;
- 导入模块:整体导入 / 解构导入
javascript
// 主文件:index.js
// 方式1:解构导入(按需获取)
const { add, sub } = require('./utils.js');
console.log(add(2, 3)); // 输出5
console.log(sub(10, 4)); // 输出6
// 方式2:整体导入(获取整个导出对象)
const utils = require('./utils.js');
console.log(utils.add(2, 3)); // 输出5
(2)CommonJS 关键特性
- 运行时加载:导入时会执行整个模块文件,返回导出对象的拷贝
- 动态导入:
require()可写在代码任意位置(如条件判断中) - 路径规则:导入本地模块需写相对路径(.//.../),导入内置模块(如 fs)或 npm 包可直接写名称
2.现代方案:ES6 模块化(兼容前端 / Node.js)
ES6 模块化是 ECMAScript 标准规范,核心是import导入、export导出,统一了前端(Vue/React)和后端(Node.js)的模块化语法,更推荐长期使用。
(1)Node.js 启用 ES6 模块的前提
Node.js 默认不识别import/export,需满足以下任一条件:
- 文件名后缀改为
.mjs - 在
package.json中添加配置:"type": "module"(推荐,整个项目生效)
json
// package.json
{
"type": "module" // 声明项目使用ES6模块化
}
(2)核心语法
- 导出模块:默认导出 / 命名导出
javascript
// 模块文件:utils.mjs(或package.json设type:module后用.js)
// 方式1:命名导出(可多个)
export const add = (a, b) => a + b;
export const sub = (a, b) => a - b;
// 方式2:默认导出(只能一个,可导出任意类型)
export default {
multiply: (a, b) => a * b,
divide: (a, b) => a / b
};
- 导入模块:对应命名导入 / 默认导入
javascript
// 主文件:index.js(package.json已设type:module)
// 方式1:命名导入(必须和导出名称一致,可重命名)
import { add, sub as subtract } from './utils.js';
console.log(add(2, 3)); // 输出5
console.log(subtract(10, 4)); // 输出6
// 方式2:默认导入(名称可自定义)
import calc from './utils.js';
console.log(calc.multiply(3, 4)); // 输出12
console.log(calc.divide(10, 2)); // 输出5
// 方式3:整体导入(导入所有命名导出和默认导出)
import * as allUtils from './utils.js';
console.log(allUtils.add(2,3)); // 输出5
console.log(allUtils.default.multiply(3,4)); // 输出12
(3)ES6 模块化关键特性
- 编译时加载:导入时只加载需要的部分(静态分析),更高效
- 静态导入:
import必须写在文件顶部,不能写在条件判断中 - 跨端兼容:语法和前端框架(Vue/React)一致,无需切换思维
新手建议:如果是纯 Node.js 后端项目,CommonJS 足够简单;如果需要和前端协同开发(如全栈项目),优先用 ES6 模块化,统一语法减少混乱。
二、包:Node.js 的 "工具仓库"
"包" 是多个模块的集合(包含package.json配置文件),是 Node.js 生态的核心。通过npm(Node 包管理器) 可快速下载、管理第三方包(如 Express、cors)
1. npm 基础操作(必备)
- 初始化项目:生成
package.json(项目配置文件,记录依赖、脚本等)
bash
npm init -y # -y表示默认配置,无需手动输入
- 安装包:
bash
# 1. 生产依赖(项目运行必需,如express)
npm install express
# 2. 开发依赖(仅开发时用,如nodemon自动重启服务)
npm install nodemon --save-dev
# 3. 全局安装(全局可用,如npm-check-updates更新依赖)
npm install -g npm-check-updates
- 使用包:无论是 CommonJS 还是 ES6 模块,导入方式一致
javascript
// CommonJS
const express = require('express');
// ES6模块化(package.json设type:module)
import express from 'express';
- 卸载包:
bash
npm uninstall express # 卸载生产依赖
npm uninstall nodemon --save-dev # 卸载开发依赖
2. package.json 的核心作用
- 记录项目依赖的包及版本(避免 "我本地能跑,线上跑不了")
- 配置脚本命令(简化启动、构建等操作):
json
{
"scripts": {
"start": "node index.js", // 普通启动
"dev": "nodemon index.js" // 开发时自动重启
}
}
运行脚本:npm run dev(启动开发服务)、npm start(启动生产服务)
三、Express 框架:Web 开发的 "快捷键"
之前用原生http模块写接口繁琐,Express是 Node.js 最流行的 Web 框架,封装了路由、中间件、响应处理等功能,能 10 倍提升接口开发效率!
1. 快速搭建 Express 服务(ES6 模块化示例)
javascript
/**
* 目标:基于 express 软件包,开发 Web 服务返回资源给用户
* 1. 下载 express 软件包
* 2. 导入 express 并创建服务对象
* 3. 监听请求方法和请求路径
* 4. 对其他路径返回 404 提示 (设置状态码)
* 5. 设置监听端口号
*/
// 2.导入 express 并创建服务对象
const express = require('express')
const server = express()
// 监听 get 请求
// server.get
server.get('/', (req, res) => {
// 全自动设置响应头
res.send("你好世界")
})
// 版本不兼容
// server.get('/*', (req, res) => {
// // 修改状态码
// res.status(404)
// // 响应文本内容
// res.send('您访问的资源不存在')
// })
// 终极 404 写法(替换原来的 server.get('/*', ...))
server.use((req, res) => {
res.status(404).send('您访问的资源不存在')
})
// 开启服务
server.listen(3000 ,() => {
console.log('服务器已启动')
})
启动后访问http://localhost:3000 ,即可看到 JSON 响应,无需手动设置响应头!
结果演示:

2.Express 核心优势
- 路由简洁:
server.get()/server.post()快速定义接口 - 响应便捷:
res.json()/res.send()/res.status()简化响应操作 - 中间件生态:支持日志、跨域、解析请求体等各类中间件
四、跨域:前端请求后端的 "拦路虎"
浏览器的同源策略(协议、域名、端口必须一致)会阻止前端(如http://localhost:8080)请求后端接口(如http://localhost:3000),这就是跨域问题。Express 用cors中间件可轻松解决!
1. 解决跨域步骤
- 第一步:安装 cors 包
bash
npm install cors
- 第二步:在 Express 中启用(ES6 模块化示例)
javascript
import express from 'express';
import cors from 'cors'; // 导入cors
import fs from 'fs/promises';
import path from 'path';
const app = express();
const port = 3000;
// 关键:启用cors中间件(允许所有跨域请求)
app.use(cors());
// 省份接口(前端可跨域请求)
app.get('/api/province', async (req, res) => {
const filePath = path.join(process.cwd(), 'data/province.json');
const data = await fs.readFile(filePath, 'utf-8');
res.json(JSON.parse(data));
});
app.listen(port, () => {
console.log(`跨域服务启动:http://localhost:${port}/api/province`);
});
2. 跨域原理
cors中间件会在响应头中添加:
plaintext
Access-Control-Allow-Origin: *
表示 "允许所有域名请求该接口",浏览器收到后会绕过同源策略限制,前端即可正常请求。