上篇回顾:2.3-01 讲了用 Element Plus 快速搭管理后台 + 二次封装原则。本篇进入前端工程化——Node.js 是前端世界的「后端运行时」,所有构建工具(Vite/Webpack/esbuild)都跑在 Node 上。但 Node 对前端的意义远不止「构建工具的宿主」。
一、开篇:一个后端工程师的疑问
「前端不就是写 HTML/CSS/JS 吗?为什么要装 Node?为什么要 npm install?为什么要 package.json?」
这是后端工程师第一次接触现代前端项目时的典型困惑。答案:现代前端不只是写页面,而是一个完整的软件工程——有依赖管理、有构建流程、有测试、有部署。这套工程化的基础设施全部建立在 Node.js 之上。
二、Node.js:JS 的后端运行时
2.1 Node 是什么
Node.js 是一个让 JS 跑在服务端的运行时(基于 V8 引擎)。浏览器里的 JS 能操作 DOM 但不能读写文件;Node 里的 JS 能读写文件、开 HTTP 服务、但不能操作 DOM。
2.2 Node 的事件循环与浏览器 JS 同源
Node 和浏览器 JS 共享同一个事件循环模型——单线程 + 异步 IO。但 Node 的事件循环比浏览器多了几个阶段(poll/check/close 等)。
2.3 Node 对前端的意义
| 意义 | 说明 |
|---|---|
| 构建工具宿主 | Webpack/Vite/esbuild 都是 Node 程序 |
| 包管理基础 | npm/pnpm 依赖 Node 运行 |
| SSR 运行时 | Vue SSR/Next.js 需要 Node 服务端 |
| 工具链 | 脚手架、代码生成、mock 服务 |
| 全栈能力 | 一个语言通吃前后端 |
三、npm vs yarn vs pnpm
3.1 三者演进
| 工具 | 特点 | 推荐度 |
|---|---|---|
| npm | Node 自带、最通用 | 基础够用 |
| yarn | 早期更快、lockfile 先驱 | 已被 pnpm 超越 |
| pnpm | 硬链接复用、节省磁盘 | 推荐 |
3.2 pnpm 为什么推荐
# npm/yarn:每个项目 node_modules 独立拷贝project-a/node_modules/lodash/# 5MBproject-b/node_modules/lodash/# 5MB(重复)# pnpm:全局存储 + 硬链接~/.pnpm-store/lodash/# 5MB(唯一)project-a/node_modules/lodash → 硬链接 project-b/node_modules/lodash → 硬链接10 个项目都用 lodash,npm 占 50MB,pnpm 只占 5MB。
3.3 pnpm 的另一个优势:严格依赖
npm 的node_modules是扁平的,你可以 import 没在 package.json 声明的依赖(因为被提升到了顶层)。pnpm 用符号链接保持嵌套结构,你只能 import 声明的依赖——避免「删了某个依赖导致另一个依赖也挂」的幽灵依赖问题。
四、package.json 逐字段解读
{"name":"my-app","version":"1.0.0","scripts":{"dev":"vite","build":"vite build","preview":"vite preview","lint":"eslint src/","test":"vitest"},"dependencies":{"vue":"^3.4.0","element-plus":"^2.5.0"},"devDependencies":{"vite":"^5.0.0","eslint":"^8.50.0"},"engines":{"node":">=18"}}| 字段 | 说明 |
|---|---|
| name/version | 包名和版本 |
| scripts | npm 命令脚本 |
| dependencies | 运行时依赖 |
| devDependencies | 开发时依赖(不进生产) |
| engines | 指定 Node 版本 |
4.1 dependencies vs devDependencies
# 运行时需要的放 dependenciesnpminstallvue element-plus# 只在开发时需要的放 devDependenciesnpminstall-Dvite eslint vitest区别:npm install --production时只装 dependencies。SSR 项目要注意——Vue 既是开发依赖也是运行依赖,要放 dependencies。
4.2 版本号语义化
^3.4.0 → 允许 3.x.x(不升大版本) ~3.4.0 → 允许 3.4.x(不升小版本) 3.4.0 → 精确版本推荐:用^(允许小版本升级),配合 lockfile 锁定具体版本。
五、scripts 的工程化用法
5.1 基本用法
{"scripts":{"dev":"vite","build":"vite build","lint":"eslint src/ --ext .vue,.js,.ts","lint:fix":"eslint src/ --fix","test":"vitest","test:coverage":"vitest --coverage","format":"prettier --write src/"}}npmrun dev# 启动开发服务器npmrun build# 构建生产包npmrun lint# 代码检查5.2 串行与并行
{"scripts":{"lint:test":"npm run lint && npm run test",// 串行"dev:all":"concurrently \"npm run dev\" \"npm run mock\""// 并行}}5.3 pre/post 钩子
{"scripts":{"prebuild":"npm run lint",// build 前自动执行"build":"vite build","postbuild":"echo done"// build 后自动执行}}六、nvm:Node 版本管理
# 安装 nvmcurl-o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh|bash# 安装 Node 18nvminstall18nvm use18# 项目指定 Node 版本echo"18">.nvmrc nvm use# 自动读 .nvmrc类似 Java 的 SDKMAN,每个项目可以用不同 Node 版本。
七、前端工程化的完整图景
开发: 脚手架(Vite create)→ 开发服务器(HMR)→ 代码检查(ESLint)→ 格式化(Prettier) 构建: 编译(TS→JS)→ 打包(模块合并)→ 压缩(Tree-shaking)→ 输出 dist/ 测试: 单测(Vitest)→ E2E(Playwright)→ 覆盖率(c8) 部署: CI/CD(GitHub Actions / Jenkins)→ 静态托管(Nginx / CDN)八、小结表
| 概念 | 价值 | 推荐 |
|---|---|---|
| Node | 前端工程化的运行时 | 必须 |
| pnpm | 节省磁盘 + 严格依赖 | 推荐 |
| package.json | 项目元信息 | 熟读每个字段 |
| scripts | 工程化命令入口 | 善用 pre/post 钩子 |
| nvm | Node 版本管理 | 用 .nvmrc 锁版本 |