如何将HTML中Google Maps API脚本移至JS文件并安全管理密钥
React 18 动态加载Google Maps API并隐藏密钥的实现方案
1. 配置环境变量
在项目根目录创建.env文件(务必把这个文件添加到.gitignore中,禁止提交到代码仓库),写入你的Google Maps API密钥:
REACT_APP_GOOGLE_MAPS_KEY=你的实际API密钥
React会自动识别并注入以REACT_APP_开头的环境变量,在代码中可通过process.env.REACT_APP_GOOGLE_MAPS_KEY直接访问。
2. 封装动态加载脚本的工具函数
创建一个独立的工具文件(比如utils/loadGoogleMaps.js),封装脚本加载逻辑,避免重复加载:
let mapsLoaded = false; let resolveMapsPromise; let rejectMapsPromise; // 用Promise跟踪脚本加载状态 const mapsPromise = new Promise((resolve, reject) => { resolveMapsPromise = resolve; rejectMapsPromise = reject; }); export function loadGoogleMaps() { if (mapsLoaded) { return mapsPromise; } mapsLoaded = true; const script = document.createElement('script'); script.type = 'text/javascript'; script.src = `https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_KEY}&libraries=places`; script.async = true; script.defer = true; script.onload = () => { resolveMapsPromise(window.google); }; script.onerror = (error) => { rejectMapsPromise(error); // 重置状态,支持后续重试 mapsLoaded = false; }; document.body.appendChild(script); return mapsPromise; }
3. 在组件中调用加载函数
在需要使用Google Maps的组件(比如MapComponent.jsx)中,等待脚本加载完成后初始化地图:
import { useEffect, useState } from 'react'; import { loadGoogleMaps } from '../utils/loadGoogleMaps'; export default function MapComponent() { const [map, setMap] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const initMap = async () => { try { const google = await loadGoogleMaps(); const mapElement = document.getElementById('map'); const newMap = new google.maps.Map(mapElement, { center: { lat: -34.397, lng: 150.644 }, zoom: 8, }); setMap(newMap); } catch (err) { setError(err); } finally { setLoading(false); } }; initMap(); }, []); if (loading) return <div>加载地图中...</div>; if (error) return <div>地图加载失败:{error.message}</div>; return <div id="map" style={{ width: '100%', height: '400px' }}></div>; }
4. 清理静态脚本
删除index.html中原来的Google Maps脚本标签,避免重复加载。
额外安全提示
- 除了隐藏密钥,建议在Google Cloud控制台给API密钥设置HTTP引用限制,仅允许你的域名调用,进一步降低泄露风险
- 如果多个组件需要使用地图,可以把加载逻辑放在App组件初始化阶段,或者用Context统一管理地图实例
内容的提问来源于stack exchange,提问作者John Glabb
相关产品推荐
相关产品推荐

