在传统的前后端分离开发模式中,前端项目经常需要调用后端API接口。这些接口地址通常以硬编码形式直接写在业务代码里,比如:
javascript复制const apiUrl = 'http://api.example.com/v1/user'
这种写法在实际开发中会带来三个典型问题:
我最近接手的一个企业级中台项目就深受其害 - 每次测试环境部署都要全量打包20分钟,开发人员每天要浪费1小时在等待构建上。
通过将后端地址提取到外部配置文件,实现:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 环境变量(.env) | 原生支持,零配置 | 需重新打包生效 | 简单项目 |
| 外部JSON配置文件 | 完全解耦,动态加载 | 需处理异步加载 | 中大型项目 |
| 服务端动态下发 | 实时生效,集中管理 | 架构复杂,依赖网络 | 微服务架构 |
经过综合评估,我们选择JSON配置文件方案,因其:
在public目录下创建config.json:
json复制{
"apiBaseUrl": "https://api.example.com",
"authUrl": "https://auth.example.com",
"cdnUrl": "https://cdn.example.com"
}
重要提示:必须将配置文件放在public目录而非src目录,否则会被webpack打包
创建src/utils/config.js:
javascript复制let _config = {}
export const loadConfig = async () => {
const response = await fetch('/config.json')
_config = await response.json()
// 开发环境可打印验证
if (process.env.NODE_ENV === 'development') {
console.log('Loaded config:', _config)
}
}
export const getConfig = (key) => {
if (!_config.apiBaseUrl) {
throw new Error('Config not loaded! Call loadConfig() first')
}
return _config[key]
}
在应用入口文件(如main.js)中:
javascript复制import { loadConfig } from './utils/config'
loadConfig().then(() => {
ReactDOM.render(<App />, document.getElementById('root'))
})
原代码:
javascript复制axios.get('http://api.example.com/v1/user')
改造后:
javascript复制import { getConfig } from '../utils/config'
axios.get(`${getConfig('apiBaseUrl')}/v1/user`)
扩展config.json为动态加载:
json复制{
"development": {
"apiBaseUrl": "http://dev-api.example.com"
},
"production": {
"apiBaseUrl": "https://api.example.com"
}
}
修改加载逻辑:
javascript复制const env = process.env.NODE_ENV || 'development'
const response = await fetch('/config.json')
const allConfigs = await response.json()
_config = allConfigs[env]
为防止浏览器缓存旧配置,可在文件名中加入hash:
html复制<script>
const configUrl = `/config.${BUILD_HASH}.json`
fetch(configUrl).then(...)
</script>
创建src/types/config.d.ts:
typescript复制interface AppConfig {
apiBaseUrl: string
authUrl: string
cdnUrl: string
}
declare module '@/utils/config' {
export const getConfig: (key: keyof AppConfig) => string
}
在Dockerfile中实现多阶段配置注入:
dockerfile复制FROM nginx:alpine
# 构建阶段
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 运行时配置注入
COPY --from=build /app/dist /usr/share/nginx/html
COPY deploy/${ENV}/config.json /usr/share/nginx/html/config.json
.gitlab-ci.yml示例:
yaml复制deploy:
stage: deploy
script:
- cp deploy/$ENVIRONMENT/config.json public/config.json
- docker build --build-arg ENV=$ENVIRONMENT -t my-app .
- docker push my-app
现象:控制台报错"Config not loaded"
排查步骤:
解决方案:
nginx复制location /config.json {
add_header Access-Control-Allow-Origin *;
}
强制刷新方案:
javascript复制fetch(`/config.json?t=${Date.now()}`)
<link rel="preload" href="/config.json" as="fetch">经过三个月的生产环境验证,该方案使得: