这里先简单对vue.config.js这个文件做个介绍

背景知识和情况介绍:
我们最后是把所有的vue-cli文件打包成一个index.html文件
这个文件里的内容,是我们不好编辑的,要提前配置好
因为这个东西,最后就是部署到nginx文件夹包下,
浏览器访问这个服务器端口,nginx监听这个端口,返回给浏览器这个.html文件
然后在渲染对应的vue文件,在vue实例化之前,访问服务器的url接口地址,拿到数据渲染页面展现页面。

那对于把vue-cli的源文件转化为html文件
这个webpack需要配置什么内容。这边介绍一下:
vue.config.js

├── 工程路径领域
│ ├── publicPath
│ ├── outputDir
│ └── assetsDir

├── 开发服务器领域
│ └── devServer

├── API代理领域
│ └── proxy

├── webpack构建领域
│ ├── configureWebpack
│ └── chainWebpack

├── 插件领域
│ └── preload/prefetch

├── SVG图标领域
│ └── svg-sprite-loader

├── 打包优化领域
│ ├── splitChunks
│ └── runtimeChunk

├── 安全性能领域
│ └── productionSourceMap

└── 代码规范领域
└── ESLint

我们这里以一个demo例子介绍下:

'use strict'
const path = require('path')
const defaultSettings = require('./src/settings.js')

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

const name = defaultSettings.title || '物业管理平台' // 标题

const port = process.env.port || process.env.npm_config_port || 80 // 端口

// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分,具体配置参考文档
module.exports = {
  // 部署生产环境和开发环境下的URL。
  // 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
  publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
  // 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
  outputDir: 'dist',
  // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
  assetsDir: 'static',
  // 是否开启eslint保存检测,有效值:ture | false | 'error'
  lintOnSave: process.env.NODE_ENV === 'development',
  // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
  productionSourceMap: false,
  // webpack-dev-server 相关配置
  devServer: {
    host: '0.0.0.0',
    port: port,
    open: true,
    proxy: {
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        target: `http://localhost:8080`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    },
    disableHostCheck: true
  },
  configureWebpack: {
    name: name,
    resolve: {
      alias: {
        '@': resolve('src')
      }
    }
  },
  chainWebpack(config) {
    config.plugins.delete('preload') // TODO: need test
    config.plugins.delete('prefetch') // TODO: need test

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

    config
      .when(process.env.NODE_ENV !== 'development',
        config => {
          config
            .plugin('ScriptExtHtmlWebpackPlugin')
            .after('html')
            .use('script-ext-html-webpack-plugin', [{
            // `runtime` must same as runtimeChunk name. default is `runtime`
              inline: /runtime\..*\.js$/
            }])
            .end()
          config
            .optimization.splitChunks({
              chunks: 'all',
              cacheGroups: {
                libs: {
                  name: 'chunk-libs',
                  test: /[\\/]node_modules[\\/]/,
                  priority: 10,
                  chunks: 'initial' // only package third parties that are initially dependent
                },
                elementUI: {
                  name: 'chunk-elementUI', // split elementUI into a single package
                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
                },
                commons: {
                  name: 'chunk-commons',
                  test: resolve('src/components'), // can customize your rules
                  minChunks: 3, //  minimum common number
                  priority: 5,
                  reuseExistingChunk: true
                }
              }
            })
          config.optimization.runtimeChunk('single'),
          {
             from: path.resolve(__dirname, './public/robots.txt'),//防爬虫文件
             to:'./',//到根目录下
          }
        }
      )
  }
}

vue.config.js 配置详解及领域分析


一、核心认知:vue.config.js 配置的五大领域

┌─────────────────────────────────────────────────────────────────────┐
│                    vue.config.js 五大配置领域                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  领域1:部署路径配置          → 项目部署在哪里                         │
│  领域2:开发服务器配置        → 本地开发体验                           │
│  领域3:webpack 基础配置      → 别名、全局变量                         │
│  领域4:webpack 优化配置      → 打包体积、加载性能                      │
│  领域5:静态资源处理          → SVG、图片、字体等                       │
│                                                                       │
└─────────────────────────────────────────────────────────────────────┘

二、这个配置完整解析

领域1:部署路径配置

// 部署路径配置
publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
// 生产环境和开发环境都用根路径部署

outputDir: 'dist',
// 打包输出目录名

assetsDir: 'static',
// 静态资源(js/css/img)放在 dist/static/ 下

productionSourceMap: false,
// 生产环境不生成 .map 文件(减少打包体积)

为什么需要?

配置 解决的问题
publicPath 部署到子路径时(如 /admin/),资源路径错误导致 404
outputDir 默认 dist,改其他地方(如 build
assetsDir 想分开放置静态资源,便于 nginx 配置缓存规则
productionSourceMap 默认生成 map 文件很大(几 MB),生产环境不需要,关掉加速构建

领域2:开发服务器配置

devServer: {
  host: '0.0.0.0',      // 允许局域网其他设备访问(手机测试)
  port: port,           // 端口(从环境变量读取,默认80)
  open: true,           // 启动后自动打开浏览器
  proxy: {              // 代理配置(解决跨域)
    [process.env.VUE_APP_BASE_API]: {
      target: `http://localhost:8080`,  // 后端地址
      changeOrigin: true,                // 修改请求头中的 origin
      pathRewrite: {
        ['^' + process.env.VUE_APP_BASE_API]: ''  // 去掉前缀
      }
    }
  },
  disableHostCheck: true   // 允许通过 IP 访问(开发环境常用)
}

代理工作原理:

前端请求:http://localhost:80/api/user
    ↓ 代理匹配到 /api
    ↓ 转发到 target: http://localhost:8080
    ↓ pathRewrite: 去掉 /api
最终请求:http://localhost:8080/user

浏览器看到的是同源请求(都是 localhost:80),没有跨域问题

为什么需要?

配置 解决的问题
host: '0.0.0.0' 手机或同事电脑访问你的开发服务器
proxy 前端端口 80,后端端口 8080,跨域被浏览器拦截
pathRewrite 后端接口路径可能没有 /api 前缀,需要去掉
disableHostCheck 允许通过 IP 直接访问(部署在服务器上时)

领域3:webpack 基础配置

configureWebpack: {
  name: name,           // 从 settings.js 读取的标题
  resolve: {
    alias: {            // 路径别名
      '@': resolve('src')   // @ 代表 src 目录
    }
  }
}

别名的作用:

// 没有别名
import utils from '../../../../utils/index.js'

// 有别名(@ 代表 src)
import utils from '@/utils/index.js'

为什么需要?

  • 避免写麻烦的相对路径 ../../../
  • 移动文件时不需要改 import 路径

领域4:webpack 优化配置(最复杂)

4.1 删除预加载(preload/prefetch)
config.plugins.delete('preload')
config.plugins.delete('prefetch')

preload/prefetch 是什么?

<!-- preload:当前页面马上需要的资源,提前加载 -->
<link rel="preload" href="chunk-vendors.js" as="script">

<!-- prefetch:未来可能需要的资源,空闲时加载 -->
<link rel="prefetch" href="other-page.js">

为什么删除?

  • 项目页面太多时,prefetch 会静默加载所有页面的资源
  • 造成:首次访问时网络请求激增,影响性能
4.2 代码分割(splitChunks)
config.optimization.splitChunks({
  chunks: 'all',
  cacheGroups: {
    libs: {
      name: 'chunk-libs',
      test: /[\\/]node_modules[\\/]/,  // 第三方库
      priority: 10,
      chunks: 'initial'
    },
    elementUI: {
      name: 'chunk-elementUI',          // element-ui 单独打包
      priority: 20,                     // 优先匹配
      test: /[\\/]node_modules[\\/]_?element-ui(.*)/
    },
    commons: {
      name: 'chunk-commons',
      test: resolve('src/components'),  // 公共组件
      minChunks: 3,                     // 至少被3个地方使用
      priority: 5,
      reuseExistingChunk: true
    }
  }
})

代码分割效果:

没有分割:
  app.js (2MB)  → 用户下载 2MB,一次加载全部

有分割:
  chunk-libs.js (800KB)    → 第三方库,很少变,长期缓存
  chunk-elementUI.js (300KB) → UI 库单独
  chunk-commons.js (200KB)   → 公共组件
  app.js (100KB)             → 业务代码
  用户首次下载 1.4MB,但第二次访问只需下载变化的 app.js

为什么需要?

  • 加快首次加载(并行下载多个小文件)
  • 利用浏览器缓存(第三方库很少变,可以长期缓存)
  • 按需加载(用户访问哪个页面,才加载那个页面的代码)
4.3 内联 runtime chunk
config.plugin('ScriptExtHtmlWebpackPlugin')
  .after('html')
  .use('script-ext-html-webpack-plugin', [{
    inline: /runtime\..*\.js$/   // 把 runtime 文件内联到 HTML
  }])

为什么要内联 runtime?

runtime.js 是非常小(几KB)但很重要的文件,管理 webpack 模块加载
如果单独文件:多一次 HTTP 请求
内联到 HTML:减少一次请求,加快首屏加载
4.4 复制静态文件
{
  from: path.resolve(__dirname, './public/robots.txt'),  // 源文件
  to: './'                                                // 目标目录
}

作用:public/robots.txt 复制到 dist/ 根目录

robots.txt 作用:告诉搜索引擎爬虫哪些页面能抓取
User-agent: *
Disallow: /admin/

领域5:静态资源处理(SVG)

// set svg-sprite-loader
config.module
  .rule('svg')
  .exclude.add(resolve('src/assets/icons'))
  .end()
config.module
  .rule('icons')
  .test(/\.svg$/)
  .include.add(resolve('src/assets/icons'))
  .end()
  .use('svg-sprite-loader')
  .loader('svg-sprite-loader')
  .options({
    symbolId: 'icon-[name]'   // 生成的 symbol id
  })

SVG 雪碧图效果:

传统方式:
  每个 SVG 是独立的图片 → 5个图标 = 5次 HTTP 请求

SVG Sprite:
  所有 SVG 打包成 1 个文件
  使用时通过 <use href="#icon-home"></use> 引用
  1 次请求即可

使用方式:

<template>
  <!-- 使用 SVG 图标 -->
  <svg>
    <use href="#icon-home" />
  </svg>
</template>

<script>
// 直接 import SVG 文件
import '@/assets/icons/home.svg'
</script>

三、这些配置解决的实际问题总结

领域 配置内容 解决什么问题
部署路径 publicPath、outputDir、assetsDir 部署位置变化时资源 404
开发体验 devServer、proxy 跨域、局域网访问、热更新
代码规范 lintOnSave 保存时自动检查代码风格
构建速度 productionSourceMap 生产构建太慢、打包太大
打包体积 splitChunks、preload/prefetch 首次加载太慢、网络请求太多
长期缓存 chunk 分割 第三方库每次都要重新下载
首屏性能 runtime 内联 多一次 HTTP 请求
SEO robots.txt 搜索引擎抓取规则

四、一般需要配置的核心领域

大多数 Vue CLI 项目至少需要配置:

// 最小必备配置
module.exports = {
  // 1. 部署路径(部署到非根目录时必须)
  publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/',
  
  // 2. 开发服务器(跨域必须)
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true
      }
    }
  },
  
  // 3. 路径别名(提升开发体验)
  configureWebpack: {
    resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src')
      }
    }
  }
}

五、配置领域对照表

┌─────────────────────────────────────────────────────────────────┐
│ 领域           │ 何时需要配置                                    │
├─────────────────────────────────────────────────────────────────┤
│ publicPath     │ 部署到子路径(如 CDN、二级目录)                 │
│ devServer.proxy│ 前后端分离,本地开发跨域                         │
│ alias          │ 几乎都需要,简化 import 路径                     │
│ splitChunks    │ 项目变大后,需要优化加载速度                      │
│ productionSourceMap│ 生产构建太慢或打包太大                       │
│ lintOnSave     │ 团队需要统一代码风格                              │
│ SVG Sprite     │ 大量使用 SVG 图标                                │
│ robots.txt     │ 需要 SEO 优化                                    │
└─────────────────────────────────────────────────────────────────┘

六、一句话总结

vue.config.js 是 Vue CLI 项目的【总控制台】,核心配置五大领域:

1. 部署路径配置 → 资源路径正确
2. 开发服务器配置 → 本地调试顺畅
3. Webpack 基础配置 → 开发体验提升
4. Webpack 优化配置 → 打包小、加载快
5. 静态资源处理 → SVG、图片优化


3. .env.development / .env.production / .env.staging

文件作用

环境变量配置文件,在构建时注入到代码中

文件内容示例
# .env.development(开发环境)
NODE_ENV=development
VUE_APP_API_BASE_URL=http://localhost:3000/api
VUE_APP_TITLE=【开发环境】我的项目

# .env.production(生产环境)
NODE_ENV=production
VUE_APP_API_BASE_URL=https://api.example.com/api
VUE_APP_TITLE=我的项目

# .env.staging(预发布环境)
NODE_ENV=production
VUE_APP_API_BASE_URL=https://staging-api.example.com/api
VUE_APP_TITLE=【测试环境】我的项目
在代码中使用
// src/api/request.js
const baseURL = process.env.VUE_APP_API_BASE_URL

// 开发环境下:http://localhost:3000/api
// 生产环境下:https://api.example.com/api
// 构建时,webpack 会把这些变量直接替换成字符串
构建时的替换结果
// 你写的代码
const url = process.env.VUE_APP_API_BASE_URL

// 生产环境构建后(dist/js/app.xxx.js 中)
const url = "https://api.example.com/api"
为什么需要它?
开发环境:调用 localhost 后端
测试环境:调用测试服务器
生产环境:调用正式服务器

不可能每次打包前手动改代码 → 用环境变量解决
构建时指定使用哪个环境
# 默认使用 .env.development(开发)
npm run serve

# 使用 .env.production(生产)
npm run build

# 使用 .env.staging(预发布)
npm run build --mode staging

# package.json 中配置
"scripts": {
  "build:prod": "vue-cli-service build --mode production",
  "build:staging": "vue-cli-service build --mode staging"
}

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐