06 · 构建打包与部署

1 阅读2分钟

6.1 error during build: Rollup failed to resolve import "xxx"

症状:dev 能跑、npm run build 报错。

原因:dev 下 Vite 按需解析宽松,build 走 Rollup 严格,要求所有 import 显式声明。

解决:

  • 补上正确的依赖声明(npm i xxx)
  • build.rollupOptions.external 显式标记外部依赖(CDN 引入的不需要打包)

6.2 [vite]: Rollup failed to resolve import "antd/es/locale/zh_CN"

antd 5 locale 路径变更:

  • 旧:antd/es/locale/zh_CN
  • 新:antd/locale/zh_CN

6.3 产物体积过大

定位:

npm run build
# 或加可视化插件
npm i -D rollup-plugin-visualizer

常见大头:

  • echarts(全量引入)→ 改按需 import
  • moment(已被 dayjs 替代,本项目已是)
  • antd 图标 → 用 @ant-design/icons 按名 import,不要 import * as Icons
  • lodash → 用 lodash-es 或 import debounce from 'lodash/debounce'

echarts 按需示例:

import * as echarts from 'echarts/core';
import { LineChart } from 'echarts/charts';
import { GridComponent, TooltipComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

echarts.use([LineChart, GridComponent, TooltipComponent, CanvasRenderer]);

6.4 tsc -b 在 CI 失败,本地正常

原因:

  • 大小写文件名差异(Win 不敏感 / Linux 敏感)
  • node_modules 版本不一致(本地缓存旧版)→ CI 必须 npm ci 而非 npm i
  • TS 版本不一致 → 锁 typescript 到 devDependencies 精确版本

6.5 部署后白屏:Failed to load module script: Expected a JavaScript module script but the server responded with MIME type "text/html"

原因:nginx 没正确返回 JS 的 MIME,或 SPA history 兜底把 /assets/*.js 也兜到 index.html

修法:nginx 里 try_files 排除静态资源:

location / {
  try_files $uri $uri/ /index.html;
}
location /assets/ {
  try_files $uri =404;
  expires 1y;
  add_header Cache-Control "public, immutable";
}

6.6 base 配置导致资源 404

场景:部署到子路径(如 /app/),Vite 的 base 没设,index.html 引用 /assets/... 报 404。

修法:

// vite.config.ts
defineConfig({ base: '/app/' });

并保证后端路由前缀一致。

6.7 chunk 加载失败:Loading chunk N failed

原因:发布新版本后,旧用户访问到老 index.html,但 chunk 文件名已改(hash 变化),老 chunk 404。

修法:

  • 路由懒加载处 catch 错误,提示用户刷新
  • import.meta.hot 或 service worker 检测版本更新
const Foo = lazy(() =>
  import('./Foo').catch(() => {
    window.location.reload();
    return { default: () => null };
  })
);

6.8 环境变量未注入

症状:import.meta.env.VITE_FOO 在生产环境是 undefined

原因:

  • 没用 VITE_ 前缀(Vite 只暴露这个前缀的变量)
  • .env.production 没放到打包时的 cwd
  • CI 上环境变量没注入到构建任务

定位:打包后 grep -r "VITE_FOO" dist/,看是否被替换为字面量。

6.9 sourcemap 暴露源码

生产不希望泄露源码:

defineConfig({ build: { sourcemap: false } });

希望 Sentry 等错误追踪能定位:

build: { sourcemap: 'hidden' } // 生成但不引用,上传给 Sentry

6.10 兼容性问题:旧浏览器白屏

症状:Chrome / Edge 正常,某些用户(老 Safari、企业 IE 套壳)白屏。

原因:Vite 默认 target 是 ESM(esnext),不兼容老浏览器。

修法:

npm i -D @vitejs/plugin-legacy
import legacy from '@vitejs/plugin-legacy';
plugins: [
  react(),
  legacy({ targets: ['defaults', 'not IE 11'] }),
]

6.11 构建慢

  • vite build --profile 看耗时
  • 关掉不必要的 plugin
  • TS 检查与 build 并行:tsc -b --noEmit & vite build(注意是 shell 后台)
  • 服务器构建用 SSD 而非 NFS / 网络盘