【问题标题】:How should I configure create-react-app to serve app from subdirectory?我应该如何配置 create-react-app 以从子目录提供应用程序?
【发布时间】:2018-08-31 23:08:48
【问题描述】:

我在服务器上呈现了经典的 Web 应用程序。我想在 React 中创建管理面板作为单页应用程序。我想从https://smyapp.example.com/admin/ 服务器管理面板。我尝试使用create-react-app,但它假定我从根 URL 提供 SPA。我应该如何配置create-react-app 以从"admin" 子目录提供应用程序?在文档中,我找到了 "homepage" 属性,但如果我正确理解它需要完整的 url。我无法提供完整的网址,因为我的应用部署在少数环境中。

【问题讨论】:

  • 您能否详细说明“我无法提供完整的 url,因为我的应用程序部署在少数环境中”?
  • @GabrielBleu 在文档中我发现类似“主页”:“mywebsite.com/subdirectory”,但我不想在这里给出完整的域名。
  • 由于路由可以由routerbasename处理,我认为这个url只用于bundle,也许你可以链接到一个共享的,比如statics.mywebsites.com

标签: reactjs webpack single-page-application create-react-app


【解决方案1】:

除了您的要求,我还添加了我的:

  • 应该由 CD 通过一个环境变量来完成。
  • 如果我需要重命名子目录,我应该只需要更改 env 变量。
  • 它应该与 react-router 一起使用。
  • 它应该适用于 scss (sass) 和 html。
  • 一切都应该在开发模式下正常工作(npm start)。

不久前我还必须在 Angular2+ 项目中实现它,我发现在 React 中实现它比在 Angular2+ 中实现它更难,你可以使用 ng build --base-href /<project_name>/source


短版

  1. 在构建之前,将PUBLIC_URL 环境变量设置为您的子目录的值,例如使用/subdir。您也可以将此变量放入您的.env.production (in case you do not have that file you can check the doc)
  2. public/index.html 中添加下面的基本元素,这是用于图像等静态文件的。
<base href="%PUBLIC_URL%/">
  1. 同样在public/index.html 中,如果您有自定义link 元素,请确保它们以%PUBLIC_URL% 为前缀(如manifest.jsonfavicon.ico href)。
  2. 如果你使用BrowserRouter,可以添加basename prop:
<BrowserRouter basename={process.env.PUBLIC_URL} />
  1. 如果您改用Router,因为您需要访问history.push 方法,以编程方式更改页面,请执行以下操作:
// history.tsx
import {createBrowserHistory} from 'history';

export default createBrowserHistory({ basename: process.env.PUBLIC_URL });
<!-- Where your router is, for me, App.tsx -->
<Router history={history}>
  ...
</Router>
  1. 在元素中使用相对链接
<!-- "./assets/quotes.png" is also ok, but "/assets/quotes.png" is not -->
<img src="assets/quotes.png" alt="" />
  1. 将您的 background-image 链接从 scss 移动到 jsx/tsx 文件(请注意,如果您使用 css 文件,则可能不需要这样做):
/*remove that*/
background-image: url('/assets/background-form.jpg');
<section style={{backgroundImage: `url('assets/background-form.jpg')`}}>
...

你应该完成了。


其他信息

我更喜欢在package.json 中使用PUBLIC_URL 而不是homepage,因为我想使用在gitlab 上设置的环境变量来设置子目录。关于该主题的相关资源:

PUBLIC_URL 覆盖homepagePUBLIC_URL 也取域名,如果你提供的话。如果只设置homepagePUBLIC_URL 将设置为homepage 的值。


如果您不想在 index.html 中使用基本元素(我不知道为什么),您需要自己将 process.env.PUBLIC_URL 附加到每个链接。请注意,如果您有带有基本元素的 react-router,但尚未设置 basename 属性,您将收到警告。


Sass 不会使用不正确的相对路径进行编译。它也不会以正确的相对路径编译到您的../public/assets 文件夹,因为ModuleScopePlugin 的限制,您可以通过将图像移动到 src 文件夹中来避免限制,我没有尝试过。


似乎无法在开发模式下测试相对路径(npm start)。 see comment


最后,这些stackoverflow链接有相关问题:

【讨论】:

  • 这应该是公认的答案。使用环境变量比 package.json 好很多
  • 这在开发中对我来说很好,但在生产中却不行。我有一个奇怪的设置,但我无法从 / 提供服务,这可能会弄乱静态/资产文件。
  • 使用 .env 文件实际上是在开发和生产环境中轻松运行应用程序的一个很好的建议
  • 感谢您的详细回答,但我真的不认为这是一个“短”版本!
【解决方案2】:

对于 create-react-app v2 和 react-router v4,我使用以下组合在“/app”下为生产(暂存、uat 等)应用提供服务:

package.json:

"homepage": "/app"

然后在app入口点:

 <BrowserRouter basename={process.env.PUBLIC_URL}>
  {/* other components */}
 </BrowserRouter>

在本地开发和部署环境中,一切都“正常工作”。 HTH!

【讨论】:

  • DRY 怎么样(不要重复自己)?在这种情况下,您的公共网址在两个地方..
【解决方案3】:

您应该为此在package.json 添加条目。

在你的 package.json 中添加一个键 "homepage": "your-subfolder/" 所有静态文件都将从“您的子文件夹”加载

如果没有子文件夹并且您需要从同一文件夹加载,则需要将路径添加为“./”或删除具有"homepage": "xxxxxxxxxx" 的整行

"homepage": "./"

来自官方文档

默认情况下,假设您的应用托管在服务器根目录下,Create React App 会生成一个构建。 要覆盖它,请在 package.json 中指定主页,例如:

“主页”:“http://mywebsite.com/relativepath”,

注意:如果您使用react-router@^4,您可以使用任何&lt;Router&gt; 上的basename 属性路由&lt;Link&gt;s。

来自here 并查看official CRA docs

【讨论】:

  • 花了一整天的时间来部署一个 CRA 构建,终于找到了解决方案——感谢这个答案!
【解决方案4】:

要获取相对 URL,您可以像这样构建应用程序:

PUBLIC_URL="." npm run build

【讨论】:

    【解决方案5】:

    也许您可以使用react-router 及其relative basename 参数,它允许您从子目录中为您的应用程序提供服务。

    basename 是所有位置的基本 URL。如果您的应用程序是从服务器上的子目录提供的,您需要将其设置为子目录。格式正确的基本名称应该有一个前导斜杠,但没有尾随斜杠。

    例如:

    <BrowserRouter basename="/calendar"/>
    

    所以&lt;Link to="/today"/&gt; 将渲染&lt;a href="/calendar/today"&gt;

    见:https://reacttraining.com/react-router/web/api/BrowserRouter/basename-string

    【讨论】:

      【解决方案6】:

      在 package.json 中加入如下内容:

      “主页”:“http://localhost:3000/subfolder”,

      并且可以在任何公共或本地服务器上正常工作。当然,子文件夹必须是您的文件夹。

      【讨论】:

      • create-react-app 中的图像和其他资产是否也会从该文件夹中提供?
      • 这不会发生在我身上,我被困在试图从子目录中获取资产
      【解决方案7】:

      您可以在 webpack 配置中指定公共路径以及使用 react route basepath。

      公共路径链接:https://webpack.js.org/guides/public-path/

      请注意,公共路径的前导和尾随斜杠 / 都是有效的。

      【讨论】:

        猜你喜欢
        • 2018-07-07
        • 1970-01-01
        • 2019-06-13
        • 2020-03-23
        • 2012-09-08
        • 2020-10-08
        • 2018-05-15
        • 2020-10-21
        • 2022-01-17
        相关资源
        最近更新 更多