Node.js模块化开发教学演示步骤:
- 环境准备:演示npm初始化、安装依赖
- 工具演示:展示nodemon、nrm的使用
- Gulp构建:逐步演示每个插件的配置和使用
- 模块系统:演示不同模块规范的导入导出
- 实战演练:让学生跟着完成一个完整的小项目
案例一:使用nodemon和nrm工具
演示代码:server.js
javascript
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<title>Node.js服务器</title>
</head>
<body>
<h1>欢迎学习Node.js!</h1>
<p>当前时间:${new Date().toLocaleString()}</p>
<p>修改这个文件,nodemon会自动重启服务器</p>
</body>
</html>
`);
});
server.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});
演示步骤:
- 安装工具:
npm install -g nodemon nrm - 查看镜像源:
nrm ls - 切换到淘宝镜像:
nrm use taobao - 启动服务器:
nodemon server.js - 修改文件内容,观察自动重启
异常处理
nrm报错版本不兼容
如果暂时无法升级 Node.js,可以安装兼容旧版本的 NRM:
bash
bash
#### 卸载当前 nrm
npm uninstall -g nrm
#### 安装兼容旧版本的 nrm
npm install -g nrm@1.2
案例二:Gulp自动化构建项目
项目结构:
gulp-demo/
├── src/
│ ├── index.html
│ ├── css/
│ │ └── style.less
│ ├── js/
│ │ └── main.js
│ └── common/
│ └── header.html
├── dist/
└── gulpfile.js
gulpfile.js 配置:
javascript
const gulp = require('gulp');
const htmlmin = require('gulp-htmlmin');
const fileinclude = require('gulp-file-include');
const less = require('gulp-less');
const csso = require('gulp-csso');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
// HTML任务:包含公共文件并压缩
gulp.task('htmlmin', () => {
return gulp.src('./src/*.html')
.pipe(fileinclude({
prefix: '@@',
basepath: '@file'
}))
.pipe(htmlmin({
collapseWhitespace: true,
removeComments: true
}))
.pipe(gulp.dest('dist'));
});
// CSS任务:转换Less并压缩
gulp.task('cssmin', () => {
return gulp.src('./src/css/*.less')
.pipe(less())
.pipe(csso())
.pipe(gulp.dest('dist/css'));
});
// JS任务:转换ES6并压缩
gulp.task('jsmin', () => {
return gulp.src('./src/js/*.js')
.pipe(babel({
presets: ['@babel/env']
}))
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
});
// 复制静态资源
gulp.task('copy', () => {
return gulp.src('./src/images/**/*')
.pipe(gulp.dest('dist/images'));
});
// 默认任务
gulp.task('default', gulp.parallel('htmlmin', 'cssmin', 'jsmin', 'copy'));
示例源文件:
src/common/header.html
html
<header>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/article.html">文章</a></li>
<li><a href="/about.html">关于</a></li>
</ul>
</nav>
</header>
src/index.html
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的网站</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
@@include('./common/header.html')
<main>
<h1>欢迎来到我的网站</h1>
<p>这是一个使用Gulp构建的示例项目</p>
</main>
<script src="js/main.js"></script>
</body>
</html>
src/css/style.less
less
@primary-color: #3498db;
@secondary-color: #2ecc71;
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
header {
background-color: @primary-color;
nav {
ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
li {
a {
color: white;
text-decoration: none;
padding: 15px 20px;
display: block;
&:hover {
background-color: darken(@primary-color, 10%);
}
}
}
}
}
}
main {
padding: 20px;
h1 {
color: @secondary-color;
}
}
src/js/main.js
javascript
// ES6语法示例
class Website {
constructor() {
this.init();
}
init() {
this.bindEvents();
this.loadData();
}
bindEvents() {
const buttons = document.querySelectorAll('button');
buttons.forEach(button => {
button.addEventListener('click', this.handleClick.bind(this));
});
}
handleClick(event) {
const message = `按钮 ${event.target.textContent} 被点击了!`;
console.log(message);
alert(message);
}
async loadData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log('加载的数据:', data);
} catch (error) {
console.error('加载数据失败:', error);
}
}
}
// 使用箭头函数和模板字符串
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000
};
const createWelcomeMessage = (userName) => {
return `欢迎, ${userName}! 当前时间: ${new Date().toLocaleString()}`;
};
// 初始化网站
document.addEventListener('DOMContentLoaded', () => {
new Website();
console.log(createWelcomeMessage('访客'));
});
案例三:模块导入导出演示
math.js (CommonJS方式)
javascript
// 导出单个函数
exports.add = (a, b) => a + b;
// 导出多个函数
exports.multiply = (a, b) => a * b;
// 导出常量
exports.PI = 3.14159;
// 默认导出
module.exports = {
add: exports.add,
multiply: exports.multiply,
PI: exports.PI
};
utils.mjs (ES6方式)
javascript
// 命名导出
export const capitalize = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
export const reverseString = (str) => {
return str.split('').reverse().join('');
};
// 默认导出
const formatDate = (date = new Date()) => {
return date.toLocaleDateString('zh-CN');
};
export default formatDate;
main.js (使用模块)
javascript
// CommonJS方式导入
const math = require('./math.js');
console.log('加法结果:', math.add(5, 3));
console.log('乘法结果:', math.multiply(4, 7));
// ES6方式导入 (需要设置 "type": "module" 在 package.json)
import formatDate, { capitalize, reverseString } from './utils.mjs';
console.log('格式化日期:', formatDate());
console.log('首字母大写:', capitalize('hello world'));
console.log('字符串反转:', reverseString('Node.js'));
案例四:文件操作演示
fileOperations.js
javascript
const fs = require('fs');
const path = require('path');
class FileManager {
constructor() {
this.baseDir = __dirname;
}
// 读取文件
readFile(filename) {
return new Promise((resolve, reject) => {
fs.readFile(path.join(this.baseDir, filename), 'utf8', (err, data) => {
if (err) reject(err);
else resolve(data);
});
});
}
// 写入文件
writeFile(filename, content) {
return new Promise((resolve, reject) => {
fs.writeFile(path.join(this.baseDir, filename), content, 'utf8', (err) => {
if (err) reject(err);
else resolve(`文件 ${filename} 写入成功`);
});
});
}
// 复制文件
async copyFile(source, target) {
try {
const content = await this.readFile(source);
await this.writeFile(target, content);
console.log(`文件从 ${source} 复制到 ${target}`);
} catch (error) {
console.error('复制文件失败:', error);
}
}
// 读取目录
readDirectory(dirPath) {
return new Promise((resolve, reject) => {
fs.readdir(path.join(this.baseDir, dirPath), (err, files) => {
if (err) reject(err);
else resolve(files);
});
});
}
}
// 使用示例
async function demoFileOperations() {
const fm = new FileManager();
try {
// 创建测试文件
await fm.writeFile('test.txt', '这是一个测试文件\n第二行内容\n第三行内容');
// 读取文件
const content = await fm.readFile('test.txt');
console.log('文件内容:', content);
// 复制到HTML文件
await fm.copyFile('test.txt', 'index.html');
// 列出当前目录文件
const files = await fm.readDirectory('.');
console.log('目录文件列表:', files);
} catch (error) {
console.error('操作失败:', error);
}
}
demoFileOperations();