Vue3+Element-Plus+mockjs 环境配置与启动排错

发布时间:2026/10/30 5:41:26
Vue3+Element-Plus+mockjs 环境配置与启动排错

简介:这份 Vue3-demo 面向希望快速上手 Vue3 新语法与组件库集成的开发者,尤其适合想了解 Element-Plus 引入方式、Mockjs 假数据配置和 axios 请求封装的初中级前端学习者。工程已完成环境搭建与依赖安装,解压后即可进入开发,省去从零初始化项目、反复调试引入顺序的麻烦。压缩包共 27 个文件、约 130KB,以 9 个 .vue 单文件组件为核心,配合 3 个 .js 与 1 个 .cjs 文件承载入口和构建配置,多个 .json 管理依赖与编辑器设置,另有 .css、.md 说明文档及 png、svg、ico 等静态资源,结构清晰、体量轻巧,便于直接阅读和二次改造。目前已有 2140 人学习,对入门者具有较好的参考价值。工程内已用 Element-Plus 的 table 组件搭好可运行的表格页面,可直接作为新页面的脚手架;同时保留 Mockjs 与 axios 的接入示例,方便对照理解假数据如何生成、请求如何发出,并据此扩展列表、表单等常见业务模块。

1. 解开压缩包就有 node_modules,第一次 npm run dev 照样可能失败

拿到的压缩包解开,node_modules就躺在里面,package.json里vue、element-plus、mockjs一个不少,看着就是那种「环境已配好、拿来就能跑」的 Vue3 项目。真上手敲npm run dev,出问题的地方往往不在业务代码:Node 版本差一个大版本,Vite 直接甩一句crypto.hash is not a function;pnpm 和 npm 的 lock 文件混着用,装出两份 Vue,页面白屏而控制台却不报错;mockjs 规则写得挺像回事,接口却照样打到真后端。Vue3 + Element-Plus + mockjs 这套组合横跨运行时、构建工具、组件库和请求拦截四层,任何一层没对齐,表现都是「跑不起来」。下面按我平时装这套骨架的顺序走:先定 Node 和包管理器,再装依赖启动,然后把 Element-Plus 按需引入和 mock 拦截配到位,最后给验证和排错的路子。适合拿到这套 demo 想直接跑通的人,也适合想把它改成自己项目底座的人。

2. 环境底座:Node 版本、包管理器与依赖清单三件事

这套 demo 号称「环境已配好」,指的是代码层面配好了,运行机器上的东西还是得自己对齐。我见过太多人把压缩包拷到另一台电脑,解压、npm install、npm run dev三步走完,然后卡在第一个报错上半天。问题几乎都集中在三处:Node 大版本、包管理器与 lock 文件、依赖到底装在哪一层。这一章先把这三件事定下来,后面装机才顺。

2.1 Node 版本和 Vite 的对应关系

Vue 3 本身对 Node 没那么挑,真正挑的是 Vite。Vue3 + Element-Plus 这套骨架基本都用 Vite 做构建,而 Vite 每个大版本对 Node 有硬性下限,低于下限不是警告,是直接起不来。常见对应关系我整理成下面这张表,拿到项目先看package.json里vite的版本范围,再对照机器上的 Node:

Vite 版本Node 最低要求常见报错
Vite 4.x14.18+ / 16+Cannot find module 'node:...'
Vite 5.x18.0+ / 20+crypto.hash is not a function
Vite 6.x18.0+ / 20+ / 22+SyntaxError: Unexpected token '?'类似语法错

先查现场:

# 看当前 Node 与 npm 版本,两个都要看 node -v npm -v # 如果项目根目录有 .nvmrc,直接按文件切 cat .nvmrc nvm use

node -v出来是v16.x,而package.json里写的是"vite": "^5.2.0",那就别挣扎了,升 Node。Vite 5 内部用了 Node 18 才稳定的crypto.hash,在 16 上运行会直接抛TypeError: crypto.hash is not a function,这个报错跟业务代码一点关系没有,纯运行时版本问题。我一般统一用 Node 20.x 的 LTS 版本,Vite 4/5/6 都能覆盖,切版本用 nvm 最省事,别去手动改系统 PATH。

还有一点容易忽略:package.json里的engines字段只是声明,npm 默认不强制。想让它真拦住,在项目根目录加一个.npmrc:

# 装依赖时强制校验 engines,版本不符直接失败而不是装完才发现 engine-strict=true

加了这行,Node 版本不对时npm install阶段就会报Unsupported engine,比等到npm run dev才发现要早得多。当然,如果你接手的是别人机器上已经装好的node_modules,切完 Node 版本记得把node_modules删掉重装,因为部分依赖带原生模块(比如 sass 的二进制),跨 Node 大版本复用会出些莫名其妙的加载错误。

2.2 npm 还是 pnpm:lock 文件别乱删

第二个高频出错点是包管理器混用。压缩包里如果带着pnpm-lock.yaml,说明原作者用 pnpm 装的。你顺手一个npm install,npm 不认识 pnpm 的 lock,会自己解析package.json重新算一遍依赖树,生成一份package-lock.json。两个 lock 文件并存,下一次谁先跑就用谁的规则,装出来的node_modules结构可能不一样。

最典型的后果是「两份 Vue」:Element-Plus 依赖的 Vue 和你业务代码里的 Vue 版本解析到两个不同路径,运行时组件注册不上,页面白屏,控制台只给你一句Cannot read properties of null (reading 'isCE'),新手看到这句基本无从下手。判断方法很直接:

# 看 vue 被安装了几份、分别在哪里 npm ls vue # 或 pnpm 项目 pnpm why vue

输出里如果出现两个不同版本的vue@3.x,就是重复安装。处理办法是把node_modules和多余的 lock 一起清掉,只保留一种:

# 三个 lock 文件只留一个,按你实际用的包管理器选 rm -rf node_modules rm -f package-lock.json yarn.lock pnpm-lock.yaml # 假设原项目用 pnpm,就装回 pnpm 再执行 pnpm install

另一种情况是 pnpm 的严格依赖模式。npm 会把依赖拍平,你代码里import一个没在package.json声明的包也能跑(幽灵依赖);pnpm 默认不拍平,同样的代码会报Module not found。遇到这种不要急着关掉严格模式,先看这个包是不是真的该被显式声明。真要临时兼容,在.npmrc里加shamefully-hoist=true,但这属于兜底,长期还是补齐依赖声明更干净。

2.3 依赖清单核对:Vue3、Element-Plus、mockjs 各在哪一层

装之前把package.json过一遍,重点看依赖分在dependencies还是devDependencies。分错了不影响开发跑,但会影响打包体积和 CI 安装策略。我按这套骨架的常见构成列一张表:

包名常见版本范围放哪一层作用
vue^3.3 / ^3.4dependencies运行时核心
vue-router^4.xdependencies路由
pinia^2.xdependencies状态管理
element-plus^2.7dependencies组件库
@element-plus/icons-vue^2.xdependencies图标
axios^1.xdependencies请求
mockjs^1.1.0devDependencies假数据生成
vite-plugin-mock^3.xdevDependenciesmock 服务插件
unplugin-auto-import^0.17devDependencies自动导入
unplugin-vue-components^0.26devDependencies组件按需注册
sass^1.xdevDependencies主题定制需要

mockjs和vite-plugin-mock放 devDependencies 是对的,它们只在开发期起作用,不该进生产包。但要注意,有些模板为了图省事把mockjs写进 dependencies,打包时如果代码里还有import Mock from 'mockjs'的静态引用,就会被打进产物,体积白涨几十 KB。核对完执行一次安装,再用下面的命令确认关键包都到位:

# 确认三个核心包的实际安装版本,避免 lock 里锁的是旧版 npm ls vue element-plus mockjs # 查看某个包为什么被装进来,排查重复依赖时很有用 npm explain vue

版本这块有个取舍:Element-Plus 2.x 要求 Vue 3.2 以上,如果你的vue写的是^3.0.0,npm 会装最新的 3.x,通常没事;但如果 lock 文件把 Vue 锁在 3.1.x,Element-Plus 的部分组件会报渲染错误。稳妥做法是显式写"vue": "^3.4.0"这类下限明确的版本,别留^3.0.0这种过宽的范围。

3. 安装与首次启动:从解压到页面出来

底座定完,进入实际安装。这一章的目标很明确:让npm run dev起来,浏览器能看到页面。听着简单,实际卡人的地方集中在目录结构认错、镜像源和网络、环境变量加载顺序三处。我习惯按「先看再删、再装、再看日志」的节奏走,比一上来就npm install稳。

3.1 解压后先看目录,别急着删 node_modules

解压完先别动文件,花两分钟看目录。这套 Vue3 + Element-Plus + mockjs 骨架的典型结构长这样:

vue3-demo/ ├── mock/ # mockjs 假数据规则,通常一个模块一个文件 ├── public/ ├── src/ │ ├── api/ # 请求封装 │ ├── components/ │ ├── views/ │ ├── App.vue │ └── main.ts ├── .env.development # 开发环境变量 ├── .env.production # 生产环境变量 ├── index.html ├── package.json ├── tsconfig.json └── vite.config.ts # 构建配置,mock 和 alias 都在这

先看package.json的scripts段,确认启动命令到底叫什么:

{ "scripts": { "dev": "vite", "build": "vue-tsc --noEmit && vite build", "preview": "vite preview" } }

有的模板把dev写成serve或者加了--mode dev,照着敲npm run dev会报Missing script: dev,不是环境问题,就是命令名对不上。接着看vite.config.ts里有没有server.port,如果写死了 3000,那启动日志里就不是默认的 5173,别拿着 5173 一直刷新。

压缩包里自带的node_modules要不要留?我的习惯是删。原因有两个:一是它可能是在别人的系统上装的,原生模块(sass、esbuild 的二进制)跟当前系统不一定匹配;二是它可能带着过期的依赖树,重装一遍反而最快。删之前先确认 lock 文件在,没有 lock 的话先跑一次安装生成,之后再删。

# 先确认有 lock 文件,再删 node_modules,顺序别反 ls package-lock.json pnpm-lock.yaml 2>/dev/null rm -rf node_modules

3.2 装依赖:镜像源、缓存与 lock 文件的处理

安装阶段最集中的问题是网络。npm 官方源在国内拉包经常超时,表现是装到一半卡住,或者报ETIMEDOUT、ECONNRESET。常规做法是换镜像源,项目级配置写在根目录.npmrc,比改全局配置更可控:

# 项目级镜像源,跟着仓库走,换机器不用重配 registry=https://registry.npmmirror.com # 原生模块的二进制也走镜像,否则 sass 这类包还会去外网拉 sass_binary_site=https://registry.npmmirror.com/-/binary/node-sass # 安装失败重试次数,网络抖动时能少挂几次 fetch-retries=3 fetch-retry-maxtimeout=60000

配置完直接装:

# 有 lock 用 ci 更稳,它严格按 lock 安装,不会偷偷升级版本 npm ci # 没有 lock 或要更新依赖时才用 install npm install

npm ci和npm install的区别值得说清楚:ci会先删掉node_modules再按 lock 文件精确安装,装出来的版本和原作者一致,适合「拿到别人的项目先跑起来」这个场景;install会根据package.json的范围解析版本,可能装出比 lock 里更新的包,适合你确实要升级依赖的时候。第一次跑通,我一般用ci。

装的过程中如果卡在某个包上,先看它是纯 JS 还是带二进制。纯 JS 包卡住基本是网络,重试或换源即可;带二进制的包(sass、esbuild、sharp)报错信息里通常带平台信息,比如Unsupported platform for esbuild,这种是平台不匹配或者镜像上没有对应产物,删掉node_modules和 lock 重装一次往往就好。还有一个隐性坑是缓存损坏,表现是某个包反复装失败但报错看不懂,可以强制清缓存:

# 清掉 npm 缓存后重装,缓存损坏时的后悔药 npm cache verify npm cache clean --force rm -rf node_modules npm ci

3.3 dev 脚本、端口与环境变量文件的加载顺序

依赖装完,npm run dev。Vite 启动很快,日志里会打出本地地址和网络地址。这一步要确认三件事:端口、.env文件有没有被加载、有没有启动报错但被刷过去。

端口在vite.config.ts里配:

// vite.config.ts 片段:端口、host 与自动打开 export default defineConfig({ server: { host: '0.0.0.0', // 局域网其他设备也能访问,方便真机调试 port: 5173, // 端口被占用时 Vite 会自动 +1,看日志确认实际端口 open: true, // 启动后自动开浏览器,省一次手点 }, })

host: '0.0.0.0'这个配置在只用本机浏览器时无所谓,但用手机连同一个 Wi-Fi 调试移动端页面时必须有,否则网络地址那一行根本不会出现。port被占用时 Vite 不会报错,而是自动换一个,日志里会写Port 5173 is in use, trying another one...,这时候你按记忆访问 5173 会看到别的项目,别怀疑自己装错了。

环境变量的加载顺序是另一个容易出错的地方。Vite 按mode加载.env、.env.local、.env.[mode]、.env.[mode].local,后面的覆盖前面的。只有VITE_开头的变量才会注入到客户端代码里,其他前缀的一律拿不到,这是很多人写API_URL然后import.meta.env.API_URL拿到undefined的原因。

# .env.development:开发环境专用,必须 VITE_ 前缀才会被前端读到 VITE_APP_TITLE=vue3-demo VITE_APP_BASE_API=/api # mock 开关,1 开启 0 关闭,后面 mock 章节会用 VITE_USE_MOCK=1

代码里这样读:

// 读取环境变量,注意 import.meta.env 是编译期替换,不是运行时对象 const baseApi = import.meta.env.VITE_APP_BASE_API const useMock = import.meta.env.VITE_USE_MOCK === '1'

要注意import.meta.env.VITE_USE_MOCK拿到的永远是字符串,写=== '1'判断,别直接当布尔用,'0'在 JS 里是真值,这个错我见过不止一次。启动日志里如果看到VITE v5.x ready in xxx ms并且没有红色报错,页面也能出内容,这一章就算过了。

4. 组件库与假数据:Element-Plus 按需引入搭 mockjs 拦截

页面能起来只是第一步。这套骨架的价值在于 Element-Plus 提供了现成组件,mockjs 提供了不依赖后端的假数据,两者配好之后才能真正开始写业务。这一章把 Element-Plus 的引入方式、自动导入插件、mock 规则配置和开关隔离一次讲清,都是可以直接抄进项目的写法。

4.1 Element-Plus 全量引入与按需引入的取舍

引入 Element-Plus 有两种方式,先看全量:

// main.ts:全量引入,简单但会把整个组件库打进包 import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' // 样式必须单独引,漏了组件会没样式 import App from './App.vue' const app = createApp(App) app.use(ElementPlus) app.mount('#app')

全量的优点是省心,所有组件、指令、样式都注册好了,写出<el-table>就能渲染;缺点是打包体积大,即使你只用了三个组件,整个库也会进去。开发期无所谓,上线前这股体积会变成实打实的首屏时间。

按需引入解决这个问题,原理是在构建时分析模板里用到的组件标签,只把对应的组件和样式引进来。手写按需引入是可行的,每个页面都写一堆import { ElButton } from 'element-plus',但维护成本高。常规做法是用unplugin-vue-components加unplugin-auto-import两个插件自动完成。我的取舍是:demo 练习、内部工具可以用全量,正式项目一律按需,两者不要在同一个项目里混着来,混用会出现组件注册两次、样式重复注入的问题。

4.2 unplugin-auto-import 与 unplugin-vue-components 的配置写法

先装插件:

# 两个插件都是开发期依赖,生产构建时会参与打包分析 npm i -D unplugin-auto-import unplugin-vue-components

然后改vite.config.ts:

// vite.config.ts:Element-Plus 按需自动导入 import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' export default defineConfig({ plugins: [ vue(), AutoImport({ // 自动导入 vue、vue-router、pinia 的 API,ref、computed 不用手写 import imports: ['vue', 'vue-router', 'pinia'], // Element-Plus 的方法类 API,比如 ElMessage、ElMessageBox 自动引入 resolvers: [ElementPlusResolver()], // 生成类型声明文件,TS 项目必须有,否则编辑器一片红 dts: 'src/auto-imports.d.ts', }), Components({ // 模板里写 <el-button> 时自动注册对应组件 resolvers: [ElementPlusResolver()], dts: 'src/components.d.ts', }), ], })

AutoImport管的是 JS 里的 API,比如你写ElMessage.success('ok')不用 import;Components管的是模板里的标签,写<el-table>不用注册。两个dts选项生成声明文件,TypeScript 才能认出这些自动导入的符号,不然编辑器会标红但运行正常,属于典型的「看着像错其实没错」。

配完之后要把main.ts里的全量引入删掉,否则两套机制打架:

// main.ts:按需引入后不再 app.use(ElementPlus) import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.mount('#app')

有一个细节要提醒:ElMessage、ElLoading这类通过函数调用的组件,样式不会自动跟着走,因为它们不在模板里,插件分析不到。稳妥做法是在main.ts里显式引一次它们的样式:

// 函数式调用的组件样式需要手动引,否则弹窗出来是白板 import 'element-plus/theme-chalk/el-message.css' import 'element-plus/theme-chalk/el-loading.css'

如果项目要用 SCSS 定制主题,ElementPlusResolver要加importStyle: 'sass',同时装sass依赖,并且vite.config.ts里配css.preprocessorOptions.scss.additionalData引入变量文件。这条路能改主题色,但配置项多一层,新手先跑通默认样式再动主题,别一上来就两个变量一起改。

4.3 mockjs 与 vite-plugin-mock 的规则配置

mock 这块有两种做法:一种是在代码里手动Mock.mock(url, template)拦截 XHR,另一种是用vite-plugin-mock在 dev server 层拦请求。前者对 axios 的适配偶尔有问题,且不好做路径匹配;后者直接挂在 Vite 的中间件上,请求在到达浏览器之前就被接管,更干净。我一般用后者。

# mockjs 提供数据模板,插件负责挂载拦截 npm i -D mockjs vite-plugin-mock

配置分两步,先在vite.config.ts里挂插件:

// vite.config.ts:mock 插件配置 import { viteMockServe } from 'vite-plugin-mock' export default defineConfig({ plugins: [ // ...其他插件 viteMockServe({ mockPath: 'mock', // mock 文件所在目录,相对项目根目录 enable: true, // 开发环境开启 logger: true, // 请求命中 mock 时在终端打日志,排查很有用 }), ], })

再写 mock 文件,一个模块一个文件,放在mock/下:

// mock/user.ts:用户列表假数据,路径要和前端请求的 url 完整匹配 import type { MockMethod } from 'vite-plugin-mock' export default [ { url: '/api/user/list', // 必须和 axios 的 baseURL + 路径拼出来一致 method: 'get', response: ({ query }) => { const page = Number(query.page) || 1 return { code: 200, data: { total: 42, // mockjs 语法:list|10 表示生成 10 条数组 'list|10': [{ 'id|+1': 1, name: '@cname', // 随机中文名 email: '@email', 'age|18-60': 1, createTime: '@datetime', }], page, }, } }, }, ] as MockMethod[]

这里的坑集中在url上。mock 的匹配是完整路径匹配,你前端 axios 配了baseURL: '/api',请求写request.get('/user/list'),实际发出的是/api/user/list,mock 里就得写全/api/user/list,写/user/list是命中不了的。'list|10'是 mockjs 的模板语法,竖线后面的数字是生成条数,'id|+1': 1是自增,@cname、@email这些是占位符,会替换成随机内容。response函数能拿到query、body,做分页和搜索的模拟够用了。

4.4 用环境变量把 mock 关在生产之外

mock 规则写完,最危险的一件事是它跟着打包上线。表现是线上环境接口本该报错的地方,返回了一堆假数据,用户看到的是测试内容。根因是开关写死了:

// 错误写法:enable 恒为 true,生产构建也会注入 mock 中间件 viteMockServe({ enable: true })

正确做法是让开关跟着环境变量走。viteMockServe的enable参数接收布尔值,在配置文件里可以读process.env,因为vite.config.ts跑在 Node 环境:

// vite.config.ts:按启动模式决定是否启用 mock import { defineConfig, loadEnv } from 'vite' export default defineConfig(({ mode }) => { // 第三个参数传空字符串,加载全部变量而不只是 VITE_ 前缀的 const env = loadEnv(mode, process.cwd(), '') return { plugins: [ viteMockServe({ mockPath: 'mock', // 只有开发模式且显式开启时才挂 mock enable: mode === 'development' && env.VITE_USE_MOCK === '1', }), ], } })

loadEnv(mode, process.cwd(), '')这行的第三个参数容易写错。默认只加载VITE_前缀的变量,传空字符串才加载全部;而process.env.VITE_USE_MOCK在配置文件里不一定能直接读到,因为 Vite 还没把 env 注入进去。用loadEnv显式读取是稳妥写法。

前端请求层也要配套判断,避免 mock 关掉之后请求还指向不存在的地址:

// src/api/request.ts:axios 实例的基础配置 import axios from 'axios' const request = axios.create({ // 从环境变量取,开发环境是 /api,生产环境换成真实网关 baseURL: import.meta.env.VITE_APP_BASE_API, timeout: 10000, }) export default request

.env.production里把VITE_APP_BASE_API写成真实接口前缀,VITE_USE_MOCK写0。这样npm run build出来的包里既没有 mock 数据,请求也会走到真实后端。验证方法很简单:构建后在dist里搜一下mockjs的痕迹,搜不到就说明没打进去。

5. 避坑与排查:这套组合出问题的五个高频点

前面按正常路径走了一遍,但实际装的时候不会这么顺。这一章列五个我踩过或者帮人排查过的具体问题,每个都按「现象 → 原因 → 解决」写,遇到对得上的直接照方抓药。

5.1 依赖与版本类问题

现象一:npm run dev直接报TypeError: crypto.hash is not a function,一行业务代码都没执行。

原因是 Node 版本低于 Vite 的要求。Vite 5 起用了 Node 18 才有的crypto.hash,Node 16 上跑必然抛这个错。解决是把 Node 升到 18 以上,我一般用 20.x LTS,切完版本删掉node_modules重装:

# 切版本后必须重装,原生模块跟 Node 版本绑定 nvm install 20 nvm use 20 rm -rf node_modules npm ci

现象二:页面白屏,控制台报Cannot read properties of null (reading 'isCE')或者组件渲染异常但定位不到代码。

原因是装出了两份 Vue。常见于 lock 文件混用,或者某个依赖自己带了一份 Vue。先用npm ls vue确认,如果输出里出现两个路径,就清干净重装,只留一种包管理器和一份 lock 文件。如果是某个第三方库强依赖旧版 Vue,用package.json的overrides强制统一版本:

{ "overrides": { "vue": "$vue" } }

"$vue"表示跟项目自己的vue版本一致,这样能压掉嵌套依赖里的旧版本。

5.2 配置与运行时类问题

现象三:Element-Plus 组件能渲染,但完全没有样式,按钮是裸的 HTML 样子。

原因分两种。一种是全量引入时漏了import 'element-plus/dist/index.css';另一种是按需引入时ElementPlusResolver没配importStyle,或者插件装了但vite.config.ts里没生效。先检查main.ts有没有残留的全量引入,再检查插件配置。如果是按需模式,把Components插件的resolvers确认写上,然后重启 dev server,插件配置改动不重启不生效。

现象四:mock 接口一直 404,或者请求跑到了真后端。

原因基本是路径不匹配。前端baseURL是/api,请求路径是/user/list,拼出来/api/user/list,mock 文件里必须写全这个路径。另一个原因是server.proxy也配了/api的代理,Vite 的中间件顺序里 proxy 可能先于 mock 处理,请求被转发走了。排查时打开viteMockServe的logger: true,请求命中 mock 会在终端打日志,没日志就说明没命中,问题在路径或中间件顺序。开发期用 mock 就把 proxy 里对应前缀注释掉。

现象五:本地一切正常,npm run build之后部署,线上接口返回假数据。

原因是 mock 开关写死成enable: true,或者判断条件没考虑mode。构建时mode是production,只要开关跟着mode和VITE_USE_MOCK走就不会出这个问题。已经上线的项目,去dist/assets里搜mockjs特征字符串,能搜到就说明打进去了,回头改配置重新构建。这类问题属于上线前必查项,别等用户反馈。

6. 装完怎么验证:三条链路跑通才算数

npm run dev起来、页面能看见,只能说明服务启动了,不代表这套环境配好了。我验证这套 Vue3 + Element-Plus + mockjs 骨架,固定跑三条链路,任何一条不通都算没装完。

第一条是组件链路。打开页面,找一个用了 Element-Plus 组件的路由,确认三件事:组件渲染正常、样式生效、图标能显示。样式最容易骗人,按钮有边框不代表样式全加载了,重点看表格、弹窗、下拉这类结构复杂的组件,它们对 CSS 依赖更重。图标用的是@element-plus/icons-vue,按需模式下图标组件不会自动注册,需要手动全局注册或者在页面里单独引:

// main.ts:图标全局注册,按需模式下必须手动做 import * as ElementPlusIconsVue from '@element-plus/icons-vue' for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) }

第二条是 mock 链路。打开浏览器开发者工具的网络面板,触发一次列表请求,看响应体里是不是code: 200加一串随机数据。这一步的关键是看请求有没有真的发出去:如果网络面板里根本没有这条请求,说明被 mock 中间件提前拦了,属于正常;如果发出去且返回 404,说明 mock 没命中,回上一章查路径。再确认分页参数能传进去,response函数里拿到的query.page有值,说明参数透传没问题。

第三条是环境切换链路,也是最容易被跳过的一条。执行一次生产构建:

# 生产构建,构建产物里不应包含 mock 数据 npm run build # 本地预览构建产物,模拟线上环境 npm run preview

然后在dist目录里搜一下mockjs、@cname这类特征串,搜不到才算干净。再打开预览页面,发一次请求,这时候应该打到真实后端或者报跨域,而不是返回假数据。三条链路对应的检查点我整理成表:

链路检查点通过标准
组件表格、弹窗、图标渲染正常且样式完整
mock网络面板响应体返回模板数据,分页参数生效
环境切换构建产物与预览请求产物无 mock 特征,请求不走拦截

这套验证流程我从一次线上事故之后固定下来的。那次是 mock 开关写死,本地测得好好的,构建上线后用户看到的全是假数据,排查了两个小时才发现问题出在一个布尔值上。从那以后我每次装完这套骨架,不管多急,npm run build加一次产物搜索都强制走一遍,五分钟的事,比上线后回滚便宜太多。希望帮到你。

本文还有配套的精品资源,点击获取