AIGC标识 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 分钟)

  1. 看 dist/js:
    • 只有 app / chunk-libs / chunk-elementUI 三五个文件
    • app.js 几十 MB、能搜到 ./src/App.vue 这种路径注释
    • 没有独立 CSS
  2. 打开测试环境 DevTools → Network:
    • app.*.js 体积异常大
    • 接口域名仍是测试的(说明不是「打成正式包」)
  3. 对比正式包:
    • 大量 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 出现大量路由 chunk
  • app.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(内容变了文件名才变)。这是缓存策略问题,和这次「包没压缩」是两件事,可以后续再做。

posted @ 2026-10-29 16:16  jialiangzai  阅读(10)  评论(1)    收藏  举报