构建一次并在多个环境中部署构建文件,只需最少的更改 React 和 Webpack

Cha*_*ndu 5 deployment build reactjs webpack

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

let BASEURL = "http://127.0.0.1:8090";
Run Code Online (Sandbox Code Playgroud)

使用这种方法,我无法在npm run build. 每次我想为每个环境生成一个新的构建(如果 BASEURL 发生变化)。

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

小智 10

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

\n
\n

详细解答:

\n

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

\n

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

\n
\n

环境变量是在构建时嵌入的。由于 Create React App 生成静态 HTML/CSS/JS 包,因此它可能无法在运行时读取它们。

\n
\n

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

\n

1.服务端占位符替换

\n

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

\n
<!doctype html>\n<html lang="en">\n  <head>\n    <script>\n      window.SERVER_DATA = __SERVER_DATA__;\n    </script>\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

<script>2.分配变量值的动态

\n

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

\n
// public/config.js\n\nconst apiUrl = \'localhost:1337\';\nconst env = \'development\';\n
Run Code Online (Sandbox Code Playgroud)\n
<!-- public/index.html -->\n\n<script src="%PUBLIC_URL%/config.js"></script>\n<script>\n  window.config = { apiUrl, env };\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n

主要缺点是它不支持 TypeScript,并且您的 IDE 或 linter 可能会抱怨apiUrlenv未定义。特别是在较大的项目中,这种方法可能很难维护。

\n

3. 使用 AJAX 动态配置,支持 TypeScript

\n

基于第二种解决方案,本文https://profinit.eu/en/blog/build-once-deploy-many-in-react-dynamic-configuration-properties/详细描述了如何最好地实现一次构建部署许多原则create-react-app,各有利弊。

\n

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

\n

3.1 全局变量

\n

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

\n
// public/config.js\n\nconst apiUrl = \'localhost:1337\';\nconst env = \'development\';\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

3.2. 反应上下文

\n

<App>使用包含配置(带有或某些默认值)的反应上下文提供程序包装您的组件undefined。第一次渲染时获取配置App,然后将其值保存到上下文中。React 将处理剩下的事情并传播值的变化!

\n

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

\n

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

\n
<!-- public/index.html -->\n\n<script src="%PUBLIC_URL%/config.js"></script>\n<script>\n  window.config = { apiUrl, env };\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n