Skip to content

🚀 NodeJS从零到一开发一个全栈项目 - 基础配置篇 ​

🚀 使用 Express 脚手架创建项目 ​

Express是Node.js最流行的Web应用框架,它提供了强大的功能来快速构建Web应用和API。使用Express Generator可以快速生成项目骨架,大大提升开发效率。

📦 第一步:安装 Express Generator ​

bash
npm i -g express-generator@4

🏗️ 第二步:创建项目 ​

Express Generator提供了多种项目创建方式,根据不同需求选择合适的模板:

bash
# 使用EJS模板引擎创建项目(适合需要服务端渲染的应用)
express --view=ejs demo 

# 不使用视图模板创建项目(适合纯API开发)
express --no-view demo

创建选项说明:

  • --view=ejs:使用EJS模板引擎,视图文件存放在views目录下,适合传统的服务端渲染应用
  • --no-view:不使用任何视图模板,专门用于后台API开发,前端页面渲染交给React、Vue等前端框架处理

⚡ 第三步:启动项目 ​

bash
cd demo
npm install
npm start

🔄 第四步:配置热重载开发环境 ​

在开发阶段,每次修改代码都需要手动重启服务会很麻烦。使用nodemon可以实现文件变化时自动重启服务:

  1. 安装nodemon:
bash
npm i -g nodemon
  1. 修改启动脚本: 在package.json文件中,将scripts下的启动命令进行修改:
json
// 原始配置
"start": "node ./bin/www"

// 修改为
"start": "nodemon ./bin/www"
  1. 重新启动项目:
bash
npm start

现在当您修改代码时,服务会自动重启,极大提升开发体验。

🐳 Docker 环境配置 ​

Docker是现代开发中不可或缺的容器化技术,它能够提供一致的开发环境,避免"在我机器上能跑"的问题。在本项目中,我们将使用Docker来运行MySQL数据库服务。

🚨 Docker 镜像下载问题解决方案 ​

问题背景: 根据最新情况,国内 Docker 镜像源普遍出现访问问题,包括阿里云镜像源已限制为仅在阿里云服务器上使用。

方案一:使用可用镜像源 ⭐️ ​

目前发现的可用镜像源配置:

json
{
  "registry-mirrors": [
    "https://docker.1ms.run"
  ]
}

方案二:配置代理访问 🔧 ​

如果上述镜像源失效,可以通过配置VPN代理来解决:

  1. 在Docker Desktop中打开设置
  2. 进入Resources → Proxies
  3. 配置代理服务器地址和端口

Docker代理配置

配置完成后重启Docker服务,即可正常拉取镜像。

方案三:Laragon 集成环境替代方案 💡 ​

适用场景: 无法安装Docker或代理配置困难的开发者

Laragon是一个轻量级的本地开发环境,集成了Apache、MySQL、PHP等服务,可以作为Docker的替代方案。

Laragon界面

⚠️ 重要配置说明:

由于Laragon的MySQL默认没有密码,在后续配置数据库连接时,需要修改config/config.json文件:

json
"development": {
  "username": "root",
  "password": null,          // 注意:这里是null值,不要加引号!
  "database": "clwy_api_development",
  "host": "127.0.0.1",
  "dialect": "mysql",
  "timezone": "+08:00",
  "logQueryParameters": true
}

注意事项: password字段设置为null时,不要添加引号,否则会被识别为字符串"null"而非空值。

🔧 Windows系统Docker启动问题完整解决方案 ​

当在Windows系统中遇到Docker Engine Stopped错误时,通常是由于系统配置或虚拟化设置问题导致的。以下是完整的排查和解决步骤:

步骤一:检查Windows版本兼容性 🔍 ​

bash
# 使用 Win + R 打开运行对话框,输入 winver 查看系统版本
winver

系统要求: Windows版本Build必须 >=19044,这是运行WSL2的最低要求。如果版本过低,需要先升级Windows系统。

步骤二:启用必要的Windows功能 ✅ ​

在控制面板 → 程序和功能 → 启动或关闭Windows功能中,确保以下功能已启用:

  • ✅ Hyper-V(虚拟化平台)
  • ✅ 虚拟机平台
  • ✅ Windows Subsystem for Linux

如果系统没有Hyper-V选项,可以通过脚本强制启用:

  1. 创建文本文件,复制以下内容:
cmd
pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt
for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hyper-v.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL
  1. 保存为Hyper.cmd文件
  2. 右键选择"以管理员身份运行"

步骤三:配置虚拟化启动类型 ⚙️ ​

在Windows PowerShell(管理员权限)中执行:

powershell
# 检查当前设置
bcdedit

# 如果 hypervisorlaunchtype 不是 auto,则执行
bcdedit /set hypervisorlaunchtype auto

配置完成后重启计算机。

步骤四:启用CPU虚拟化 💻 ​

检查虚拟化状态:

  1. 打开任务管理器(Ctrl + Shift + Esc)
  2. 切换到"性能"选项卡
  3. 选择"CPU",查看右侧是否显示"虚拟化:已启用"

如果未启用,需要进入BIOS设置:

主板品牌进入BIOS按键虚拟化设置路径
Intel主板F2/Del高级设置 → CPU → Intel VT-x
AMD主板F2/Del高级设置 → CPU配置 → SVM模式
联想/戴尔F1/F12安全 → 虚拟化

步骤五:检查和配置WSL 🐧 ​

bash
# 检查WSL安装状态
wsl -l -v

# 如果未安装WSL,执行安装命令
wsl --install

# 强制关闭WSL服务并重启
wsl --shutdown

安装完成后需要重启系统。

步骤六:重置Docker和WSL(最后手段) 🔄 ​

如果以上步骤都无法解决问题,可以尝试完全重置:

  1. 卸载Docker Desktop
  2. 清理WSL环境:
powershell
# 在PowerShell(管理员)中执行
wsl --unregister DockerDesktop
wsl --unregister Ubuntu    # 如果安装了Ubuntu发行版
wsl --unregister docker-desktop
wsl --unregister docker-desktop-data
  1. 重新安装Docker Desktop

🗂️ Docker镜像配置 ​

json
{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "registry-mirrors": [
      "https://docker.1ms.run"
  ]
}

🐙 使用 Docker Compose 管理数据库 ​

Docker Compose是Docker的编排工具,可以通过一个YAML文件定义和管理多个容器服务。在本项目中,我们使用它来快速搭建MySQL数据库环境。

📝 创建配置文件 ​

在项目根目录中创建docker-compose.yml文件:

⚠️ 重要提醒:文件必须放在项目根目录中,否则Docker无法正确找到配置。

yml
services:
  mysql:
    image: mysql:8.3.0
    command:
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
    environment:
      - MYSQL_ROOT_PASSWORD=clwy1234
      - MYSQL_LOWER_CASE_TABLE_NAMES=0
    ports:
      - "3306:3306"
    volumes:
      - ./data/mysql:/var/lib/mysql

配置说明:

  • mysql:8.3.0:使用MySQL 8.3.0版本
  • --default-authentication-plugin:设置默认认证插件,确保兼容性
  • --character-set-server=utf8mb4:支持完整的Unicode字符集,包括emoji
  • MYSQL_ROOT_PASSWORD:设置root用户密码
  • volumes:数据持久化,将容器内数据映射到本地

🚀 启动服务 ​

bash
# 在项目根目录下执行
docker-compose up -d

参数说明:

  • -d:后台运行模式(detached)

启动成功后,Docker Desktop面板中会显示相应的容器服务。

⚠️ 端口冲突解决方案 ​

如果本地已安装MySQL服务,可能会出现3306端口占用冲突:

bash
# 查看端口占用情况
netstat -ano | findstr :3306

# 查看占用端口的具体应用程序
tasklist | findstr PID号

# 停止本地MySQL服务(以MySQL80为例)
net stop MySQL80

# 强制结束进程
taskkill /PID 6336 /F

💾 数据库基础操作 ​

🏗️ 创建数据库 ​

创建名为clwy_api_development的数据库,配置如下:

配置项值说明
Database Encodingutf8mb4支持完整Unicode字符集,包括emoji表情
Database Collationutf8mb4_general_ci不区分大小写,不区分重音符号

📋 数据表命名规范 ​

在创建数据表时,必须遵循以下命名规范:

  • ✅ 首字母大写:如Articles、Users
    • ❌ 错误示例:articles(Linux服务器上会报错)
  • ✅ 使用复数形式:表名必须以s结尾
    • ❌ 错误示例:Article(Node.js查询时无法找到表)

📊 SQL基础操作语法 ​

1️⃣ 数据插入(INSERT) ​

sql
-- 基础语法
INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);

-- 单行插入示例
INSERT INTO `Articles` (`title`, `content`) 
VALUES ('行路难·其一', '长风破浪会有时,直挂云帆济沧海。');

-- 批量插入示例
INSERT INTO `Articles` (`title`, `content`) VALUES 
('将进酒', '天生我材必有用,千金散尽还复来。'),
('宣州谢朓楼饯别校书叔云', '抽刀断水水更流,举杯消愁愁更愁。'),
('梦游天姥吟留别', '安能摧眉折腰事权贵,使我不得开心颜!'),
('春夜宴从弟桃花园序', '天地者,万物之逆旅也;光阴者,百代之过客也。'),
('庐山谣寄卢侍御虚舟', '我本楚狂人,凤歌笑孔丘。手持绿玉杖,朝别黄鹤楼。'),
('望庐山瀑布', '飞流直下三千尺,疑是银河落九天。'),
('清平调', '云想衣裳花想容,春风拂槛露华浓。'),
('春夜洛城闻笛', '谁家玉笛暗飞声,散入春风满洛城。');

2️⃣ 数据更新(UPDATE) ​

sql
-- 基础语法
UPDATE 表名 SET 列1=值1, 列2=值2, ... WHERE 条件;

-- 更新示例:修改ID为2的记录
UPDATE `Articles` 
SET `title`='黄鹤楼送孟浩然之广陵', 
    `content`='故人西辞黄鹤楼,烟花三月下扬州。' 
WHERE `id`=2;

安全提示:WHERE条件必不可少,否则会更新表中所有数据!

3️⃣ 数据删除(DELETE) ​

sql
-- 基础语法
DELETE FROM 表名 WHERE 条件;

-- 删除示例:删除ID为5的记录
DELETE FROM `Articles` WHERE `id`=5;

-- 删除多条记录示例
DELETE FROM `Articles` WHERE `id` IN (1, 3, 5);

危险警告:删除操作不可逆,务必确保WHERE条件正确!

4️⃣ 数据查询(SELECT) ​

sql
-- 查询所有数据
SELECT * FROM `Articles`;

-- 查询指定字段
SELECT `id`, `title` FROM `Articles`;

-- 条件查询
SELECT * FROM `Articles` WHERE `id` > 2;

-- 排序查询
SELECT * FROM `Articles` WHERE `id` > 2 ORDER BY `id` DESC;  -- 降序
SELECT * FROM `Articles` WHERE `id` > 2 ORDER BY `id` ASC;   -- 升序

-- 限制数量查询
SELECT * FROM `Articles` LIMIT 5;                           -- 前5条
SELECT * FROM `Articles` LIMIT 5 OFFSET 10;                 -- 跳过10条,取5条

🔧 Sequelize ORM 框架实用指南 ​

🤔 什么是 Sequelize? ​

Sequelize 是 Node.js 中最流行的 ORM(对象关系映射)工具,它的作用就是让你用 JavaScript 代码操作数据库,而不用写复杂的 SQL 语句。

mermaid
graph LR
    A[前端表单提交] --> B[后端 API 接收]
    B --> C[Sequelize 操作数据库]
    C --> D[MySQL 数据库]
    D --> E[返回数据给前端]

简单理解:

  • 用户注册 → Sequelize 把用户信息存入数据库
  • 文章列表 → Sequelize 从数据库查询文章返回给前端
  • 更新资料 → Sequelize 修改数据库中的用户信息

🚀 三种核心使用场景 ​

场景一:建表 + 造数据 📊 ​

步骤1:创建模型和迁移

bash
# 创建文章模型(会同时生成迁移文件)
sequelize model:generate --name Article --attributes title:string,content:text

步骤2:执行迁移创建表

bash
sequelize db:migrate

步骤3:创建测试数据

bash
# 生成种子文件
sequelize seed:generate --name demo-articles

# 执行种子文件填充数据
sequelize db:seed:all

场景二:新增字段迁移 ✨ ​

假设要给用户表添加头像字段:

步骤1:创建迁移文件

bash
sequelize migration:create --name add-avatar-to-user

步骤2:编写迁移代码

javascript
// migrations/xxx-add-avatar-to-user.js
module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.addColumn('Users', 'avatar', {
      type: Sequelize.STRING,
      allowNull: true
    });
  },
  
  async down(queryInterface, Sequelize) {
    await queryInterface.removeColumn('Users', 'avatar');
  }
};

步骤3:执行迁移

bash
sequelize db:migrate

步骤4:更新模型文件

javascript
// models/user.js 中添加新字段
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    name: DataTypes.STRING,
    email: DataTypes.STRING,
    avatar: DataTypes.STRING,  // 🔥 新增这一行
  });
  return User;
};

场景三:回滚迁移 ⏪ ​

bash
# 回滚最后一次迁移
sequelize db:migrate:undo

# 回滚到指定迁移
sequelize db:migrate:undo:to --to 20230101000000-create-user.js

# 回滚所有迁移(危险操作)
sequelize db:migrate:undo:all

🛠️ 常用命令速查表 ​

操作命令说明
创建模型sequelize model:generate --name User --attributes name:string,email:string创建模型和迁移文件
执行迁移sequelize db:migrate应用所有未执行的迁移
回滚迁移sequelize db:migrate:undo回滚最后一次迁移
创建种子sequelize seed:generate --name demo-users生成种子文件
执行种子sequelize db:seed:all填充所有测试数据
清空种子sequelize db:seed:undo:all清空种子数据

💡 前端开发者必知要点 ​

✅ 必须掌握的 ​

  1. 基本流程:能够建表、造数据、新增字段
  2. 迁移概念:知道如何安全地修改数据库结构
  3. 环境区分:理解开发/测试/生产环境的数据库配置

⭐ 加分技能 ​

  1. 调试能力:能查看迁移状态和解决连接问题
  2. 团队协作:知道如何与后端开发者协作处理数据库变更

❌ 不需要深入的 ​

  1. 复杂的 SQL 优化
  2. 高级的关联查询
  3. 数据库性能调优

🔍 实际工作流程示例 ​

bash
# 日常开发流程
git pull origin main           # 拉取最新代码
docker-compose up -d          # 启动本地数据库
sequelize db:migrate          # 同步数据库结构
npm start                     # 启动开发服务器

# 新功能开发
sequelize model:generate --name Comment --attributes content:text,userId:integer
sequelize db:migrate          # 创建新表
sequelize db:seed:all         # 填充测试数据

通过这些实用场景,你就可以快速上手 Sequelize,进行全栈开发了! 🚀

📦 安装和配置Sequelize ​

步骤一:安装依赖包 ​

bash
# 全局安装Sequelize CLI工具
npm i -g sequelize-cli

# 在项目中安装Sequelize核心包和MySQL驱动
npm i sequelize mysql2

步骤二:初始化项目 ​

bash
# 在项目根目录执行初始化
sequelize init

初始化完成后,项目中会生成以下目录结构:

project/
├── config/          # 配置文件目录
│   └── config.json  # 数据库连接配置
├── migrations/      # 数据库迁移文件
├── models/          # 数据模型文件
│   └── index.js     # 模型入口文件
└── seeders/         # 数据种子文件

目录说明:

目录作用使用场景
config存放数据库连接配置不同环境的数据库配置
migrations数据库结构变更记录创建表、修改字段、删除表等操作
models数据模型定义定义表结构和数据关系
seeders测试数据种子快速填充测试数据

步骤三:配置数据库连接 ​

修改config/config.json文件,配置开发环境数据库连接:

json
{
  "development": {
    "username": "root",
    "password": "clwy1234",
    "database": "clwy_api_development",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "timezone": "+08:00",
    "define": {
      "timestamps": true,
      "underscored": false,
      "freezeTableName": false
    }
  },
  "test": {
    "username": "root",
    "password": "clwy1234",
    "database": "clwy_api_test",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "timezone": "+08:00"
  },
  "production": {
    "username": "root",
    "password": "your_production_password",
    "database": "clwy_api_production",
    "host": "your_production_host",
    "dialect": "mysql",
    "timezone": "+08:00"
  }
}

🏗️ 使用Sequelize管理数据表 ​

创建数据模型 ​

bash
# 创建Article模型和对应的迁移文件
sequelize model:generate --name Article --attributes title:string,content:text,authorId:integer

# 执行数据库迁移,创建实际的数据表
sequelize db:migrate

命令解析:

  • --name Article:模型名称(单数形式)
  • --attributes:字段定义,格式为 字段名:类型

创建测试数据 ​

bash
# 生成种子文件
sequelize seed:generate --name demo-articles

# 填充指定种子数据
sequelize db:seed --seed 20250516000000-demo-articles.js

# 填充所有种子数据
sequelize db:seed:all

回滚操作 ​

bash
# 回滚最后一次迁移
sequelize db:migrate:undo

# 回滚所有迁移
sequelize db:migrate:undo:all

# 回滚种子数据
sequelize db:seed:undo:all

🎯 Sequelize模型核心概念 ​

命名约定 ​

Sequelize遵循特定的命名约定:

类型约定示例
模型名单数,首字母大写Article, User, Category
表名复数,全小写articles, users, categories
字段名驼峰命名firstName, createdAt, userId

数据类型映射 ​

Sequelize类型MySQL类型说明
STRINGVARCHAR(255)短字符串
TEXTTEXT长文本
INTEGERINT整数
BOOLEANTINYINT(1)布尔值
DATEDATETIME日期时间
DECIMALDECIMAL精确小数

这样,我们就完成了从Express项目创建到数据库ORM配置的完整流程。接下来你可以继续添加业务逻辑和API接口开发的内容。

🤔 配置文件工作机制详解 ​

很多开发者在初次接触这些配置文件时会有疑问:这些文件到底什么时候被读取?它们是如何工作的?让我们详细剖析一下。

📄 docker-compose.yml 文件工作机制 ​

🕐 什么时候被读取? ​

docker-compose.yml 文件只在以下情况下被 Docker 引擎读取:

bash
# 这些命令会读取 docker-compose.yml 文件
docker-compose up -d          # 启动服务时读取
docker-compose down           # 停止服务时读取
docker-compose build          # 构建镜像时读取
docker-compose ps             # 查看服务状态时读取
docker-compose logs mysql     # 查看服务日志时读取

🔄 工作流程解析 ​

mermaid
graph TD
    A[执行 docker-compose up -d] --> B[Docker 读取 docker-compose.yml]
    B --> C[解析服务配置]
    C --> D[拉取 MySQL 镜像]
    D --> E[创建并启动容器]
    E --> F[MySQL 服务运行在 3306 端口]
    
    G[你的 Node.js 应用启动] --> H[读取 config/config.json]
    H --> I[连接到 localhost:3306]
    I --> J[成功连接到 Docker 中的 MySQL]

重要理解:

  • docker-compose.yml 是 Docker 的配置文件,不是 Node.js 的
  • 它只在你执行 docker-compose 命令时才会被读取
  • 一旦容器启动,这个文件就不会再被读取,除非你重新启动服务

🎯 实际应用场景 ​

bash
# 第一次启动项目
cd your-project
docker-compose up -d    # 此时读取 docker-compose.yml,创建 MySQL 容器

# 之后每次开发
npm start              # Node.js 应用启动,读取 config/config.json 连接数据库

# 关闭开发环境
docker-compose down    # 再次读取 docker-compose.yml,停止容器

⚙️ config/config.json 文件工作机制 ​

🕐 什么时候被读取? ​

config/config.json 文件在以下时机被 Sequelize 读取:

javascript
// 当你的 Node.js 应用执行这些操作时
const { Sequelize } = require('sequelize');

// 1. 应用启动时,Sequelize 初始化
const sequelize = new Sequelize(config.development);  // 读取配置

// 2. 执行 Sequelize CLI 命令时
sequelize db:migrate        // 读取配置连接数据库
sequelize db:seed:all       // 读取配置连接数据库
sequelize model:generate    // 读取配置(虽然不连数据库)

🔄 详细工作流程 ​

mermaid
graph TD
    A[Node.js 应用启动] --> B[加载 models/index.js]
    B --> C[读取 config/config.json]
    C --> D[根据 NODE_ENV 选择环境]
    D --> E[development/test/production]
    E --> F[使用配置连接数据库]
    F --> G[建立数据库连接池]
    G --> H[应用可以操作数据库]

📋 环境变量机制 ​

javascript
// models/index.js 中的逻辑(Sequelize 自动生成)
const env = process.env.NODE_ENV || 'development';  // 确定环境
const config = require(__dirname + '/../config/config.json')[env];  // 读取对应环境配置

// 不同环境下的配置选择
// 开发环境:npm start → NODE_ENV=development → 使用 config.development
// 测试环境:npm test → NODE_ENV=test → 使用 config.test  
// 生产环境:NODE_ENV=production → 使用 config.production

🔗 两个配置文件的协作关系 ​

🎭 角色分工 ​

配置文件负责的工具作用阶段主要功能
docker-compose.ymlDocker Engine基础设施搭建创建数据库服务器
config/config.jsonSequelize ORM应用层连接连接到数据库服务器

🏗️ 完整的工作时序 ​

bash
# 第1步:启动基础设施(Docker读取docker-compose.yml)
docker-compose up -d
# Docker创建MySQL容器,监听3306端口

# 第2步:创建数据库和表结构(Sequelize读取config.json)
sequelize db:migrate
# Sequelize连接到localhost:3306,执行建表SQL

# 第3步:启动应用(Node.js读取config.json)
npm start
# 应用连接到localhost:3306,开始处理业务逻辑

💡 常见误区和最佳实践 ​

❌ 常见误区 ​

  1. 端口配置不一致
yaml
# docker-compose.yml 中
ports:
  - "3307:3306"    # 映射到本地3307端口

# config.json 中还写着
"port": 3306       # ❌ 应该改为3307
  1. 环境变量混淆
bash
# 错误理解:认为docker-compose.yml会读取NODE_ENV
NODE_ENV=production docker-compose up -d  # ❌ Docker不关心NODE_ENV

✅ 最佳实践 ​

  1. 保持端口一致性
json
// config/config.json
{
  "development": {
    "host": "127.0.0.1",
    "port": 3306,      // 与docker-compose.yml中的端口映射一致
    "database": "clwy_api_development"
  }
}
  1. 使用环境变量增强安全性
json
{
  "production": {
    "username": "${DB_USERNAME}",
    "password": "${DB_PASSWORD}",
    "database": "${DB_NAME}",
    "host": "${DB_HOST}"
  }
}

🔍 调试技巧 ​

验证Docker服务状态 ​

bash
# 检查容器是否正常运行
docker-compose ps

# 检查容器日志
docker-compose logs mysql

# 测试数据库连接
docker-compose exec mysql mysql -u root -p

验证Sequelize配置 ​

bash
# 测试数据库连接
sequelize db:migrate:status

# 查看当前环境
echo $NODE_ENV

# 手动测试连接(在Node.js中)
const { Sequelize } = require('sequelize');
const config = require('./config/config.json').development;
const sequelize = new Sequelize(config);
sequelize.authenticate().then(() => console.log('连接成功'));

现在你应该清楚地理解了这两个配置文件的工作机制:Docker Compose 负责搭建数据库服务器,Sequelize 负责连接和操作这个数据库服务器。它们在不同的阶段发挥作用,但最终目标是让你的应用能够顺利访问数据库。