# react 使用 window 全局变量

  • 先通过create-react-app构建 react 项目
  • 安装axios
  • 使用的 IED 是 vscode

# 需求描述

业务项目中,需要给项目配置一些特殊的变量,例如:api接口地址,静态资源的外网路径,某些外网的关联链接地址.而这些变量可能会在打包之后修改(业务代码不变).通常由运维人员直接在打包好的代码里修改.

# 要解决的问题

  • 在打包后的项目中定义配置文件,供运维人员修改
  • 需要在配置文件加载后(无论是否成功),然后再挂载app,避免因加载延迟导致后续获取变量错误
  • 使用变量的时候,可以智能提示相关的变量定义(IDE提示功能)

# step 1 配置文件

默认在public文件夹中添加config.json

// /public/config.json

{
  "PRODUCTION_ORIGIN": "http://www.abc.com",
  "PRODUCTION_API_URL": "http://www.abc.com/test/api"
}

# step 2 定义获取配置的工具函数

// /src/utils/app-config.js

import axios from "axios";

// 用来定义配置项的文件(放到'public'中)
const CONFIG_FILE_PATH = "/config.json";

// 默认配置
const DEFAULT_APP_CONFIG = {
  PRODUCTION_ORIGIN: "",
  PRODUCTION_API_URL: "",
};

// 注入指定的项目配置到window全局变量
async function injectAppConfig(callback) {
  // 先给window注入默认的配置
  window.AppConfig = DEFAULT_APP_CONFIG;
  try {
    // timestamp是为了防止浏览器缓存,导致修改'config.json'后没有刷新
    const { data } = await axios.get(
      process.env.PUBLIC_URL + CONFIG_FILE_PATH,
      { timestamp: Date.now() }
    );
    // 修改
    window.AppConfig = Object.assign({}, DEFAULT_APP_CONFIG, data);
  } catch (err) {
    console.error("获取 app-config 失败\n", err);
  }

  if (typeof callback === "function") {
    callback();
  }
}

export default injectAppConfig;

# step 3 引用注入工具函数

把原来的挂载函数使用injectAppConfig替换

// /src/index.js
import injectAppConfig from "@/utils/app-config";

injectAppConfig(() => {
  ReactDOM.render(<App />, document.getElementById("root"));
});

# step 4 使用

// src/App.js

function App() {
  return (
    <>
      <h1>Home Page</h1>
      <p>{window.AppConfig.PRODUCTION_ORIGIN}</p>
      <p>{window.AppConfig.PRODUCTION_API_URL}</p>
    </>
  );
}

# 如何让 IDE 智能提示

这里使用的 IDE 是 vscode

在项目的根目录添加文件夹typings,然后在里面再添加global.d.ts.

// /typings/global.d.ts

interface IAppConfig {
  PRODUCTION_ORIGIN: string;
  PRODUCTION_API_URL: string;
}

interface Window {
  AppConfig: IAppConfig;
}

这样就可以在写代码时获得提示: dock

Last Updated: 3/11/2021, 12:10:19 PM