Skip to content

vue.config.js 系统学习文档 ​

适合人群:正在维护 Vue CLI 项目,尤其是 Vue2 老项目、Vue3 + Vue CLI 项目,或者需要理解旧项目工程配置的学习者。

学习目标:理解 vue.config.js 是什么、放在哪里、常用配置怎么写、如何配置代理、路径、构建输出、Webpack 扩展、CSS 和环境变量。

核对时间:2026-06-18。Vue CLI 已进入维护模式,新项目通常更推荐 Vite,但大量存量项目仍然需要理解 vue.config.js。


目录 ​

  1. vue.config.js 是什么
  2. 它和 vite.config.ts 有什么区别
  3. 最小配置写法
  4. 常用基础配置
  5. 开发服务器 devServer 配置
  6. CSS 相关配置
  7. configureWebpack 与 chainWebpack
  8. 路径别名配置
  9. 多页面 pages 配置
  10. 环境变量在 vue.config.js 中的使用
  11. 常见生产环境配置
  12. 常见实战场景
  13. 初学者常见坑
  14. 推荐学习顺序
  15. 学习资源

1. vue.config.js 是什么 ​

vue.config.js 是 Vue CLI 项目的全局配置文件。

它通常放在项目根目录:

text
my-vue-cli-app/
├── public/
├── src/
├── package.json
├── babel.config.js
└── vue.config.js

Vue CLI 内部基于 Webpack。vue.config.js 的作用是让你不用直接维护完整 Webpack 配置,也能修改常见工程化行为。

它可以配置:

  • 部署基础路径。
  • 构建输出目录。
  • 静态资源目录。
  • 开发服务器端口和代理。
  • CSS loader 选项。
  • Webpack 别名。
  • Webpack 插件。
  • 多页面应用。
  • source map。
  • 第三方插件选项。

1.1 它在哪些项目中常见 ​

常见于:

  • Vue2 + Vue CLI 项目。
  • Vue3 + Vue CLI 项目。
  • 早期企业后台项目。
  • 基于 Vue CLI 改造的自研脚手架。

不常见于:

  • Vite 项目。
  • Nuxt 项目。
  • 自行搭建的纯 Webpack 项目。

1.2 vue.config.js 是怎么被加载的(内部机制) ​

理解加载机制,能避免很多「改了不生效」的困惑。

  • vue-cli-service 启动时,会读取项目根目录的 vue.config.js(通过 Node 的 require 加载,所以默认是 CommonJS 写法)。
  • 这个文件里的「顶层字段」(publicPath、outputDir、devServer、css 等)会被 Vue CLI 翻译成对应的底层 Webpack 配置,而不是直接拿给你一个 Webpack 配置文件。
  • configureWebpack 里的内容会通过 webpack-merge 合并进最终 Webpack 配置;chainWebpack 则用 webpack-chain 链式 API 精细修改已有的 rule/plugin。
  • 整个配置在 serve/build 启动时一次性加载,修改 vue.config.js 后必须重启命令才会生效(不像 .vue 文件有热更新)。

想确认你的配置最终变成了什么 Webpack 配置,随时可以:

bash
vue-cli-service inspect

⚠️ Vue CLI 已进入维护模式,官方不再开发新特性,只修关键 bug。新项目优先考虑 Vite;但对存量 Vue CLI 项目,理解这套机制仍然必要。


2. 它和 vite.config.ts 有什么区别 ​

vue.config.js 属于 Vue CLI。

vite.config.ts 属于 Vite。

两者不要混用。

项目类型配置文件底层构建工具常见命令
Vue2 + Vue CLIvue.config.jsWebpackvue-cli-service serve
Vue3 + Vue CLIvue.config.jsWebpackvue-cli-service serve
Vue3 + Vitevite.config.tsVite + Rollupvite
Vue2 + Vitevite.config.tsVite + Rollupvite

判断方式:

看 package.json。

Vue CLI 项目通常有:

json
{
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build"
  }
}

Vite 项目通常有:

json
{
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  }
}

3. 最小配置写法 ​

vue.config.js:

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

Vue CLI 默认使用 CommonJS 写法,因为这个文件运行在 Node.js 环境。

也可以导出函数或根据环境变量动态返回配置,但初学阶段先掌握对象写法。

3.1 常见完整示例 ​

js
const path = require('node:path')

function resolve(dir) {
  return path.join(__dirname, dir)
}

module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? '/admin/' : '/',
  outputDir: 'dist',
  assetsDir: 'static',
  productionSourceMap: false,

  devServer: {
    host: '0.0.0.0',
    port: 8080,
    open: true,
    proxy: {
      '/api': {
        target: process.env.VUE_APP_PROXY_TARGET,
        changeOrigin: true,
        pathRewrite: {
          '^/api': '',
        },
      },
    },
  },

  configureWebpack: {
    resolve: {
      alias: {
        '@': resolve('src'),
      },
    },
  },

  css: {
    loaderOptions: {
      scss: {
        additionalData: `@use "@/styles/variables.scss" as *;`,
      },
    },
  },
}

4. 常用基础配置 ​

4.1 publicPath ​

部署基础路径。

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

如果项目部署到域名根路径:

text
https://example.com/

使用:

js
publicPath: '/'

如果项目部署到子路径:

text
https://example.com/admin/

使用:

js
publicPath: '/admin/'

它会影响构建后 JS、CSS、图片等资源的引用路径。

4.2 outputDir ​

构建输出目录。

js
module.exports = {
  outputDir: 'dist',
}

默认是 dist。

4.3 assetsDir ​

放置构建后静态资源的目录。

js
module.exports = {
  assetsDir: 'static',
}

构建后可能类似:

text
dist/
├── index.html
└── static/
    ├── js/
    ├── css/
    └── img/

4.4 indexPath ​

指定生成的 index.html 路径。

js
module.exports = {
  indexPath: 'index.html',
}

通常不需要改。多页面或后端模板集成时可能会用到。

4.5 filenameHashing ​

是否在生成的静态资源文件名中包含 hash。

js
module.exports = {
  filenameHashing: true,
}

生产环境推荐保持开启,利于浏览器缓存。

4.6 productionSourceMap ​

生产构建是否生成 source map。

js
module.exports = {
  productionSourceMap: false,
}

常见选择:

  • 内部测试环境可以打开。
  • 线上生产环境通常关闭,或上传到错误监控平台但不公开。

4.7 lintOnSave ​

保存时是否触发 lint。

js
module.exports = {
  lintOnSave: 'default',
}

也可以:

js
lintOnSave: false

不建议长期关闭 lint。更好的做法是修正规则或代码。

4.8 transpileDependencies ​

指定需要被 Babel 转译的依赖。

js
module.exports = {
  transpileDependencies: ['some-esm-package'],
}

常见场景:

  • 某些第三方包发布了较新的语法。
  • 老浏览器无法直接运行。
  • 需要让 Babel 处理该依赖。

4.9 parallel ​

是否用 thread-loader 开启 Babel/TS 的多线程转译,默认在 CPU 核心数 > 1 时开启。

js
module.exports = {
  parallel: require('node:os').cpus().length > 1,
}

适用场景:

  • 项目较大、转译耗时明显时保持开启。
  • CI 或低配虚拟机里,多线程反而可能拖慢构建,可以显式关掉:parallel: false。

4.10 runtimeCompiler ​

是否需要把 Vue 的「运行时 + 模板编译器」完整打包进来,默认 false。

js
module.exports = {
  runtimeCompiler: true,
}

两种构建形态:

  • runtime-only(默认,体积更小):.vue 文件在构建阶段就被编译成 render 函数,运行时不需要编译器。
  • runtime + compiler(runtimeCompiler: true):允许在组件里直接写 template: '<div>...</div>' 字符串,但会增大包体积。

💡 除非你确实要在运行时动态编译模板(比如从接口返回模板字符串),否则保持默认 false 即可,别为了「兼容」盲目开启。


5. 开发服务器 devServer 配置 ​

devServer 底层对应 webpack-dev-server。

5.1 端口、host、自动打开 ​

js
module.exports = {
  devServer: {
    host: '0.0.0.0',
    port: 8080,
    open: true,
  },
}

含义:

  • host: '0.0.0.0':允许局域网访问。
  • port: 8080:固定端口。
  • open: true:启动后自动打开浏览器。

5.2 配置代理 ​

开发环境常用代理解决跨域。

js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: {
          '^/api': '',
        },
      },
    },
  },
}

业务代码:

js
axios.get('/api/users')

实际流程:

text
浏览器 -> Vue CLI dev server -> 后端 http://localhost:3000/users

5.3 使用环境变量配置代理地址 ​

.env.development:

env
VUE_APP_PROXY_TARGET=http://localhost:3000

vue.config.js:

js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: process.env.VUE_APP_PROXY_TARGET,
        changeOrigin: true,
      },
    },
  },
}

注意:修改 .env 或 vue.config.js 后,需要重启开发服务器。

5.4 history 路由刷新 ​

Vue Router 使用 history 模式时,本地刷新子路由可能需要 fallback。

Vue CLI 通常已经做了相应处理。如果你定制 devServer 后出现刷新 404,可以检查 webpack-dev-server 的 history fallback 相关配置。

生产环境也要在 Nginx 或服务器上配置:

nginx
location / {
  try_files $uri $uri/ /index.html;
}

5.5 devServer 其他常用选项 ​

devServer 直接透传 webpack-dev-server 的配置,以下是除端口、代理外的高频项:

js
module.exports = {
  devServer: {
    https: true,                                        // 本地 HTTPS
    allowedHosts: ['localhost', '.example.com'],        // 白名单,防 DNS rebinding 攻击
    headers: {                                          // 自定义响应头
      'X-Custom-Header': 'hello',
    },
    client: {
      overlay: { errors: true, warnings: false },       // 编译错误覆盖层
    },
    historyApiFallback: true,                           // history 路由回退(默认已开)
  },
}
  • https:需要本地调试 HTTPS 相关能力(如 PWA、跨域 cookie)时开启。
  • allowedHosts:默认只允许本机访问;用局域网 IP 或自定义域名访问时报 Invalid Host header,就是这里要放行。
  • client.overlay:编译报错时全屏遮罩提示,团队里有人嫌烦可以只关 warnings。
  • historyApiFallback:Vue Router history 模式下刷新子路由 404 的回退,Vue CLI 默认已经处理,一般不用改。

6. CSS 相关配置 ​

6.1 css.extract ​

是否提取 CSS 到独立文件。

js
module.exports = {
  css: {
    extract: process.env.NODE_ENV === 'production',
  },
}

生产环境通常提取,开发环境通常注入 style 便于热更新。

6.2 css.sourceMap ​

是否为 CSS 生成 source map。

js
module.exports = {
  css: {
    sourceMap: false,
  },
}

调试样式时可以打开,但会增加构建成本。

6.3 css.loaderOptions ​

给 CSS 相关 loader 传选项。

Sass 全局变量:

js
module.exports = {
  css: {
    loaderOptions: {
      scss: {
        additionalData: `@use "@/styles/variables.scss" as *;`,
      },
    },
  },
}

Less 全局变量:

js
module.exports = {
  css: {
    loaderOptions: {
      less: {
        lessOptions: {
          modifyVars: {
            'primary-color': '#42b883',
          },
          javascriptEnabled: true,
        },
      },
    },
  },
}

6.4 不要滥用全局注入 ​

适合全局注入:

  • Sass 变量。
  • mixin。
  • function。

不适合全局注入:

  • 大量真实 CSS。
  • reset 样式。
  • 组件样式。

真实 CSS 应该通过入口文件引入:

js
import '@/styles/index.scss'

7. configureWebpack 与 chainWebpack ​

Vue CLI 给了两种扩展 Webpack 的方式。

7.1 configureWebpack ​

适合简单合并配置。

对象写法:

js
module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        '@': require('node:path').resolve(__dirname, 'src'),
      },
    },
  },
}

函数写法:

js
module.exports = {
  configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
      config.devtool = false
    }
  },
}

7.2 chainWebpack ​

适合精细修改内部 Webpack 配置。

它使用 webpack-chain API。

js
module.exports = {
  chainWebpack: config => {
    config.resolve.alias.set('@', require('node:path').resolve(__dirname, 'src'))
  },
}

7.3 什么时候用哪个 ​

优先级建议:

  1. 简单新增配置:用 configureWebpack。
  2. 需要修改已有 loader/plugin:用 chainWebpack。
  3. 能用 Vue CLI 顶层配置解决,就不要改底层 Webpack。

7.4 查看最终 Webpack 配置 ​

可以使用:

bash
vue-cli-service inspect

输出到文件:

bash
vue-cli-service inspect > webpack.config.output.js

在改 chainWebpack 前,建议先看最终配置里对应 rule/plugin 的名字。

7.5 configureWebpack 的合并语义(内部机制) ​

configureWebpack 的「对象」和「函数」两种写法,合并行为不一样:

  • 对象写法:通过 webpack-merge 把对象合并进 Vue CLI 生成好的配置,你写的同名字段会覆盖默认值。
  • 函数写法:接收 Vue CLI 已经生成好的 config,你在函数里直接改(或返回一个新对象让 Vue CLI 再 merge)。
js
module.exports = {
  configureWebpack: config => {
    // 此时 config 已经是完整的 Webpack 配置
    if (process.env.NODE_ENV === 'production') {
      config.devtool = false
    }
    return config // 返回 undefined 表示「不改」;返回对象则 merge
  },
}

为什么需要两种:

  • 对象适合「无条件新增/覆盖」。
  • 函数适合「按环境、按条件」改配置,因为你能拿到最终 config 和 process.env.NODE_ENV。

⚠️ 注意 merge 的粒度:普通对象字段是「覆盖」,但数组(如 plugins)按索引合并,删减数组项容易踩坑。要精确增删 plugin/loader,用 chainWebpack 的 .delete() / .use() 更可靠。


8. 路径别名配置 ​

常见别名:

js
const path = require('node:path')

function resolve(dir) {
  return path.join(__dirname, dir)
}

module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        '@': resolve('src'),
        '@components': resolve('src/components'),
        '@utils': resolve('src/utils'),
      },
    },
  },
}

使用:

js
import UserCard from '@components/UserCard.vue'
import { formatDate } from '@utils/date'

8.1 TypeScript 项目要同步 tsconfig ​

tsconfig.json:

json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

否则项目可能能运行,但编辑器和类型检查报错。


9. 多页面 pages 配置 ​

Vue CLI 默认是单页面应用。如果要做多页面,可以使用 pages。

js
module.exports = {
  pages: {
    index: {
      entry: 'src/pages/index/main.js',
      template: 'public/index.html',
      filename: 'index.html',
      title: '首页',
    },
    admin: {
      entry: 'src/pages/admin/main.js',
      template: 'public/admin.html',
      filename: 'admin.html',
      title: '后台',
    },
  },
}

目录结构:

text
src/
└── pages/
    ├── index/
    │   └── main.js
    └── admin/
        └── main.js

多页面适合:

  • 后台和前台完全分离。
  • 多个独立入口。
  • 老系统逐步迁移。

不适合:

  • 普通 Vue Router 单页面项目。

10. 环境变量在 vue.config.js 中的使用 ​

Vue CLI 会加载 .env 文件。

在客户端代码中,只有这些变量会被嵌入:

  • NODE_ENV。
  • BASE_URL。
  • 以 VUE_APP_ 开头的变量。

在 vue.config.js 中,可以读取:

js
process.env.NODE_ENV
process.env.VUE_APP_API_BASE_URL
process.env.VUE_APP_PROXY_TARGET

示例:

js
module.exports = {
  publicPath: process.env.VUE_APP_PUBLIC_PATH || '/',
  devServer: {
    proxy: {
      '/api': {
        target: process.env.VUE_APP_PROXY_TARGET,
        changeOrigin: true,
      },
    },
  },
}

10.1 不要在前端 env 中放秘密 ​

下面这种变量不能放进前端 .env:

env
VUE_APP_DB_PASSWORD=123456
VUE_APP_SECRET_KEY=abcdef

原因:

  • 前端构建产物会被用户下载。
  • 以 VUE_APP_ 开头的变量会被嵌入客户端代码。
  • 用户可以从源码或构建产物中找到它们。

真正的密钥应该放在服务端。


11. 常见生产环境配置 ​

11.1 部署到子路径 ​

js
module.exports = {
  publicPath: process.env.NODE_ENV === 'production' ? '/admin/' : '/',
}

如果 Vue Router 使用 history:

js
const router = new VueRouter({
  mode: 'history',
  base: '/admin/',
  routes,
})

11.2 关闭生产 source map ​

js
module.exports = {
  productionSourceMap: false,
}

11.3 配置 splitChunks ​

js
module.exports = {
  configureWebpack: {
    optimization: {
      splitChunks: {
        chunks: 'all',
      },
    },
  },
}

不要上来就写复杂拆包规则。先用 bundle analyzer 看结果,再决定是否定制。

11.4 Bundle Analyzer ​

安装:

bash
npm install webpack-bundle-analyzer -D

配置:

js
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')

module.exports = {
  configureWebpack: config => {
    if (process.env.ANALYZE) {
      config.plugins.push(new BundleAnalyzerPlugin())
    }
  },
}

运行:

bash
ANALYZE=true npm run build

Windows PowerShell:

powershell
$env:ANALYZE='true'; npm run build

12. 常见实战场景 ​

12.1 开发环境代理多个后端服务 ​

js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
      },
      '/upload': {
        target: 'http://localhost:4000',
        changeOrigin: true,
      },
    },
  },
}

12.2 给项目加版本号 ​

js
const webpack = require('webpack')
const pkg = require('./package.json')

module.exports = {
  configureWebpack: {
    plugins: [
      new webpack.DefinePlugin({
        __APP_VERSION__: JSON.stringify(pkg.version),
      }),
    ],
  },
}

业务代码:

js
console.log(__APP_VERSION__)

12.3 移除 prefetch ​

有些项目会移除默认 prefetch,避免浏览器提前加载过多异步 chunk。

js
module.exports = {
  chainWebpack: config => {
    config.plugins.delete('prefetch')
  },
}

是否移除要看项目实际加载表现,不要盲目。

12.4 SVG 图标特殊处理 ​

很多项目会把 src/icons 下的 SVG 当成 symbol sprite,把其他 SVG 当普通图片。

示例思路:

js
const path = require('node:path')

function resolve(dir) {
  return path.join(__dirname, dir)
}

module.exports = {
  chainWebpack: config => {
    config.module.rule('svg').exclude.add(resolve('src/icons'))

    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      })
  },
}

需要安装:

bash
npm install svg-sprite-loader -D

13. 初学者常见坑 ​

13.1 在 Vite 项目里写 vue.config.js ​

Vite 不读取 vue.config.js。

Vite 项目应该写:

text
vite.config.ts

13.2 修改 vue.config.js 后不重启服务 ​

配置文件变化通常需要重启:

bash
npm run serve

13.3 publicPath 和路由 base 不一致 ​

部署到 /admin/ 时,至少要检查:

  • publicPath。
  • Vue Router base。
  • Nginx fallback。

13.4 只配置 Webpack alias,不配 tsconfig ​

TypeScript 项目要两边都配:

  • vue.config.js 给 Webpack。
  • tsconfig.json 给 TypeScript 和编辑器。

13.5 把秘密写进 VUE_APP_ ​

VUE_APP_ 变量会进入客户端构建产物。不要放密码、token、私钥。

13.6 滥用 chainWebpack ​

chainWebpack 能力很强,但也更难维护。

优先顺序:

  1. Vue CLI 顶层配置。
  2. configureWebpack。
  3. chainWebpack。

14. 推荐学习顺序 ​

第一阶段:认识配置文件 ​

目标:

  • 知道 vue.config.js 放在哪里。
  • 知道它只属于 Vue CLI。
  • 会配置 publicPath、outputDir。

第二阶段:开发环境 ​

目标:

  • 会配置端口。
  • 会配置代理。
  • 会用 .env.development 管理代理地址。

第三阶段:资源与样式 ​

目标:

  • 会配置 Sass 全局变量。
  • 会理解 CSS 是否提取。
  • 会处理静态资源目录。

第四阶段:Webpack 扩展 ​

目标:

  • 会用 configureWebpack 加别名。
  • 会用 chainWebpack 修改已有规则。
  • 会用 vue-cli-service inspect 查看最终配置。

第五阶段:生产部署 ​

目标:

  • 会配置子路径部署。
  • 会关闭生产 source map。
  • 会分析构建体积。
  • 会处理 history 路由刷新。

15. 学习资源 ​

建议:学习 vue.config.js 时,不要只背配置项。你应该每次改完后运行:

bash
vue-cli-service inspect

看最终 Webpack 配置发生了什么变化。这样才能真正理解 Vue CLI 帮你封装了什么。

基于 VitePress 构建的个人学习文档知识库