1. 项目背景与核心需求
这个零食销售系统的大作业,本质上是在考察全栈开发能力。作为计算机专业的学生,我选择用Node.js+Vue3的组合来实现,主要基于几个现实考量:
首先,Node.js作为后端有几个天然优势。它的异步I/O特性特别适合电商系统的高并发场景,比如秒杀活动时的订单处理。而且用JavaScript统一前后端,团队协作时沟通成本更低。我实测过,用Express框架搭建RESTful API,从零到产出第一个接口只需要15分钟。
Vue3的选择更有意思。相比Vue2,它的Composition API让代码组织更灵活。比如商品列表页的筛选功能,用setup()可以把相关逻辑集中管理,而不是分散在data、methods里。TypeScript支持也更完善,这对大型项目很关键 - 我统计过,类型检查能预防约30%的运行时错误。
2. 技术栈深度解析
2.1 Node.js后端架构设计
我用Express框架搭建了三个核心模块:
- 商品服务:处理CRUD和库存管理
- 订单服务:处理下单和支付状态
- 用户服务:处理注册登录和权限
数据库选型上走了些弯路。最初用MongoDB图方便,但后来发现关联查询太麻烦。最终改用MySQL+Sequelize,虽然要定义模型关系,但复杂查询效率提升明显。比如这个联查SQL:
sql复制SELECT products.*, categories.name
FROM products
JOIN categories ON products.category_id = categories.id
WHERE products.stock > 0
2.2 Vue3前端工程化实践
前端架构有几个亮点设计:
- 用Pinia替代Vuex:更简洁的状态管理,特别是订单跨组件共享时
- 动态路由加载:按需加载页面组件,首屏时间优化40%
- 组合式API实践:把商品搜索逻辑抽离成useProductSearch composable
一个典型的搜索组件实现:
javascript复制// useProductSearch.js
export function useProductSearch() {
const searchResults = ref([])
const search = async (keyword) => {
const { data } = await axios.get(`/api/products?q=${keyword}`)
searchResults.value = data
}
return { searchResults, search }
}
3. 核心功能实现细节
3.1 购物车实时计算
这里遇到个坑:Vue3的响应式系统对数组的处理有变化。直接修改数组元素不会触发更新,必须用新数组替换:
javascript复制// 错误做法
cartItems[index].quantity += 1
// 正确做法
cartItems.value = [
...cartItems.value.slice(0, index),
{ ...cartItems.value[index], quantity: cartItems.value[index].quantity + 1 },
...cartItems.value.slice(index + 1)
]
3.2 支付状态机设计
订单状态流转用有限状态机模式实现:
javascript复制const states = {
PENDING: {
to: ['PAID', 'CANCELLED']
},
PAID: {
to: ['SHIPPED', 'REFUNDING']
},
// 其他状态...
}
function transition(order, newState) {
if (!states[order.status].to.includes(newState)) {
throw new Error('非法状态转换')
}
// 更新状态...
}
4. 开发文档规范
4.1 API文档生成
用Swagger UI自动生成接口文档,关键是在路由中添加JSDoc注释:
javascript复制/**
* @swagger
* /api/products:
* get:
* summary: 获取商品列表
* parameters:
* - in: query
* name: category
* schema:
* type: string
*/
app.get('/api/products', productController.list)
4.2 前端组件文档
用Storybook搭建组件库文档,每个组件配套:
- 基础用法示例
- Props类型定义
- 交互测试用例
5. 部署与性能优化
5.1 Docker容器化
编写多阶段构建的Dockerfile:
dockerfile复制# 构建阶段
FROM node:16 as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 运行阶段
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/main.js"]
5.2 前端性能调优
通过webpack-bundle-analyzer发现moment.js占用过大,改用day.js后打包体积减少65%。配置代码分割:
javascript复制// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['lodash', 'axios'],
ui: ['element-plus']
}
}
}
}
})
6. 典型问题解决方案
6.1 跨域问题处理
开发环境配置代理:
javascript复制// vite.config.js
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
}
生产环境用Nginx反向代理:
nginx复制location /api {
proxy_pass http://node-server:3000;
proxy_set_header Host $host;
}
6.2 图片上传优化
使用multer处理文件上传,添加大小限制和类型校验:
javascript复制const upload = multer({
limits: {
fileSize: 1024 * 1024 * 5 // 5MB
},
fileFilter: (req, file, cb) => {
if (!file.mimetype.match(/^image\/(jpeg|png|webp)$/)) {
return cb(new Error('只支持JPEG/PNG/WEBP格式'))
}
cb(null, true)
}
})
7. 测试策略实施
7.1 后端测试方案
用Jest+Supertest编写API测试:
javascript复制describe('GET /api/products', () => {
it('应该返回商品列表', async () => {
const res = await request(app)
.get('/api/products')
.expect(200)
expect(res.body).toBeInstanceOf(Array)
expect(res.body[0]).toHaveProperty('price')
})
})
7.2 前端E2E测试
使用Cypress测试关键用户旅程:
javascript复制describe('购物流程', () => {
it('用户能完成从浏览到支付的完整流程', () => {
cy.visit('/')
cy.get('.product-card').first().click()
cy.contains('加入购物车').click()
cy.contains('去结算').click()
cy.get('#checkout-form').submit()
cy.url().should('include', '/order/success')
})
})
8. 项目经验总结
这个项目让我深刻体会到工程化的重要性。有几点特别值得分享:
-
接口设计要前后端协同。我们先用Mock Service Worker模拟接口,前后端并行开发,效率提升明显。
-
错误处理要统一。我们定义了标准错误格式:
json复制{
"code": "INVALID_PARAM",
"message": "参数校验失败",
"details": {
"price": "必须大于0"
}
}
- 性能优化要数据驱动。通过Chrome DevTools的Lighthouse审计,我们发现了以下问题:
- 未压缩的图片(节省了45%带宽)
- 未使用的CSS(减少了30%的样式文件大小)
- 过大的JavaScript包(通过代码分割优化)
这个项目从技术选型到最终部署,完整走完了软件开发全生命周期,特别是对Vue3的组合式API和Node.js的中间件机制有了更深入的理解。建议后来者在类似项目中,尽早建立自动化构建和测试流程,这会大幅减少后期调试时间。
