vue.config.js配置全解:从开发调试到构建优化的核心技能
2026/9/14 20:52:38 网站建设 项目流程

我最早意识到vue.config.js是“绕不过去的坎”,是在一个项目上线前最后一晚:本地跑得飞快的 Vue 项目,一部署到测试服务器就白屏,控制台报了一堆静态资源 404。接着是后端同事说接口跨域了,再然后是首屏加载直接把我电脑风扇转满。三个问题全指向同一个文件,而当时我的vue.config.js还几乎是个空壳。

后来做过的 Vue 项目越多,越发现这个文件才是 Vue CLI 工程真正的“中枢神经”。它看起来只是导出一个对象,实际控制着开发服务器、构建产物、Loader 规则、插件注入、多环境变量,几乎决定了你的项目在上线前是省心还是糟心。这篇文章我想从实际踩坑的角度,把这几年在vue.config.js里沉淀下来的配置思路、原理解释和可复用的配置片段一次讲透。

1. 为什么说 vue.config.js 是 Vue CLI 项目的中枢配置

很多人第一次见到vue.config.js,是在脚手架生成的项目根目录里。它可选、可空、甚至删掉项目也能跑,于是不少同学就默认它是“不急着学的东西”。但这个认知在工程规模变大后会立刻反噬。

1.1 它到底在配置什么层面

Vue CLI 3 之后的核心设计思路是“零配置上手,渐进式自定义”。脚手架帮你把 Webpack、DevServer、PostCSS、ESLint 这些底层工具全部封装好了,对外只暴露一个统一入口。vue.config.js就是这个入口,它在@vue/cli-service启动时被加载,经过内部处理后再合并成最终的 Webpack 完整配置。

它实际控制的层级可以分成四层:

  • DevServer 层:本地开发服务器的端口、代理、热更新、host 配置,全在这里控制。
  • Build 输出层:产物目录、静态资源路径、文件名 hash、sourcemap 策略,决定打包出来的 dist 长什么样。
  • Loader 与规则层:哪些文件走什么 loader 处理、哪些依赖需要被转译、如何修改已有的 webpack 规则。
  • 插件层:往构建流程里注入自定义 Webpack 插件,比如体积分析、代码压缩、CDN 加速。

这四层几乎覆盖了一个前端工程从开发到上线的全部链路。所以,配置不熟的项目,日常开发不会有感觉,因为 DevServer 的默认值基本够用,但一到部署、一到性能优化、一到多环境切换,就开始连环踩坑

1.2 加载时机与基本形态

vue.config.js运行在 Node.js 环境中,用的是 CommonJS 语法,而不是 ES Module:

// vue.config.js const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, lintOnSave: false, devServer: { port: 8080, }, })

这里需要注意:凡是业务代码里能用import的语法,在这个文件里都不能直接用(除非你用 CJS 的require变通)。我见过有人好奇地在里面写export default,结果 CLI 直接报“Unexpected token 'export'”。这个文件本质是一个 Node 脚本,不是在浏览器里跑的模块。

另外还有一个很实用的判断标准:这个文件里绝对不能写任何业务逻辑。它是构建期的配置文件,不是运行时代码,不要尝试在这里面放接口地址、业务枚举、权限表之类的数据。跨环境变量有专门机制(后面讲.env文件),归它管的只有构建行为本身。

注意:改完 vue.config.js 里的大部分配置(尤其是 devServer 相关),必须手动重启 npm run serve,热更新不会自动加载。这一点很多人反复踩坑,改了半天页面没变化,以为是配置写错了,其实纯粹是没重启。

1.3 默认值为什么要清楚

很多人配置报错,是因为不知道默认值是什么。比如publicPath默认是/,意味着构建产物的所有资源引用都是以根路径开头;比如outputDir默认是dist;比如assetsDir默认是空字符串,静态资源直接平铺在 dist 根目录。

我整理了一份高频配置项清单,方便你对照排查:

表:vue.config.js 核心配置项速查

配置项默认值作用常见适配场景
publicPath/打包资源的基础路径部署在子路径或 CDN 时必须改
outputDirdist构建产物输出目录后端有固定目录要求时改
assetsDir''静态资源子目录想让 js/css/img 分目录存放时改
indexindex.html入口 HTML 文件名后端模板接管时需要改
productionSourceMaptrue生产环境是否产出 sourcemap有安全/体积要求时设 false
lintOnSavetrue保存时是否执行 eslint 检查觉得卡顿或想交给 CI 时设 false
transpileDependencies[]指定 node_modules 中需要被 babel 转译的依赖安装的包是 ES 版本时用
devServer内置默认开发服务器配置端口/代理/热更新等

把这张表记在心里,很多配置问题根本不用搜索,直接查自己的场景属于哪一行就行。

2. devServer 代理配置:本地联调的第一道拦路虎

前后端分离开发时,本地页面请求后端接口几乎必然遇到跨域。因为你的开发服务器跑在localhost:8080,后端接口地址是http://192.168.1.10:9090,两边端口不同、host 也可能不同,浏览器同源策略直接就把请求拦了。

解决方案有两个方向:后端开启 CORS,或者前端做代理。在真实的团队协作里,后端的 CORS 通常只放行特定域名,本地开发环境的 host 千奇百怪,所以最稳妥的做法就是让 DevServer 做转发代理,浏览器看到的所有请求都发往同一个源,跨域问题从根上消失。

2.1 一段靠谱的 proxy 配置

以下是我项目中经常使用的代理配置:

// vue.config.js module.exports = { devServer: { port: 8080, host: '0.0.0.0', proxy: { '/api': { target: 'http://192.168.1.10:9090', changeOrigin: true, ws: true, pathRewrite: { '^/api': '' }, // 后端接口没有统一前缀时,需要重写路径 }, }, }, }

字段拆开解释一下:

  • target:后端真实地址。可以是内网 IP、局域网域名,也可以是线上环境的临时地址。
  • changeOrigin: true:让代理转发时把请求头里的 Host 字段改成 target 的域名。很多后端接口会根据 Host 做校验或路由,不加这个字段会得到诡异的 404。
  • pathRewrite:路径重写。这里的意思是把请求路径开头的/api去掉,再转发给后端。比如前端请求/api/user/list,后端实际收到的是/user/list

这组配置是我踩了无数次坑以后固定下来的:前端请求全带/api前缀,后端服务不一定有这个前缀,所以必须重写。如果你的后端所有接口本身就带/api,那 pathRewrite 这一行可以删掉。

2.2 axios baseURL 与 pathRewrite 的配合细节

很多同学在 axios 里写baseURL: '/api',又在代理里把/api重写掉了,结果请求发出去变成/user/list,代理一看“没有/api开头的路径”,直接不转发,最后请求落在 DevServer 自己身上,返回一个 index.html。

正确的配合方式是二选一:

  • 方案 A:axios baseURL = '/api',代理里pathRewrite: { '^/api': '' },后端不需要感知/api前缀。
  • 方案 B:axios baseURL = ''或具体接口路径,代理里不写pathRewrite,后端接口本身就带/api

我个人推荐方案 B,因为生产环境如果也用 Nginx 做同源反向代理,后端大概率是有统一前缀的,开发环境保持一致的路径规则,可以减少环境切换时“路径对不上”的坑。

2.3 配置不生效的三大原因

代理配置看起来简单,但经常有人配了以后还是没有效果。我遇到过的原因基本逃不出这三个:

第一,没有重启 dev server。代理配置在 devServer 启动时就固定了,保存文件不会重新加载,必须重启。

第二,请求路径根本没经过代理。如果你的前端项目部署后通过 Nginx 访问,而你在浏览器访问的地址是 Nginx 的地址,代理根本不参与。代理只作用于本地 DevServer 启动时的开发环境。

第三,代理前缀与 axios baseURL 不一致。请求发出去了,但实际路径不是以/api开头,代理规则匹配不上。建议配置完先打开浏览器 Network 面板看请求 URL 的 Path 部分,确认它走到了预期前缀。

注意:changeOrigin 在大多数场景下都建议设为 true。尤其是请求公司内网统一登录系统(SSO)或网关的时候,Host 不对会被直接拒绝或跳转错误。

3. publicPath:部署白屏和 404 的第一嫌疑

这一节必须单独拿出来说,因为publicPath 的配置错误是线上事故出现频率最高的一种。它控制的是构建产物中所有静态资源(JS、CSS、图片、字体)的引用路径,默认值是/

3.1 根路径和相对路径的区别

默认的/代表所有资源引用从域名根路径开始:

<script src="/js/app.abc123.js"></script>

如果你的应用部署在域名根路径https://example.com/下,没问题,资源能正常加载。

但如果部署在子路径下,比如团队用 Nginx 将前端应用挂在https://example.com/web/下,那浏览器会去请求https://example.com/js/app.abc123.js,而真实文件位于https://example.com/web/js/,自然 404,应用白屏。

解决方式是改成相对路径:

module.exports = { publicPath: './', }

这样构建产物里的资源引用会变成:

<script src="js/app.abc123.js"></script>

页面从哪个子路径打开,资源就从哪个子路径下拼接获取,灵活性最大。但相对路径也有代价:如果你的前端应用做了 history 路由(mode: 'history'),并且在二级路径下刷新页面,Nginx 的 try_files 需要正确回退到 index.html,否则子路由下的资源路径同样会错乱。

3.2 publicPath 与 vue-router base 的联动

这里有一个非常容易忽略的点:改了 publicPath,路由 base 也要同步改

比如你的应用部署在/web/下,publicPath已经设成/web/了,但 vue-router 的createWebHistory()默认使用location.pathname作为基准路径,你在 Nginx 里必须保证所有/web/前缀下的请求都回退到index.html

如果不想在代码里硬编码/web/,可以借助环境变量:

// 推荐写法,避免硬编码 const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes, })

Vue CLI 构建时默认会注入process.env.BASE_URL,它的值正好来自publicPath。所以保持两者一致,路由就不会因为路径嵌套而错乱。

3.3 真实部署场景下的 publicPath 组合

不同部署方式对应的配置确实不同,我在项目里验证过这几类:

表:部署场景与 publicPath 推荐值

部署方式publicPath 推荐值说明
域名根路径/最简单,常规部署
Nginx 子路径/web/静态资源全在 /web/ 下
独立 CDN + 主域名线上 CDN 地址静态资源全走 CDN,页面托管在主站
本地 file 协议打开./不通过服务器直接打开 dist/index.html,适合临时预览

我遇到过最极端的场景是:静态资源放 CDN,CDN 域名是cdn.example.com,应用本身跑在www.example.com。这种时候 publicPath 就设成https://cdn.example.com/,构建出来的 JS 引用也全部指向 CDN。但如果 CDN 回源配置不到位,文件会加载失败,所以选这条路之前先确认 CDN 的回源策略。

提示:publicPath 不是只能写成静态字符串,它可以是相对路径、绝对路径、甚至是完整 URL。Vue CLI 会把它直接拼接进资源路径里。所以只要你的部署拓扑明确了,这个值就不难确定。

4. configureWebpack 与 chainWebpack:深度定制 Webpack 的两种姿势

Vue CLI 把 Webpack 配置封装了一层,但总有默认配置满足不了的需求:加一个插件、改几个 Loader 选项、调整压缩参数。这种时候就需要直接操作 Webpack 配置,有两条路:configureWebpackchainWebpack

4.1 什么时候用 configureWebpack

configureWebpack支持接收对象或函数。对象形式适合新增配置项,比如加一个插件:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports = { configureWebpack: { plugins: [ new BundleAnalyzerPlugin(), ], }, }

函数形式适合需要拿到最终配置后再修改的场景:

module.exports = { configureWebpack: (config) => { if (process.env.NODE_ENV === 'production') { config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true } return config }, }

这里我配置的是生产环境下自动去掉console.log。因为压缩 minifier 在默认配置里是一个数组,函数形式可以方便地直接访问并修改它。

4.2 什么时候必须用 chainWebpack

如果要修改已有的默认规则configureWebpack就不够用了。比如你想给某个 loader 加参数、想把某个规则从默认匹配中剔除、想修改默认的 splitChunks 行为,这些操作在对象合并中无法表达,必须用chainWebpack的链式调用来精确修改。

chainWebpack基于 webpack-chain 库,风格是链式 API。我实际用到最多的是给 svg 文件新增一个自定义规则:

module.exports = { chainWebpack: (config) => { // 找到默认的 svg 规则,排除掉 icons 目录 config.module .rule('svg') .exclude.add(path.resolve(__dirname, 'src/assets/icons')) .end() // 给 icons 目录下的 svg 新增一个规则,使用 svg-sprite-loader config.module .rule('icons') .test(/\.svg$/) .include.add(path.resolve(__dirname, 'src/assets/icons')) .end() .use('svg-sprite-loader') .loader('svg-sprite-loader') .options({ symbolId: 'icon-[name]' }) }, }

这套配置在做图标雪碧图的时候非常常见:让大部分 svg 走默认的 file-loader,单独把某个目录下的 svg 交给 svg-sprite-loader 处理,生成 symbol 集合,方便用<svg><use>引用。

4.3 基于环境变量动态切配置

实际项目里常有这种需求:测试环境需要 sourcemap 定位问题,生产环境为了安全不要 sourcemap;或者测试环境不压缩代码,方便报错行号还原。跨环境差异就该用环境变量来驱动,而不是在发布前手动改配置。

// vue.config.js const isProd = process.env.NODE_ENV === 'production' module.exports = { productionSourceMap: !isProd, css: { sourceMap: !isProd, extract: isProd, }, configureWebpack: (config) => { if (!isProd) { config.devtool = 'eval-cheap-module-source-map' } }, }

现在部署平台都会注入NODE_ENV(npm scripts 里也能通过--mode指定),所以配置里通过process.env.NODE_ENV做分支判断是最保险的做法,不需要额外引入第三方库。

5. 构建性能与产物优化:配置里的每一行都在为上线铺路

vue.config.js里关于构建优化的配置,是收益最明显也最容易被忽略的一块。项目规模一大,首次构建 2 分钟、二次构建 40 秒、单文件超过 1MB,是很常见的事。下面这三板斧我几乎在每个项目里都会用。

5.1 体积分析先行:不知道哪里大,优化无从谈起

很多人的优化是盲目的——抽了个公共库,体积没降多少;加了个压缩插件,构建时间反而涨了。所以我建议第一步永远是先接入体积分析插件:

const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') module.exports = { chainWebpack: (config) => { if (process.env.npm_config_report) { config .plugin('webpack-bundle-analyzer') .use(BundleAnalyzerPlugin, [{ analyzerPort: 8888 }]) } }, }

这样当你运行npm run build --report时,构建完成会自动打开一个可视化页面,你的dist里哪个包占了多大体积、哪个依赖是重复引用的、哪个大库其实可以换懒加载,全部一目了然。

5.2 第三方库 CDN 化:externals 的正确打开方式

像 Vue、Vue Router、Axios、Element UI 这类几乎不会变的库,完全可以不参与打包,而是通过 CDN 引入,构建产物体积能小一半还不止。

配置方式分两步。第一步,在vue.config.js里告诉 Webpack 这些依赖不用打包了:

module.exports = { configureWebpack: { externals: { vue: 'Vue', 'vue-router': 'VueRouter', axios: 'axios', 'element-ui': 'ELEMENT', }, }, }

第二步,在public/index.html里通过 CDN 标签引入这些库。注意顺序:先引 Vue 和 Router,再引 Element UI,再引你自己的业务代码。这个过程本质上是在说:“名字叫 Vue 的全局变量就是 vue 这个包,构建时不用管它,运行时浏览器会给你。”

外链 CDN 有一个容易被忽略的细节:CDN 挂掉或网络被墙,整个应用直接白屏。所以如果是内网部署,更稳的方案是把这些静态文件下载到本地,由 Nginx 托管,配置里照样用 externals 排除打包,但 HTML 里的 src 指向本地路径。

5.3 构建提速:让 Webpack 少干点重复活

构建速度的优化,核心思路是“少编译、多缓存”。下面是几个配置维度的经验值:

  • transpileDependencies: []:默认情况下 CLI 不会对 node_modules 里的文件做 Babel 转译,这是正确的。如果你额外安装的包需要转译(比如 lib-flexible、vant 的 ESM 版本),才需要把它们加进来,不要无脑全量转译。
  • 开启cache-loader:Vue CLI 默认就带了 Babel 的缓存,一般不必额外配置。你真正需要关注的是有没有在业务代码里import了过多的大模块。
  • 对于大型项目,可以尝试把thread-loader加到 babel-loader 之前,让多进程并行转译 JS。注意不是所有场景都值得,小项目加上反而因为进程调度拖慢速度。

给一组可用的 chainWebpack 示例:

const path = require('path') module.exports = { chainWebpack: (config) => { config.module .rule('js') .test(/\.m?jsx?$/) .exclude.add((filepath) => { // 不转译 node_modules 下大部分包,只保留指定需要转译的包 return /node_modules/.test(filepath) && !/node_modules[\\/](vue-awesome-swiper)[\\/]/.test(filepath) }) .end() }, }

exclude函数里可以精细控制哪些 node_modules 里的包需要被处理,哪些不用处理,这个比全量排除再放行要灵活很多。

5.4 sourcemap 策略:开发要方便,上线要安全

sourcemap 是构建产物和源码的映射文件,看报错堆栈时很有用,但它同时也是暴露源码的工具,生成的.map文件体积还不小。一个常见配置组合是:

module.exports = { productionSourceMap: false, // 生产环境不生成 .map 文件 css: { sourceMap: process.env.NODE_ENV !== 'production', }, }

如果团队确实需要线上定位问题,可以考虑只在测试环境打开 sourcemap,生产环境关闭。大部分公司的做法是生产环境配合一套错误监控平台(如 Sentry),错误上报时带上 release 版本号,再通过 sourcemap 映射回来,这是一种更专业的兜底方案。

提示:关闭 productionSourceMap 后,如果后端或运维同事反馈线上报错看不到具体代码位置,不要直接打开 map。正确的做法是保留一份构建时的 map 文件到归档系统,线上不直接暴露。

6. 多环境配置:一套代码在不同环境间自由切换

一个前端项目通常至少有三个环境:开发、测试、生产。不同环境对应的接口地址、CDN 路径、路由模式可能都不同。vue.config.js本身做不了这件事,但它和.env文件配合得天衣无缝。

6.1 .env 文件的基本规则

Vue CLI 支持在项目根目录放.env.env.development.env.production等文件,文件里的键值对会自动注入到process.env中。但要注意:

  • 只有以VUE_APP_开头的变量才会被注入到客户端代码中。
  • NODE_ENVBASE_URL是特殊情况,不用加前缀,CLI 会自动注入。
  • 变量在所有vue.config.js可访问的 Node 环境里也能用。

举个例子:

// .env.development VUE_APP_API_BASE_URL = /api VUE_APP_PUBLIC_PATH = / // .env.production VUE_APP_API_BASE_URL = https://api.example.com VUE_APP_PUBLIC_PATH = https://cdn.example.com/

然后在vue.config.js里读取并使用:

module.exports = { publicPath: process.env.VUE_APP_PUBLIC_PATH || '/', devServer: { proxy: { '/api': { target: 'http://192.168.1.10:9090', changeOrigin: true, pathRewrite: { '^/api': '' }, }, }, }, }

业务代码里用它:

axios.defaults.baseURL = process.env.VUE_APP_API_BASE_URL

6.2 自定义 mode:不止开发和生产

CLI 默认只有developmentproduction两种模式,但实际工作中往往需要staging(预发布)、test(测试)、mock(模拟数据)等更多环境。通过--mode参数可以实现自定义:

// package.json { "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "build:test": "vue-cli-service build --mode test", "build:staging": "vue-cli-service build --mode staging" } }

运行时,CLI 会加载.env.test.env.staging文件。注意:--mode只是指定加载哪个.env文件,不会自动改NODE_ENV,所以你仍然需要在.env.test里手动指定NODE_ENV=production(因为测试环境也要走压缩构建),否则 CLI 默认把它当开发模式处理。

我见过很多人在这一环节翻车:npm run build:test构建出来居然还带着 sourcemap 且未压缩,就是因为没有在.env.test里补上NODE_ENV=production。这个坑报错不一定明显,但产物一看就露馅。

6.3 从 env 文件到配置生效的完整链路

把这套机制串起来看,一个典型的多环境配置链路是:

  1. 开发本地执行npm run serve,CLI 读取.env.developmentprocess.env.NODE_ENV被设为developmentVUE_APP_API_BASE_URL被注入。
  2. 同时读取vue.config.jspublicPathdevServer.proxy根据 env 变量的值生成。
  3. 构建时执行npm run build:test,CLI 读取.env.testNODE_ENV=production,代码压缩、关闭 sourcemap,接口指向测试地址。
  4. 正式上线执行npm run build,读取.env.production,接口、CDN 路径、publicPath 全部切换成生产值。

这样一套代码就能在开发、测试、预发、生产之间平滑切换,不用在部署时改任何业务代码,也不用运维同学临时帮你改配置。

7. 组合起来:一套可以直接落地的生产级配置

章节拆开讲完,我最后放一个完整示例。这个配置是我在多个中型后台管理项目中验证过的,涵盖了代理、多环境、体积优化、CDN、构建提速,你可以直接参考然后按需删减。

// vue.config.js const path = require('path') const { defineConfig } = require('@vue/cli-service') const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') const isProd = process.env.NODE_ENV === 'production' const isAnalyze = process.env.npm_config_report === 'true' module.exports = defineConfig({ transpileDependencies: true, lintOnSave: false, productionSourceMap: false, publicPath: process.env.VUE_APP_PUBLIC_PATH || '/', outputDir: 'dist', assetsDir: 'static', indexPath: 'index.html', devServer: { port: 8080, host: '0.0.0.0', client: { overlay: { warnings: false, errors: true, }, }, proxy: { '/api': { target: process.env.VUE_APP_DEV_TARGET || 'http://192.168.1.10:9090', changeOrigin: true, ws: true, pathRewrite: { '^/api': '' }, }, }, }, css: { sourceMap: !isProd, extract: isProd, }, configureWebpack: (config) => { // 生产环境去掉 console if (isProd) { config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true } // 接入体积分析 if (isAnalyze) { config.plugins.push(new BundleAnalyzerPlugin()) } }, chainWebpack: (config) => { // 配置别名 config.resolve.alias .set('@', path.resolve(__dirname, 'src')) .set('@views', path.resolve(__dirname, 'src/views')) // 忽略不需要打包的第三方库 config.plugin('ignore').use(require('webpack').IgnorePlugin, [ /^\.\/locale$/, /moment$/, ]) // 修改 html 插件参数,按需注入外部 CDN config.plugin('html').tap((args) => { args[0].cdn = { css: [], js: isProd ? [ 'https://cdn.example.com/vue/2.7.14/vue.min.js', 'https://cdn.example.com/vue-router/3.6.5/vue-router.min.js', 'https://cdn.example.com/axios/1.4.0/axios.min.js', ] : [], } return args }) }, })

这个配置是一个比较重的形态,实际项目可以根据团队情况砍掉一部分。比如你的部署环境用不到 CDN,就可以去掉 html plugin 的 CDN 注入;比如项目规模不大,就不需要 IgnorePlugin。

对应的.env文件(生产版):

// .env.production NODE_ENV=production VUE_APP_BASE_URL=https://example.com/ VUE_APP_PUBLIC_PATH=https://static.example.com/ VUE_APP_DEV_TARGET=https://api.example.com/

这里我把接口地址拆分成了VUE_APP_BASE_URL(页面域名)和VUE_APP_DEV_TARGET(后端接口地址),分别是业务代码和 devServer 代理使用的目标,互不干扰,部署时只要替换这些值即可。

上线前建议再核对这些配置项:

检查项正确姿势错误后果
publicPath与部署路径/CDN 地址一致静态资源 404、应用白屏
productionSourceMap生产环境设为 false源码泄露、构建产物过大
drop_console生产环境开启console 影响部分浏览器性能
devServer.proxy与后端实际地址一致联调失败、接口 404
.env文件内容不出现硬编码敏感信息密钥泄露、环境变量污染
CDN 外链有可用性保障外链挂掉时应用整体不可用

我在这套配置上踩过最深的坑,是上线前改完 publicPath 后忘记同步 update 路由 base,结果应用在子路径下确实能打开首页,但一旦进入二级路由刷新页面,Nginx 找不到对应的资源路径,全部 404。后来养成了习惯:凡是动 publicPath,必定检查 vue-router 的 history base,必定检查 Nginx 的 try_files 配置,三处保持一致再发包。

如果你现在维护的 Vue CLI 项目还没有系统梳理过vue.config.js,我建议你抽个下午把现有配置打开,对着上面这几类问题逐项过一遍。这个过程会让很多以前“跑得好好的、但不知道为什么会挂”的线上问题,一下子就有了答案。如果项目已经准备迁往 Vite,这份配置里的 publicPath、proxy、多环境变量的经验也可以平移过去,因为配置的本质是同一套部署逻辑,只是壳换了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询