【问题标题】:Build once and deploy build file in multiple environments with minimal changes React and Webpack一次构建并在多个环境中部署构建文件,只需最少的更改 React 和 Webpack
【发布时间】:2018-04-04 11:34:10
【问题描述】:

在 webpack.config 文件中声明了一个要在应用程序中读取的变量。

let BASEURL = "http://127.0.0.1:8090";

使用这种方法,我无法在npm run build 之后更新 BASEURL。如果 BASEURL 发生变化,每次我想为每个环境生成一个新版本。

有没有什么方法可以一次构建并在多个环境中部署构建文件而只需进行最少的更改?

【问题讨论】:

  • 认为您应该在 index.js 或正在构建的代码库中的任何文件中执行此操作,并且您可以使用 process.env.ENV_VARIABLE 进行任何您想要的检查。跨度>
  • 构建后我需要解决方案。所以同一个构建可以在多个环境中使用

标签: reactjs webpack deployment build


【解决方案1】:

Tl;dr:使用 AJAX 并在反应上下文或全局变量中进行配置。


详细解答:

确实如您所说,使用npm run build构建应用程序后,环境变量变为硬连线,无法更改。

create-react-app的官方声明是支持一次构建部署多次的原则。来自https://create-react-app.dev/docs/adding-custom-environment-variables/

环境变量在构建时嵌入。由于 Create React App 生成一个静态 HTML/CSS/JS 包,它不可能在运行时读取它们。

不过,实现原理是有方法的,只是稍微复杂一点。这个想法是,您需要在运行时从外部源获取变量的值,例如阿贾克斯。更详细地说,可能的解决方案可能是(但不限于)以下:

1。服务器端占位符替换

这是create-react-apphttps://create-react-app.dev/docs/title-and-meta-tags/#injecting-data-from-the-server-into-the-page 中提出的解决方案,引入了一个自定义占位符,并在呈现给客户端之前将其替换为服务器上的数据

<!doctype html>
<html lang="en">
  <head>
    <script>
      window.SERVER_DATA = __SERVER_DATA__;
    </script>

虽然这可行,但它会带来很大的开销,因为它将整个后端实现留给您。根据您的技术堆栈,这可能非常容易实现,也可能非常复杂。

2。分配变量值的动态&lt;script&gt;

https://www.cotyhamilton.com/build-once-deploy-anywhere-for-react-applications/ 中提出的解决方案利用了 javascript 的动态特性。在动态下载的config.js 文件中,为变量分配了一个值。在其余的 React 代码中,变量被读取和使用。您可以随时更改config.js 文件,无需重新编译react 应用。

// public/config.js

const apiUrl = 'localhost:1337';
const env = 'development';
<!-- public/index.html -->

<script src="%PUBLIC_URL%/config.js"></script>
<script>
  window.config = { apiUrl, env };
</script>

主要的缺点是它不支持 TypeScript,你的 IDE 或 linter 可能会抱怨 apiUrlenv 没有定义。尤其是在较大的项目中,这种方法可能难以维护。

3。使用 AJAX 进行动态配置,支持 TypeScript

基于第二个解决方案,本文https://profinit.eu/en/blog/build-once-deploy-many-in-react-dynamic-configuration-properties/ 非常详细地描述了如何使用create-react-app 最好地实现一次构建部署多次 原则以及优缺点。

它建议使用 AJAX 将动态配置下载为 JSON。主要的警告是确保在一些代码轮胎使用它之前下载动态配置。在 React 生命周期的上下文中,有两种方法可以实现这一点。

3.1 全局变量

globalConfigUrl 下载动态配置 JSON,将其存储在全局变量中,然后才渲染 React 应用程序。 TypeScript 中的示例:

// index.tsx:
import axios from "axios";
import React, {ReactElement} from "react";
import App from "./App";
import {globalConfig, globalConfigUrl} from "./configuration/config";

axios.get(globalConfigUrl)
  .then((response) => {
    globalConfig.config = response.data; // THIS IS THE IMPORTANT LINE
    return <App />;
  })
  .catch(e => {
      return <p style={{color: "red", textAlign: "center"}}>Error while fetching global config</p>;
  })
  .then((reactElement: ReactElement) => {
    ReactDOM.render(
      reactElement,
      document.getElementById("root")
    );
  });

完整的工作示例:https://codesandbox.io/s/build-once-deploy-many-global-config-object-dvpzr

3.2.反应上下文

使用包含配置的反应上下文提供程序包装您的&lt;App&gt; 组件(使用undefined 或一些默认值)。首次呈现 App 时获取配置,然后将其值保存到上下文中。 React 会处理剩下的事情并传播值的变化!

完整的工作示例:https://codesandbox.io/s/build-once-deploy-many-react-context-7lk7g

基本思想是这样的。查看上面的文章/工作示例以了解所有详细信息:

// App.tsx
import {useConfig} from "./configuration/useConfig";

// ... in the method: 
  const { setConfig } = useConfig(); // the `useConfig` is a custom hook, wrapping a React context. See the full working example for all details
  useEffect(() => {
    axios
      .get(dynamicConfigUrl)
      .then((response) => {
        setConfig(response.data);
      })
  }, [setConfig]);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 2020-11-05
    • 2019-10-05
    • 2014-02-15
    • 1970-01-01
    相关资源
    最近更新 更多