解决.env.production 写死 IP 的问题:Vue + config.json 运行时加载方案

背景:前端常用 .env.production 在构建时写死 API 地址
场景:运维部署时经常不知道目标主机 IP/域名
问题:每次 IP 变动都要重新编译 → 增加运维成本
引出需求:只修改 IP 就能完成部署,不需要重新打包

目录

  • 一、解决方案思路
  • 二、实现步骤
  • 三、打包部署
  • 四、知识补充

一、解决方案思路

1、前端层面

  • 把动态配置从 .env.production 抽离,放到 public/config.json
  • 在应用启动时 fetch 该文件 → 写入 window.__APP _ CONFIG __
  • 业务代码改用 window.__APP _ CONFIG __ 或封装好的 axios 实例获取 baseURL

2、后端层面(Spring Boot)

  • Spring Security 默认拦截所有请求,导致 /config.json 也被保护 → 返回 401
  • 在 security 配置中将 /config.json 加入 permitAll 白名单,确保前端静态资源匿名可访问

二、实现步骤

  1. 新建 public/config.json(存放运行时配置)
{"ENV": "production","VUE_APP_BASE_API": "","VUE_APP_GPU_BASE_URL": "http://10.143.135.91:9001","VUE_APP_AUTO_LOGIN_USER": "admin","VUE_APP_AUTO_LOGIN_PWD": "21232f297a57a5a743894a0e4a801fc3"
}

在这里插入图片描述

  1. 修改 main.js → 应用启动前加载 config.json

在 src/bootstrapConfig.ts 中封装 loadRuntimeConfig
✅ Vue 3(Vite 或 Vue CLI)
src/bootstrapConfig.ts(JS 项目就用 .js)

export type AppConfig = {ENV: stringVUE_APP_BASE_API: stringVUE_APP_GPU_BASE_URL: stringVUE_APP_AUTO_LOGIN_USER: stringVUE_APP_AUTO_LOGIN_PWD: string
}export async function loadRuntimeConfig(): Promise<AppConfig> {const res = await fetch('./config.json', { cache: 'no-store' })if (!res.ok) throw new Error(`load config.json failed: ${res.status}`)const cfg = (await res.json()) as AppConfig;(window as any).__APP_CONFIG__ = cfgreturn cfg
}
export function getConfig(): AppConfig {return (window as any).__APP_CONFIG__ as AppConfig
}

src/main.ts

import { createApp } from 'vue'
import App from './App.vue'
import { loadRuntimeConfig } from './bootstrapConfig'async function bootstrap() {await loadRuntimeConfig()createApp(App).mount('#app')
}
bootstrap()

✅ Vue 2(Vue CLI)

src/bootstrapConfig.js

export async function loadRuntimeConfig() {const res = await fetch('./config.json', { cache: 'no-store' })if (!res.ok) throw new Error('load config.json failed: ' + res.status)window.__APP_CONFIG__ = await res.json()
}
export function getConfig() { return window.__APP_CONFIG__ }

src/main.js

import Vue from 'vue'
import App from './App.vue'
import { loadRuntimeConfig } from './bootstrapConfig'async function bootstrap() {await loadRuntimeConfig()new Vue({ render: h => h(App) }).$mount('#app')
}
bootstrap()
  1. axios 封装:统一读取 ‘__APP_CONFIG __’ 作为 baseURL

src/api/http.ts

import axios from 'axios'const api = axios.create({baseURL: (window as any).__APP_CONFIG__.VUE_APP_BASE_API
})export default api

业务里:

import api from '@/api/http'
// api.get('/xxx')

另一种方式
使用${window.__APP_CONFIG __.VUE_APP_GPU_BASE_URL}
在这里插入图片描述

  1. Spring Security 配置修改:放行 /config.json
public class WebSecurityConfig extends WebSecurityConfigurerAdapter   {........@Overrideprotected void configure(HttpSecurity http) throws Exception {List<String> defaultExcludes = new ArrayList<>();defaultExcludes.add("/");defaultExcludes.add("/#/**");defaultExcludes.add("/static/**");defaultExcludes.add("/swagger-ui.html");defaultExcludes.add("/swagger-ui/**");defaultExcludes.add("/swagger-resources/**");defaultExcludes.add("/doc.html");defaultExcludes.add("/doc.html#/**");defaultExcludes.add("/v3/api-docs/**");defaultExcludes.add("/index.html");defaultExcludes.add("/webjars/**");defaultExcludes.add("/js/**");defaultExcludes.add("/api/device/query/snap/**");defaultExcludes.add("/record_proxy/*/**");defaultExcludes.add("/api/emit");defaultExcludes.add("/favicon.ico");defaultExcludes.add("/api/user/login");defaultExcludes.add("/index/hook/**");defaultExcludes.add("/api/device/query/snap/**");defaultExcludes.add("/index/hook/abl/**");// 👇 新增这一行,允许匿名访问 config.jsondefaultExcludes.add("/config.json");

部署到Spring Boot → 验证只改 config.json 就能适配 IP
在这里插入图片描述
注意:改造后的文件结构

  1. .env.production (最小化)
# just a flag
NODE_ENV=production
VUE_APP_BUILD_VERSION=1.0.0

⚠️ 注意:
VUE_APP_BASE_API、GPU_BASE_URL、账号密码这些 删掉,因为它们要 runtime 配置,不要在这里写。
可以额外放一些编译时常量(例如版本号、构建时间)。

三、打包部署

方案一
在yml文件下添加配置规则,能够读取容器内的文件

spring:web:resources:static-locations: file:/app/static/,classpath:/static/

方案二
在Dockerfile配置文件

ENTRYPOINT ["java", \"-Dspring.web.resources.static-locations=file:/app/static/,classpath:/static/", \"-Dspring.resources.static-locations=file:/app/static/,classpath:/static/", \"-jar","wvp.jar", \"--spring.config.location=/app/config/"]

在这里插入图片描述

👉 -Dspring.resources.static-locations 是 Spring Boot 2.3 及之前的老配置项,
👉 -Dspring.web.resources.static-locations 是 Spring Boot 2.4 及之后的新配置项,作用完全相同,只是命名空间不同。

意思是:

  1. 覆盖默认规则(自己指定顺序)。
  2. 让 Spring Boot 在两个地方找静态资源:
    file:/app/static/ → 容器里的目录(来自宿主机挂载的 /app/static)。
    classpath:/static/ → 打包在 jar 里的 resources/static/。

👉 关键点是:顺序有优先级,Spring Boot 会先从 file:/app/static/ 找,如果找不到,再去 classpath:/static/。

挂载文件(先copy一份到宿主机 然后挂载到容器内部/app/static/)
在这里插入图片描述
然后就会首先读取容器里面的IP
在这里插入图片描述
修改之后重启容器

docker compose up -d --force-recreate

四、知识补充

Spring Boot 静态资源路径设置
如果你不写任何配置,Spring Boot 会自动从以下目录里找静态文件(按顺序):

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/ ✅ 最常见(即你项目里的 src/main/resources/static)
  • classpath:/public/

举个例子:
你把 src/main/resources/static/config.json 打包进 jar → 浏览器访问 http://localhost:8080/config.json 就能拿到。
这是因为 classpath:/static/ 在默认搜索路径里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94808.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94808.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何从三星手机转移到另一部三星手机

三星Galaxy S系列因其出色的设计、令人惊叹的显示屏、惊艳的摄像头、更好的扬声器以及创新的指纹传感器而受到大多数用户的欢迎&#xff0c;获得了良好的声誉。让用户感到满意的是&#xff0c;三星Galaxy S10拥有更美观的设计、令人惊叹的显示屏、令人惊叹的摄像头、更好的扬声…

聚焦建筑能源革新!安科瑞 “光储直柔” 方案护航碳中和目标实现

1、背景在 “双碳” 目标引领下&#xff0c;能源结构转型与建筑能效提升成为重要课题。清华大学江亿院士提出的 “光储直柔” 新型配电系统&#xff0c;为建筑领域绿色发展提供了创新方向。光储直柔得到了业界广泛认同和积极响应&#xff0c;国家、各部委、地区陆续出台相关政策…

Shell 中 ()、(())、[]、{} 的用法详解

文章目录Shell 中 ()、(())、[]、{} 的用法详解一、先明确&#xff1a;四类符号的核心功能定位二、逐个拆解&#xff1a;用法、示例与避坑点1. ()&#xff1a;子 Shell 执行&#xff0c;隔离环境核心用法1&#xff1a;子 Shell 执行命令&#xff0c;隔离变量核心用法2&#xff…

开发避坑指南(41):Vue3 提示框proxy.$modal.msgSuccess()提示文本换行解决方案

需求 由于接口返回的提示信息过长&#xff0c;接口已经在返回提示中加入换行标签了&#xff0c;但是使用proxy.modal.msgSuccess(res.msg)提示没有换行&#xff0c;那么Vue3中proxy.modal.msgSuccess(res.msg)提示没有换行&#xff0c;那么Vue3 中 proxy.modal.msgSuccess(res.…

[Sync_ai_vid] 唇形同步推理流程 | Whisper架构

链接&#xff1a;https://github.com/bytedance/LatentSync/blob/main/docs/syncnet_arch.md docs&#xff1a;LatentSync LatentSync是一个端到端唇语同步项目&#xff0c;能够生成语音与唇形完美匹配的逼真视频。 该项目通过使用*音频条件化3D U-Net*&#xff08;一种生成式…

uniapp中 ios端 scroll-view 组件内部子元素z-index失效问题

发现子组件中的弹窗在ios手机上会被限制在scroll-view里面&#xff0c;安卓手机上不受限制&#xff0c;网上找了好久原因 scroll-view组件内部设置了 -webkit-overflow-scrolling: touch 样式&#xff0c;导致z-index失效&#xff08;safari 3D变换会忽略z-index的层级问题&…

PyTorch图像预处理完全指南:从基础操作到GPU加速实战

引言 图像预处理是模型性能的"隐形基石"&#xff0c;在计算机视觉任务中直接决定模型能否提取有效特征。科学的预处理流程能让基础模型性能提升15%以上&#xff0c;而GPU加速预处理可使数据准备阶段耗时降低60%以上。本文将聚焦PyTorch预处理核心技术&#xff0c;从基…

【前端教程】 CSS浮动布局解析与优化:从基础实现到工程化改进

浮动(float)是CSS中实现页面布局的经典技术,虽然现代布局更多使用Flexbox和Grid,但理解浮动的工作原理仍是前端开发者的基础素养。本文以一个三栏浮动布局的代码为例,从布局原理解析、潜在问题诊断、工程化优化三个维度,带你深入理解浮动布局的精髓与优化思路。 一、原代…

DVWA靶场通关笔记-暴力破解(Impossible级别)

目录 一、查看源码 二、功能分析 三、SQL注入分析 1、使用PDO预处理语句和参数绑定 2、mysqli_real_escape_string转义 3、stripslashes去除反斜杠 四、暴力破解分析 1、token防止暴力破解机制 2、登录失败随机延迟机制 3、登陆失败报错信息相同 4、登陆失败的账户…

IAR工程如何生成compile_commands.json文件(能生成但是clangd不能生成“.cache文件”)

最近一直在使用vscodeclangd的方式编写代码&#xff0c;感觉使用clangd查找函数调用、函数声明、类型定义等等都比使用vscode自带的c/c插件好用太多了。现在我有一个功能是IAR版本的&#xff0c;那么有没有办法生成clangd使用的compile_commands.json文件呢&#xff1f;答案是&…

QT5.14.2、CMake 扩展openCV

一、准备工具Qt5.14.2c11cmake3.24.0opencv3.4.16二、使用cmake可扩展opencv 首先解压cmake、opencv 两个下载的压缩包&#xff0c;如下&#xff1a;运行cmake-gui.exe打开后有弹窗选择&#xff0c;然后进入QT的安装路径下找 mingw73_64文件下的 C和C的执行文件这个截图是我扩展…

【3D入门-指标篇下】 3D重建评估指标对比-附实现代码

3D重建评估指标对比表 每个指标的具体代码位于文章末尾指标计算方法数值范围评估重点优缺点适用场景Chamfer Distance (C1)从预测网格到真实网格的平均距离[0, ∞)几何形状准确性优点&#xff1a;直观、计算高效缺点&#xff1a;对噪声敏感整体形状评估Chamfer Distance (C2)从…

香港电讯创新解决方案,开启企业数字化转型新篇章

在数字化浪潮席卷全球的今天&#xff0c;企业正加速突破传统办公和业务模式的桎梏&#xff0c;力求通过高效协同与业务创新实现跨越式发展。香港电讯作为科技解决方案提供商&#xff0c;持续推动技术创新应用。近期&#xff0c;香港电讯通过多项创新应用、产品升级及战略合作&a…

数据分析编程第六步:大数据运算

6.1 数据介绍直接打开集算器运行 createEventsAndUsers.splx 文件&#xff0c;就可以得到如下两张表&#xff08;也可以根据代码中的注释&#xff0c;修改起止日期以及每天的数据量&#xff09;&#xff1a;电商数据表 events.csv字段名含义eventID事件编号, 从 1 开始流水号us…

vue2+elementui 表格单元格增加背景色,根据每列数据的大小 颜色依次变浅显示2

注意&#xff1a; 正数前5和负数后5的颜色是固定的&#xff0c;剩下5之后的数据颜色是根据第5个颜色依次变浅的&#xff1b; 封装的js方法&#xff1a; /*** 最终版表格颜色处理器* param {Array} data 完整表格数据* param {String} field 当前字段名* param {Object} row 当前…

【AOSP】Android Dump 开发与调试指南

在 Android 系统开发与调试中&#xff0c;dump 是一个不可或缺的强大工具。它能够提供关于系统服务、应用程序状态以及底层硬件信息的详细快照。对于希望深入了解 Android 系统内部工作原理、排查复杂问题或进行性能优化的开发者来说&#xff0c;掌握 dump 的使用至关重要。一、…

Qt数据结构与编码技巧全解析

文章目录Qt中的数据结构QDebugqDebug函数QT的内置类型一般都会重载 << 运算符QT的几何规则QString 字符串编码变长 VS 定长QString 适合中转数据吗&#xff1f;Qstring 的底层使用写时复制QString的具体使用QString 的构造函数格式化构造数值转化为字符串字符串转成数值增…

Ubuntu操作系统下MySQL、MongoDB、Redis

在开发和运维过程中&#xff0c;经常需要从Windows客户端远程连接到Ubuntu服务器上的数据库。本文将详细介绍如何在Ubuntu操作系统下安装和配置MySQL、MongoDB和Redis&#xff0c;以允许从Windows客户端进行远程连接&#xff0c;并提供详细的远程连接命令和配置说明。一、MySQL…

校园勤工俭学微信小程序的设计与实现:基于数字化服务生态的赋能体系构建

在高等教育普及化与数字化校园建设的双重驱动下&#xff0c;传统校园勤工俭学管理模式正面临深刻变革。当前高校勤工俭学工作普遍存在岗位匹配效率低下、过程管理粗放、数据孤岛严重等痛点——根据教育部全国学生资助管理中心2022年统计数据&#xff0c;全国普通高校共有约450万…

Apisix工作流程

是的,你的理解基本正确:当请求到达APISIX时,它会先根据请求的URI、Host、请求方法、 headers等信息匹配最合适的路由,然后执行路由关联的插件逻辑,最后转发到路由配置的上游服务。下面详细讲解APISIX处理请求的全链路及可能的情况。 一、请求全链路流程 APISIX处理请求的…