VueCLI 测试环境打开很慢NODE_ENV和BABEL_ENV的坑
Vue CLI 测试环境打开很慢:NODE_ENV 和 BABEL_ENV 的坑
适用:Vue CLI 3/4 + webpack 的老项目(
vue-cli-service build --mode staging)
现象:deploy:stage/build:stage之后,测试环境每次打开都要转很久;正式环境build:prod却很快。
结论:测试包连的还是测试接口,但 打包方式走成了开发模式。
先记住两件事,它们不是一回事
| 开关 | 决定什么 | 典型写法 |
|---|---|---|
--mode staging |
读哪份配置、连哪套接口 | vue-cli-service build --mode staging → 读 .env.staging |
NODE_ENV=production |
Webpack 怎么打:压不压缩、抽不抽 CSS | 只认 production 才开生产优化 |
BABEL_ENV=production |
Babel 怎么转:路由会不会拆成多个 chunk | 走 development 时可能把懒加载打没 |
一句话:
- mode = 这包给哪个环境用(接口域名)
- NODE_ENV = 这包打得漂不漂亮(压缩优化)
- BABEL_ENV = 页面是拆开加载,还是全塞进一个大文件
很多人把 NODE_ENV 写成 staging,以为这样才叫「测试环境」。Vue CLI 看到不是 production,就会按 开发模式 打包。
典型事故现场
脚本
{
"build:prod": "vue-cli-service build --mode production",
"build:stage": "vue-cli-service build --mode staging",
"deploy:stage": "yarn build:stage && bash build/deploy-soft.sh dev"
}
错误的 .env.staging
NODE_ENV = 'staging'
ENV = 'staging'
VUE_APP_BASE_API = 'https://zyb-api2.fityun.cn'
VUE_APP_NEW_ORDER_API = 'https://zyb-dapi.fityun.cn'
VUE_APP_ERP_API = 'https://zyb-erp-api.fityun.cn'
接口是对的,测试环境没连到正式接口。问题出在第一行:NODE_ENV = 'staging'。
打出来的包长这样
| 文件 | 异常体积 |
|---|---|
dist/js/app.时间戳.js |
约 99MB,未压缩,带 webpack 路径注释 |
dist/js/chunk-libs.*.js |
约 14MB |
dist/js/chunk-elementUI.*.js |
约 2.5MB |
| CSS | 没有独立 .css 文件,样式全塞进 JS |
dist/js 里往往只有三四个文件。路由明明写了懒加载,却没有任何按页面拆出的 chunk。
浏览器每次打开都要下载、解析近 100MB 未压缩 JS,体感就是「项目又更新了,卡死」。正式包压缩 + 按路由拆包,所以线上很快。
原因拆开看
1. Webpack 只认 NODE_ENV === 'production'
Vue CLI 内部大致是:
// node_modules/@vue/cli-service/lib/config/prod.js
if (process.env.NODE_ENV === 'production') {
webpackConfig.mode('production')
}
默认 webpack mode 是 development。
NODE_ENV 写成 staging / test / dev 都不算生产,于是:
- JS 不压缩
- CSS 不抽成独立文件(
extract = isProd) - Vue 走开发版,带一堆运行时检查
.env 里的值优先级高于 Vue CLI 的默认值。你写了 NODE_ENV = 'staging',它就会尊重你,不会自动改回 production。
2. Babel 在 staging 构建时会误走 development
vue-cli-service build 的默认 mode 是 production。
一旦你传了 --mode staging,而 .env.staging 又没写 BABEL_ENV,Vue CLI 会把 BABEL_ENV 设成 development(因为它只把 production / test 当特殊 mode)。
很多从 vue-element-admin 拷来的项目里有这段:
// babel.config.js
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
env: {
development: {
// 把 import() 转成 require(),加快本地热更新
plugins: ['dynamic-import-node']
}
}
}
babel-plugin-dynamic-import-node 只该给 npm run dev 用。
路由本来是懒加载:
component: () => import('@/views/login/index')
插件生效后会变成同步 require(),所有页面打进一个 app.js。这就是 99MB 单文件的来源。
3. 时间戳文件名会放大这个问题
有的项目为了防缓存,把输出写成:
const Timestamp = new Date().getTime()
filename: `js/[name].${Timestamp}.js`
每次发版文件名都变,浏览器缓存全部失效。正式包体积小,还能接受;测试包 99MB 每次强制重下,就会「每次打开都像更新项目」。
时间戳不是这次变慢的根因,但会让开发态大包更难熬。根因仍是:没走生产打包。
怎么确认是这个问题(2 分钟)
- 看
dist/js:- 只有
app/chunk-libs/chunk-elementUI三五个文件 app.js几十 MB、能搜到./src/App.vue这种路径注释- 没有独立 CSS
- 只有
- 打开测试环境 DevTools → Network:
app.*.js体积异常大- 接口域名仍是测试的(说明不是「打成正式包」)
- 对比正式包:
- 大量
chunk-*.js(按路由拆的) app.js小很多- 有独立 CSS
- 大量
接口对、包却巨大 → 就是构建开关错了,不是后端、也不是运维缓存。
正确改法
.env.staging 建议写成:
NODE_ENV = 'production'
BABEL_ENV = 'production'
# 业务上区分测试 / 正式,用这个,不要用 NODE_ENV
ENV = 'staging'
VUE_APP_ADMIN_ORIGIN = 'https://zyb-admin-lianlian.fityun.cn'
VUE_APP_BASE_API = 'https://zyb-api2.fityun.cn'
VUE_APP_NEW_ORDER_API = 'https://zyb-dapi.fityun.cn'
VUE_APP_ERP_API = 'https://zyb-erp-api.fityun.cn'
改完后再 build:stage / deploy:stage,检查:
dist/js出现大量路由 chunkapp.js从几十 MB 降到正常生产体积- Network 里接口仍是
zyb-*,没有变成正式api2.fityun.cn
为什么两个都要改
| 只改这个 | 结果 |
|---|---|
只改 NODE_ENV |
会压缩,但懒加载仍被打掉,变成「压缩过的超大 app.js」 |
只改 BABEL_ENV |
页面能拆开,但不压缩、不抽 CSS |
两个都写成 production |
压缩 + 抽 CSS + 按路由拆包,接口仍走测试 |
Vue 官方就是这个用法:测试环境的配置文件里,NODE_ENV 也写 production,接口地址继续写测试域名。
业务代码里不要用 NODE_ENV 判断测试环境
改完之后,stage 包里的 process.env.NODE_ENV 会变成 'production'。
如果业务里写了:
isTest: process.env.NODE_ENV == 'development' || process.env.NODE_ENV == 'staging'
这个值会从 true 变成 false。
正确做法:用自己的环境标记,例如:
process.env.ENV === 'staging'
// 或项目里注入的
process.env.VUE_APP_BUILD_MODE === 'staging'
NODE_ENV 在打包场景里只表示「按生产方式优化」,不表示「这是线上」。
接口请求更是只看 VUE_APP_*:
baseURL: process.env.VUE_APP_BASE_API
这份值来自 .env.staging,跟 NODE_ENV 无关。所以 改构建开关不会把测试包打成正式包。
一张图串起来
npm run build:stage
│
▼
--mode staging ──────────► 读 .env.staging
VUE_APP_* = 测试接口 ✅
│
├── NODE_ENV=production ──► Webpack 压缩 / 抽 CSS / Vue 生产版
│
└── BABEL_ENV=production ─► 不启用 dynamic-import-node
路由 import() 保留,按页拆 chunk
以前缺的是下面两步,所以上面接口是对的,包却是开发态。
给同事的检查清单
新项目或新同事接手时,打开 .env.staging 看一眼:
本地 npm run dev 不受影响:serve 时 NODE_ENV / BABEL_ENV 仍是 development,热更新插件该在的时候还在。
延伸:文件名用时间戳还是 contenthash
生产优化修好之后,测试环境已经能用。如果还想让「没改过的库文件」继续走缓存,可以把:
filename: `js/[name].${Timestamp}.js`
改成 webpack 默认的 contenthash(内容变了文件名才变)。这是缓存策略问题,和这次「包没压缩」是两件事,可以后续再做。
本文来自博客园,作者:jialiangzai,转载请注明原文链接:https://www.cnblogs.com/zsnhweb/p/23483347

浙公网安备 33010602011771号